mindcache 3.4.0 → 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.
@@ -8,17 +8,13 @@ import * as Y from 'yjs';
8
8
  type AccessLevel = 'user' | 'system';
9
9
  /**
10
10
  * Known system tags that control key behavior
11
- * - 'SystemPrompt': Include in system prompt
12
- * - 'LLMRead': LLM can read this key (visible to LLMs)
11
+ * - 'SystemPrompt': Include in system prompt (visible to LLM context)
12
+ * - 'LLMRead': LLM can read this key via tools
13
13
  * - 'LLMWrite': LLM can write to this key via tools
14
- * - 'protected': Cannot be deleted (replaces hardcoded)
14
+ * - 'protected': Cannot be deleted
15
15
  * - 'ApplyTemplate': Process value through template injection
16
- *
17
- * @deprecated 'prompt' - Use 'SystemPrompt' instead
18
- * @deprecated 'readonly' - Use absence of 'LLMWrite' instead (if LLMWrite not present, readonly=true)
19
- * @deprecated 'template' - Use 'ApplyTemplate' instead
20
16
  */
21
- type SystemTag = 'SystemPrompt' | 'LLMRead' | 'LLMWrite' | 'protected' | 'ApplyTemplate' | 'prompt' | 'readonly' | 'template';
17
+ type SystemTag = 'SystemPrompt' | 'LLMRead' | 'LLMWrite' | 'protected' | 'ApplyTemplate';
22
18
  /**
23
19
  * Type of value stored in a MindCache key
24
20
  */
@@ -37,17 +33,11 @@ interface KeyAttributes {
37
33
  systemTags: SystemTag[];
38
34
  /** Z-index for ordering keys (lower values appear first) */
39
35
  zIndex: number;
40
- /** @deprecated Use !systemTags.includes('LLMWrite') instead */
41
- readonly: boolean;
42
- /** @deprecated Use systemTags.includes('SystemPrompt') instead */
43
- visible: boolean;
44
- /** @deprecated Use systemTags.includes('protected') instead */
45
- hardcoded: boolean;
46
- /** @deprecated Use systemTags.includes('ApplyTemplate') instead */
47
- template: boolean;
48
- /** @deprecated Use contentTags instead */
49
- tags?: string[];
50
36
  }
37
+ /**
38
+ * Default attributes for new keys
39
+ */
40
+ declare const DEFAULT_KEY_ATTRIBUTES: KeyAttributes;
51
41
  /**
52
42
  * A single entry in the MindCache store
53
43
  */
@@ -71,10 +61,6 @@ type Listener = (value: unknown) => void;
71
61
  * Called when any key changes (no parameters - use getAll() to get current state)
72
62
  */
73
63
  type GlobalListener = () => void;
74
- /**
75
- * Default attributes for new keys
76
- */
77
- declare const DEFAULT_KEY_ATTRIBUTES: KeyAttributes;
78
64
  /**
79
65
  * A single entry in the global history log
80
66
  */
@@ -95,6 +81,21 @@ interface HistoryOptions {
95
81
  /** Save full snapshot every N entries for fast restore (default: 10) */
96
82
  snapshotInterval?: number;
97
83
  }
84
+ /**
85
+ * Helper functions for working with system tags
86
+ */
87
+ declare const SystemTagHelpers: {
88
+ /** Check if key is writable by LLM */
89
+ isLLMWritable: (attrs: KeyAttributes) => boolean;
90
+ /** Check if key is readable by LLM (in context or via tools) */
91
+ isLLMReadable: (attrs: KeyAttributes) => boolean;
92
+ /** Check if key is included in system prompt */
93
+ isInSystemPrompt: (attrs: KeyAttributes) => boolean;
94
+ /** Check if key is protected from deletion */
95
+ isProtected: (attrs: KeyAttributes) => boolean;
96
+ /** Check if key uses template injection */
97
+ hasTemplateInjection: (attrs: KeyAttributes) => boolean;
98
+ };
98
99
 
99
100
  /**
100
101
  * Cloud configuration options for MindCache constructor
@@ -143,7 +144,6 @@ declare class MindCache {
143
144
  private listeners;
144
145
  private globalListeners;
145
146
  readonly version = "3.3.2";
146
- private _isRemoteUpdate;
147
147
  private normalizeSystemTags;
148
148
  private _cloudAdapter;
149
149
  private _connectionState;
@@ -219,7 +219,6 @@ declare class MindCache {
219
219
  get isOnline(): boolean;
220
220
  waitForSync(): Promise<void>;
221
221
  disconnect(): void;
222
- isRemoteUpdate(): boolean;
223
222
  serialize(): STM;
224
223
  deserialize(data: STM): void;
225
224
  private encodeFileToBase64;
@@ -247,6 +246,16 @@ declare class MindCache {
247
246
  */
248
247
  set_attributes(key: string, attributes: Partial<KeyAttributes>): void;
249
248
  set_value(key: string, value: any, attributes?: Partial<KeyAttributes>): void;
249
+ /**
250
+ * LLM-safe method to write a value to a key.
251
+ * This method:
252
+ * - Only updates the value, never modifies attributes/systemTags
253
+ * - Checks LLMWrite permission before writing
254
+ * - Returns false if key doesn't exist or lacks LLMWrite permission
255
+ *
256
+ * Used by create_vercel_ai_tools() to prevent LLMs from escalating privileges.
257
+ */
258
+ llm_set_key(key: string, value: any): boolean;
250
259
  delete_key(key: string): void;
251
260
  clear(): void;
252
261
  /**
@@ -429,6 +438,14 @@ declare class MindCache {
429
438
  /**
430
439
  * Generate Vercel AI SDK compatible tools for writable keys.
431
440
  * For document type keys, generates additional tools: append_, insert_, edit_
441
+ *
442
+ * Security: All tools use llm_set_key internally which:
443
+ * - Only modifies VALUES, never attributes/systemTags
444
+ * - Prevents LLMs from escalating privileges
445
+ */
446
+ create_vercel_ai_tools(): Record<string, any>;
447
+ /**
448
+ * @deprecated Use create_vercel_ai_tools() instead
432
449
  */
433
450
  get_aisdk_tools(): Record<string, any>;
434
451
  /**
@@ -532,4 +549,4 @@ declare class CloudAdapter {
532
549
  private scheduleReconnect;
533
550
  }
534
551
 
535
- export { type AccessLevel as A, CloudAdapter as C, DEFAULT_KEY_ATTRIBUTES as D, type GlobalListener as G, type HistoryEntry as H, type KeyAttributes as K, type Listener as L, MindCache as M, type Operation as O, type SystemTag as S, type MindCacheOptions as a, type KeyType as b, type STM as c, type STMEntry as d, type HistoryOptions as e, type MindCacheCloudOptions as f, type MindCacheIndexedDBOptions as g, type CloudConfig as h, type ConnectionState as i, type CloudAdapterEvents as j, type SetOperation as k, type DeleteOperation as l, type ClearOperation as m };
552
+ export { type AccessLevel as A, CloudAdapter as C, DEFAULT_KEY_ATTRIBUTES as D, type GlobalListener as G, type HistoryEntry as H, type KeyAttributes as K, type Listener as L, MindCache as M, type Operation as O, type SystemTag as S, type MindCacheOptions as a, type KeyType as b, type STM as c, type STMEntry as d, type HistoryOptions as e, type MindCacheCloudOptions as f, type MindCacheIndexedDBOptions as g, SystemTagHelpers as h, type CloudConfig as i, type ConnectionState as j, type CloudAdapterEvents as k, type SetOperation as l, type DeleteOperation as m, type ClearOperation as n };
@@ -8,17 +8,13 @@ import * as Y from 'yjs';
8
8
  type AccessLevel = 'user' | 'system';
9
9
  /**
10
10
  * Known system tags that control key behavior
11
- * - 'SystemPrompt': Include in system prompt
12
- * - 'LLMRead': LLM can read this key (visible to LLMs)
11
+ * - 'SystemPrompt': Include in system prompt (visible to LLM context)
12
+ * - 'LLMRead': LLM can read this key via tools
13
13
  * - 'LLMWrite': LLM can write to this key via tools
14
- * - 'protected': Cannot be deleted (replaces hardcoded)
14
+ * - 'protected': Cannot be deleted
15
15
  * - 'ApplyTemplate': Process value through template injection
16
- *
17
- * @deprecated 'prompt' - Use 'SystemPrompt' instead
18
- * @deprecated 'readonly' - Use absence of 'LLMWrite' instead (if LLMWrite not present, readonly=true)
19
- * @deprecated 'template' - Use 'ApplyTemplate' instead
20
16
  */
21
- type SystemTag = 'SystemPrompt' | 'LLMRead' | 'LLMWrite' | 'protected' | 'ApplyTemplate' | 'prompt' | 'readonly' | 'template';
17
+ type SystemTag = 'SystemPrompt' | 'LLMRead' | 'LLMWrite' | 'protected' | 'ApplyTemplate';
22
18
  /**
23
19
  * Type of value stored in a MindCache key
24
20
  */
@@ -37,17 +33,11 @@ interface KeyAttributes {
37
33
  systemTags: SystemTag[];
38
34
  /** Z-index for ordering keys (lower values appear first) */
39
35
  zIndex: number;
40
- /** @deprecated Use !systemTags.includes('LLMWrite') instead */
41
- readonly: boolean;
42
- /** @deprecated Use systemTags.includes('SystemPrompt') instead */
43
- visible: boolean;
44
- /** @deprecated Use systemTags.includes('protected') instead */
45
- hardcoded: boolean;
46
- /** @deprecated Use systemTags.includes('ApplyTemplate') instead */
47
- template: boolean;
48
- /** @deprecated Use contentTags instead */
49
- tags?: string[];
50
36
  }
37
+ /**
38
+ * Default attributes for new keys
39
+ */
40
+ declare const DEFAULT_KEY_ATTRIBUTES: KeyAttributes;
51
41
  /**
52
42
  * A single entry in the MindCache store
53
43
  */
@@ -71,10 +61,6 @@ type Listener = (value: unknown) => void;
71
61
  * Called when any key changes (no parameters - use getAll() to get current state)
72
62
  */
73
63
  type GlobalListener = () => void;
74
- /**
75
- * Default attributes for new keys
76
- */
77
- declare const DEFAULT_KEY_ATTRIBUTES: KeyAttributes;
78
64
  /**
79
65
  * A single entry in the global history log
80
66
  */
@@ -95,6 +81,21 @@ interface HistoryOptions {
95
81
  /** Save full snapshot every N entries for fast restore (default: 10) */
96
82
  snapshotInterval?: number;
97
83
  }
84
+ /**
85
+ * Helper functions for working with system tags
86
+ */
87
+ declare const SystemTagHelpers: {
88
+ /** Check if key is writable by LLM */
89
+ isLLMWritable: (attrs: KeyAttributes) => boolean;
90
+ /** Check if key is readable by LLM (in context or via tools) */
91
+ isLLMReadable: (attrs: KeyAttributes) => boolean;
92
+ /** Check if key is included in system prompt */
93
+ isInSystemPrompt: (attrs: KeyAttributes) => boolean;
94
+ /** Check if key is protected from deletion */
95
+ isProtected: (attrs: KeyAttributes) => boolean;
96
+ /** Check if key uses template injection */
97
+ hasTemplateInjection: (attrs: KeyAttributes) => boolean;
98
+ };
98
99
 
99
100
  /**
100
101
  * Cloud configuration options for MindCache constructor
@@ -143,7 +144,6 @@ declare class MindCache {
143
144
  private listeners;
144
145
  private globalListeners;
145
146
  readonly version = "3.3.2";
146
- private _isRemoteUpdate;
147
147
  private normalizeSystemTags;
148
148
  private _cloudAdapter;
149
149
  private _connectionState;
@@ -219,7 +219,6 @@ declare class MindCache {
219
219
  get isOnline(): boolean;
220
220
  waitForSync(): Promise<void>;
221
221
  disconnect(): void;
222
- isRemoteUpdate(): boolean;
223
222
  serialize(): STM;
224
223
  deserialize(data: STM): void;
225
224
  private encodeFileToBase64;
@@ -247,6 +246,16 @@ declare class MindCache {
247
246
  */
248
247
  set_attributes(key: string, attributes: Partial<KeyAttributes>): void;
249
248
  set_value(key: string, value: any, attributes?: Partial<KeyAttributes>): void;
249
+ /**
250
+ * LLM-safe method to write a value to a key.
251
+ * This method:
252
+ * - Only updates the value, never modifies attributes/systemTags
253
+ * - Checks LLMWrite permission before writing
254
+ * - Returns false if key doesn't exist or lacks LLMWrite permission
255
+ *
256
+ * Used by create_vercel_ai_tools() to prevent LLMs from escalating privileges.
257
+ */
258
+ llm_set_key(key: string, value: any): boolean;
250
259
  delete_key(key: string): void;
251
260
  clear(): void;
252
261
  /**
@@ -429,6 +438,14 @@ declare class MindCache {
429
438
  /**
430
439
  * Generate Vercel AI SDK compatible tools for writable keys.
431
440
  * For document type keys, generates additional tools: append_, insert_, edit_
441
+ *
442
+ * Security: All tools use llm_set_key internally which:
443
+ * - Only modifies VALUES, never attributes/systemTags
444
+ * - Prevents LLMs from escalating privileges
445
+ */
446
+ create_vercel_ai_tools(): Record<string, any>;
447
+ /**
448
+ * @deprecated Use create_vercel_ai_tools() instead
432
449
  */
433
450
  get_aisdk_tools(): Record<string, any>;
434
451
  /**
@@ -532,4 +549,4 @@ declare class CloudAdapter {
532
549
  private scheduleReconnect;
533
550
  }
534
551
 
535
- export { type AccessLevel as A, CloudAdapter as C, DEFAULT_KEY_ATTRIBUTES as D, type GlobalListener as G, type HistoryEntry as H, type KeyAttributes as K, type Listener as L, MindCache as M, type Operation as O, type SystemTag as S, type MindCacheOptions as a, type KeyType as b, type STM as c, type STMEntry as d, type HistoryOptions as e, type MindCacheCloudOptions as f, type MindCacheIndexedDBOptions as g, type CloudConfig as h, type ConnectionState as i, type CloudAdapterEvents as j, type SetOperation as k, type DeleteOperation as l, type ClearOperation as m };
552
+ export { type AccessLevel as A, CloudAdapter as C, DEFAULT_KEY_ATTRIBUTES as D, type GlobalListener as G, type HistoryEntry as H, type KeyAttributes as K, type Listener as L, MindCache as M, type Operation as O, type SystemTag as S, type MindCacheOptions as a, type KeyType as b, type STM as c, type STMEntry as d, type HistoryOptions as e, type MindCacheCloudOptions as f, type MindCacheIndexedDBOptions as g, SystemTagHelpers as h, type CloudConfig as i, type ConnectionState as j, type CloudAdapterEvents as k, type SetOperation as l, type DeleteOperation as m, type ClearOperation as n };
@@ -1,5 +1,5 @@
1
- import { M as MindCache, h as CloudConfig, C as CloudAdapter } from '../CloudAdapter-WvuWM4fD.mjs';
2
- export { m as ClearOperation, j as CloudAdapterEvents, i as ConnectionState, l as DeleteOperation, O as Operation, k as SetOperation } from '../CloudAdapter-WvuWM4fD.mjs';
1
+ import { M as MindCache, i as CloudConfig, C as CloudAdapter } from '../CloudAdapter-D2xxVv4E.mjs';
2
+ export { n as ClearOperation, k as CloudAdapterEvents, j as ConnectionState, m as DeleteOperation, O as Operation, l as SetOperation } from '../CloudAdapter-D2xxVv4E.mjs';
3
3
  import 'yjs';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
- import { M as MindCache, h as CloudConfig, C as CloudAdapter } from '../CloudAdapter-WvuWM4fD.js';
2
- export { m as ClearOperation, j as CloudAdapterEvents, i as ConnectionState, l as DeleteOperation, O as Operation, k as SetOperation } from '../CloudAdapter-WvuWM4fD.js';
1
+ import { M as MindCache, i as CloudConfig, C as CloudAdapter } from '../CloudAdapter-D2xxVv4E.js';
2
+ export { n as ClearOperation, k as CloudAdapterEvents, j as ConnectionState, m as DeleteOperation, O as Operation, l as SetOperation } from '../CloudAdapter-D2xxVv4E.js';
3
3
  import 'yjs';
4
4
 
5
5
  /**
@@ -73,7 +73,7 @@ var init_IndexedDBAdapter = __esm({
73
73
  await this.initDB();
74
74
  await this.load();
75
75
  const listener = () => {
76
- if (this.mindcache && !this.mindcache.isRemoteUpdate()) {
76
+ if (this.mindcache) {
77
77
  this.scheduleSave();
78
78
  }
79
79
  };
@@ -453,15 +453,9 @@ var init_CloudAdapter = __esm({
453
453
  var DEFAULT_KEY_ATTRIBUTES = {
454
454
  type: "text",
455
455
  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: []
456
+ systemTags: [],
457
+ // Keys are private by default - explicitly add SystemPrompt/LLMRead/LLMWrite to enable LLM access
458
+ zIndex: 0
465
459
  };
466
460
 
467
461
  // src/core/MindCache.ts
@@ -477,38 +471,16 @@ var MindCache = class {
477
471
  version = "3.3.2";
478
472
  // Internal flag to prevent sync loops when receiving remote updates
479
473
  // (Less critical with Yjs but kept for API compat)
480
- _isRemoteUpdate = false;
481
474
  normalizeSystemTags(tags) {
482
475
  const normalized = [];
483
- let hasSystemPrompt = false;
484
- let hasLLMRead = false;
485
- let hasLLMWrite = false;
486
- let hasReadonly = false;
476
+ const seen = /* @__PURE__ */ new Set();
487
477
  for (const tag of tags) {
488
- if (tag === "SystemPrompt" || tag === "prompt") {
489
- hasSystemPrompt = true;
490
- } else if (tag === "LLMRead") {
491
- hasLLMRead = true;
492
- } else if (tag === "LLMWrite") {
493
- hasLLMWrite = true;
494
- } else if (tag === "readonly") {
495
- hasReadonly = true;
496
- } else if (tag === "protected") {
497
- normalized.push(tag);
498
- } else if (tag === "ApplyTemplate" || tag === "template") {
499
- normalized.push("ApplyTemplate");
500
- }
501
- }
502
- if (hasSystemPrompt) {
503
- normalized.push("SystemPrompt");
504
- }
505
- if (hasLLMRead) {
506
- normalized.push("LLMRead");
507
- }
508
- if (hasReadonly) {
509
- normalized.push("readonly");
510
- } else if (hasLLMWrite) {
511
- normalized.push("LLMWrite");
478
+ if (["SystemPrompt", "LLMRead", "LLMWrite", "protected", "ApplyTemplate"].includes(tag)) {
479
+ if (!seen.has(tag)) {
480
+ seen.add(tag);
481
+ normalized.push(tag);
482
+ }
483
+ }
512
484
  }
513
485
  return normalized;
514
486
  }
@@ -899,10 +871,6 @@ var MindCache = class {
899
871
  this._idbProvider = null;
900
872
  }
901
873
  }
902
- // Legacy bridge
903
- isRemoteUpdate() {
904
- return false;
905
- }
906
874
  // Serialize state
907
875
  serialize() {
908
876
  const json = {};
@@ -939,16 +907,10 @@ var MindCache = class {
939
907
  const attrs = entry.attributes || {};
940
908
  const normalizedAttrs = {
941
909
  type: attrs.type || "text",
910
+ contentType: attrs.contentType,
942
911
  contentTags: attrs.contentTags || [],
943
- systemTags: attrs.systemTags || this.normalizeSystemTags(attrs.visible !== false ? ["prompt"] : []),
944
- zIndex: attrs.zIndex ?? 0,
945
- // Legacy fields
946
- readonly: attrs.readonly ?? false,
947
- visible: attrs.visible ?? true,
948
- hardcoded: attrs.hardcoded ?? false,
949
- template: attrs.template ?? false,
950
- tags: attrs.tags || [],
951
- contentType: attrs.contentType
912
+ systemTags: this.normalizeSystemTags(attrs.systemTags || []),
913
+ zIndex: attrs.zIndex ?? 0
952
914
  };
953
915
  entryMap.set("attributes", normalizedAttrs);
954
916
  }
@@ -1053,7 +1015,7 @@ var MindCache = class {
1053
1015
  if (_processingStack && _processingStack.has(key)) {
1054
1016
  return `{{${key}}}`;
1055
1017
  }
1056
- if (attributes?.systemTags?.includes("ApplyTemplate") || attributes?.systemTags?.includes("template") || attributes?.template) {
1018
+ if (attributes?.systemTags?.includes("ApplyTemplate")) {
1057
1019
  if (typeof value === "string") {
1058
1020
  const stack = _processingStack || /* @__PURE__ */ new Set();
1059
1021
  stack.add(key);
@@ -1067,13 +1029,8 @@ var MindCache = class {
1067
1029
  return {
1068
1030
  type: "text",
1069
1031
  contentTags: [],
1070
- systemTags: ["prompt", "readonly", "protected"],
1071
- zIndex: 999999,
1072
- readonly: true,
1073
- visible: true,
1074
- hardcoded: true,
1075
- template: false,
1076
- tags: []
1032
+ systemTags: ["SystemPrompt", "protected"],
1033
+ zIndex: 999999
1077
1034
  };
1078
1035
  }
1079
1036
  const entryMap = this.rootMap.get(key);
@@ -1098,6 +1055,14 @@ var MindCache = class {
1098
1055
  mergedAttrs.systemTags = this.normalizeSystemTags(mergedAttrs.systemTags);
1099
1056
  }
1100
1057
  entryMap.set("attributes", mergedAttrs);
1058
+ const currentValue = entryMap.get("value");
1059
+ if (mergedAttrs.type === "document" && !(currentValue instanceof Y__namespace.Text)) {
1060
+ const strValue = typeof currentValue === "string" ? currentValue : String(currentValue ?? "");
1061
+ entryMap.set("value", new Y__namespace.Text(strValue));
1062
+ this.getUndoManager(key);
1063
+ } else if (mergedAttrs.type !== "document" && currentValue instanceof Y__namespace.Text) {
1064
+ entryMap.set("value", currentValue.toString());
1065
+ }
1101
1066
  });
1102
1067
  }
1103
1068
  set_value(key, value, attributes) {
@@ -1108,10 +1073,15 @@ var MindCache = class {
1108
1073
  if (existingEntry) {
1109
1074
  const existingAttrs = existingEntry.get("attributes");
1110
1075
  if (existingAttrs?.type === "document") {
1111
- if (typeof value === "string") {
1112
- this._replaceDocumentText(key, value);
1076
+ if (!attributes?.type || attributes.type === "document") {
1077
+ if (typeof value === "string") {
1078
+ this._replaceDocumentText(key, value);
1079
+ }
1080
+ if (attributes) {
1081
+ this.set_attributes(key, attributes);
1082
+ }
1083
+ return;
1113
1084
  }
1114
- return;
1115
1085
  }
1116
1086
  }
1117
1087
  if (!existingEntry && attributes?.type === "document") {
@@ -1127,26 +1097,55 @@ var MindCache = class {
1127
1097
  this.getUndoManager(key);
1128
1098
  this.doc.transact(() => {
1129
1099
  const oldAttributes = isNewEntry ? {
1130
- ...DEFAULT_KEY_ATTRIBUTES,
1131
- contentTags: [],
1132
- systemTags: ["SystemPrompt", "LLMWrite"],
1133
- tags: [],
1134
- zIndex: 0
1100
+ ...DEFAULT_KEY_ATTRIBUTES
1135
1101
  } : entryMap.get("attributes");
1136
1102
  const finalAttributes = attributes ? { ...oldAttributes, ...attributes } : oldAttributes;
1137
1103
  let normalizedAttributes = { ...finalAttributes };
1138
1104
  if (finalAttributes.systemTags) {
1139
1105
  normalizedAttributes.systemTags = this.normalizeSystemTags(finalAttributes.systemTags);
1140
1106
  }
1141
- if (finalAttributes.template) {
1142
- if (!normalizedAttributes.systemTags.includes("template")) {
1143
- normalizedAttributes.systemTags.push("template");
1144
- }
1107
+ let valueToSet = value;
1108
+ if (normalizedAttributes.type === "document" && !(valueToSet instanceof Y__namespace.Text)) {
1109
+ valueToSet = new Y__namespace.Text(typeof value === "string" ? value : String(value ?? ""));
1110
+ } else if (normalizedAttributes.type !== "document" && valueToSet instanceof Y__namespace.Text) {
1111
+ valueToSet = valueToSet.toString();
1145
1112
  }
1146
- entryMap.set("value", value);
1113
+ entryMap.set("value", valueToSet);
1147
1114
  entryMap.set("attributes", normalizedAttributes);
1148
1115
  });
1149
1116
  }
1117
+ /**
1118
+ * LLM-safe method to write a value to a key.
1119
+ * This method:
1120
+ * - Only updates the value, never modifies attributes/systemTags
1121
+ * - Checks LLMWrite permission before writing
1122
+ * - Returns false if key doesn't exist or lacks LLMWrite permission
1123
+ *
1124
+ * Used by create_vercel_ai_tools() to prevent LLMs from escalating privileges.
1125
+ */
1126
+ llm_set_key(key, value) {
1127
+ if (key === "$date" || key === "$time" || key === "$version") {
1128
+ return false;
1129
+ }
1130
+ const entryMap = this.rootMap.get(key);
1131
+ if (!entryMap) {
1132
+ return false;
1133
+ }
1134
+ const attributes = entryMap.get("attributes");
1135
+ if (!attributes?.systemTags?.includes("LLMWrite")) {
1136
+ return false;
1137
+ }
1138
+ if (attributes.type === "document") {
1139
+ if (typeof value === "string") {
1140
+ this._replaceDocumentText(key, value);
1141
+ }
1142
+ return true;
1143
+ }
1144
+ this.doc.transact(() => {
1145
+ entryMap.set("value", value);
1146
+ });
1147
+ return true;
1148
+ }
1150
1149
  delete_key(key) {
1151
1150
  if (key === "$date" || key === "$time") {
1152
1151
  return;
@@ -1591,15 +1590,13 @@ var MindCache = class {
1591
1590
  }
1592
1591
  const attributes = entryMap.get("attributes");
1593
1592
  const value = entryMap.get("value");
1594
- if (attributes?.hardcoded) {
1593
+ if (attributes?.systemTags?.includes("protected")) {
1595
1594
  return;
1596
1595
  }
1597
1596
  lines.push(`### ${key}`);
1598
1597
  const entryType = attributes?.type || "text";
1599
1598
  lines.push(`- **Type**: \`${entryType}\``);
1600
- lines.push(`- **Readonly**: \`${attributes?.readonly ?? false}\``);
1601
- lines.push(`- **Visible**: \`${attributes?.visible ?? true}\``);
1602
- lines.push(`- **Template**: \`${attributes?.template ?? false}\``);
1599
+ lines.push(`- **System Tags**: \`${attributes?.systemTags?.join(", ") || "none"}\``);
1603
1600
  lines.push(`- **Z-Index**: \`${attributes?.zIndex ?? 0}\``);
1604
1601
  if (attributes?.contentTags && attributes.contentTags.length > 0) {
1605
1602
  lines.push(`- **Tags**: \`${attributes.contentTags.join("`, `")}\``);
@@ -1685,16 +1682,11 @@ var MindCache = class {
1685
1682
  }
1686
1683
  continue;
1687
1684
  }
1688
- if (line.startsWith("- **Readonly**:")) {
1689
- currentAttributes.readonly = line.includes("`true`");
1690
- continue;
1691
- }
1692
- if (line.startsWith("- **Visible**:")) {
1693
- currentAttributes.visible = line.includes("`true`");
1694
- continue;
1695
- }
1696
- if (line.startsWith("- **Template**:")) {
1697
- currentAttributes.template = line.includes("`true`");
1685
+ if (line.startsWith("- **System Tags**:")) {
1686
+ const tagsStr = line.match(/`([^`]+)`/)?.[1] || "";
1687
+ if (tagsStr !== "none") {
1688
+ currentAttributes.systemTags = tagsStr.split(", ").filter((t) => t);
1689
+ }
1698
1690
  continue;
1699
1691
  }
1700
1692
  if (line.startsWith("- **Z-Index**:")) {
@@ -1705,7 +1697,6 @@ var MindCache = class {
1705
1697
  if (line.startsWith("- **Tags**:")) {
1706
1698
  const tags = line.match(/`([^`]+)`/g)?.map((t) => t.slice(1, -1)) || [];
1707
1699
  currentAttributes.contentTags = tags;
1708
- currentAttributes.tags = tags;
1709
1700
  continue;
1710
1701
  }
1711
1702
  if (line.startsWith("- **Content Type**:")) {
@@ -1961,8 +1952,12 @@ var MindCache = class {
1961
1952
  /**
1962
1953
  * Generate Vercel AI SDK compatible tools for writable keys.
1963
1954
  * For document type keys, generates additional tools: append_, insert_, edit_
1955
+ *
1956
+ * Security: All tools use llm_set_key internally which:
1957
+ * - Only modifies VALUES, never attributes/systemTags
1958
+ * - Prevents LLMs from escalating privileges
1964
1959
  */
1965
- get_aisdk_tools() {
1960
+ create_vercel_ai_tools() {
1966
1961
  const tools = {};
1967
1962
  for (const [key, val] of this.rootMap) {
1968
1963
  if (key.startsWith("$")) {
@@ -1970,7 +1965,7 @@ var MindCache = class {
1970
1965
  }
1971
1966
  const entryMap = val;
1972
1967
  const attributes = entryMap.get("attributes");
1973
- const isWritable = !attributes?.readonly && (attributes?.systemTags?.includes("LLMWrite") || !attributes?.systemTags);
1968
+ const isWritable = attributes?.systemTags?.includes("LLMWrite");
1974
1969
  if (!isWritable) {
1975
1970
  continue;
1976
1971
  }
@@ -1986,15 +1981,18 @@ var MindCache = class {
1986
1981
  required: ["value"]
1987
1982
  },
1988
1983
  execute: async ({ value }) => {
1989
- if (isDocument) {
1990
- this._replaceDocumentText(key, value);
1991
- } else {
1992
- this.set_value(key, value);
1984
+ const success = this.llm_set_key(key, value);
1985
+ if (success) {
1986
+ return {
1987
+ result: `Successfully wrote "${value}" to ${key}`,
1988
+ key,
1989
+ value
1990
+ };
1993
1991
  }
1994
1992
  return {
1995
- result: `Successfully wrote "${value}" to ${key}`,
1993
+ result: `Failed to write to ${key} - permission denied or key not found`,
1996
1994
  key,
1997
- value
1995
+ error: true
1998
1996
  };
1999
1997
  }
2000
1998
  };
@@ -2009,6 +2007,9 @@ var MindCache = class {
2009
2007
  required: ["text"]
2010
2008
  },
2011
2009
  execute: async ({ text }) => {
2010
+ if (!attributes?.systemTags?.includes("LLMWrite")) {
2011
+ return { result: `Permission denied for ${key}`, key, error: true };
2012
+ }
2012
2013
  const yText = this.get_document(key);
2013
2014
  if (yText) {
2014
2015
  yText.insert(yText.length, text);
@@ -2032,6 +2033,9 @@ var MindCache = class {
2032
2033
  required: ["index", "text"]
2033
2034
  },
2034
2035
  execute: async ({ index, text }) => {
2036
+ if (!attributes?.systemTags?.includes("LLMWrite")) {
2037
+ return { result: `Permission denied for ${key}`, key, error: true };
2038
+ }
2035
2039
  this.insert_text(key, index, text);
2036
2040
  return {
2037
2041
  result: `Successfully inserted text at position ${index} in ${key}`,
@@ -2052,6 +2056,9 @@ var MindCache = class {
2052
2056
  required: ["find", "replace"]
2053
2057
  },
2054
2058
  execute: async ({ find, replace }) => {
2059
+ if (!attributes?.systemTags?.includes("LLMWrite")) {
2060
+ return { result: `Permission denied for ${key}`, key, error: true };
2061
+ }
2055
2062
  const yText = this.get_document(key);
2056
2063
  if (yText) {
2057
2064
  const text = yText.toString();
@@ -2076,6 +2083,12 @@ var MindCache = class {
2076
2083
  }
2077
2084
  return tools;
2078
2085
  }
2086
+ /**
2087
+ * @deprecated Use create_vercel_ai_tools() instead
2088
+ */
2089
+ get_aisdk_tools() {
2090
+ return this.create_vercel_ai_tools();
2091
+ }
2079
2092
  /**
2080
2093
  * Generate a system prompt containing all visible STM keys and their values.
2081
2094
  * Indicates which tools can be used to modify writable keys.
@@ -2088,13 +2101,13 @@ var MindCache = class {
2088
2101
  }
2089
2102
  const entryMap = val;
2090
2103
  const attributes = entryMap.get("attributes");
2091
- const isVisible = attributes?.visible !== false && (attributes?.systemTags?.includes("prompt") || attributes?.systemTags?.includes("SystemPrompt") || !attributes?.systemTags);
2104
+ const isVisible = attributes?.systemTags?.includes("SystemPrompt") || attributes?.systemTags?.includes("LLMRead");
2092
2105
  if (!isVisible) {
2093
2106
  continue;
2094
2107
  }
2095
2108
  const value = this.get_value(key);
2096
2109
  const displayValue = typeof value === "object" ? JSON.stringify(value) : value;
2097
- const isWritable = !attributes?.readonly && (attributes?.systemTags?.includes("LLMWrite") || !attributes?.systemTags);
2110
+ const isWritable = attributes?.systemTags?.includes("LLMWrite");
2098
2111
  const isDocument = attributes?.type === "document";
2099
2112
  const sanitizedKey = this.sanitizeKeyForTool(key);
2100
2113
  if (isWritable) {
@@ -2135,7 +2148,7 @@ var MindCache = class {
2135
2148
  return null;
2136
2149
  }
2137
2150
  const attributes = entryMap.get("attributes");
2138
- const isWritable = !attributes?.readonly && (attributes?.systemTags?.includes("LLMWrite") || !attributes?.systemTags);
2151
+ const isWritable = attributes?.systemTags?.includes("LLMWrite");
2139
2152
  if (!isWritable) {
2140
2153
  return null;
2141
2154
  }