mindcache 2.3.0 → 2.4.0

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.
@@ -10,6 +10,157 @@ var __export = (target, all) => {
10
10
  __defProp(target, name, { get: all[name], enumerable: true });
11
11
  };
12
12
 
13
+ // src/local/IndexedDBAdapter.ts
14
+ var IndexedDBAdapter_exports = {};
15
+ __export(IndexedDBAdapter_exports, {
16
+ IndexedDBAdapter: () => IndexedDBAdapter
17
+ });
18
+ var IndexedDBAdapter;
19
+ var init_IndexedDBAdapter = __esm({
20
+ "src/local/IndexedDBAdapter.ts"() {
21
+ IndexedDBAdapter = class {
22
+ constructor(config = {}) {
23
+ this.config = config;
24
+ this.dbName = config.dbName || "mindcache_db";
25
+ this.storeName = config.storeName || "mindcache_store";
26
+ this.key = config.key || "mindcache_data";
27
+ }
28
+ mindcache = null;
29
+ unsubscribe = null;
30
+ saveTimeout = null;
31
+ db = null;
32
+ dbName;
33
+ storeName;
34
+ key;
35
+ async attach(mc) {
36
+ if (this.mindcache) {
37
+ this.detach();
38
+ }
39
+ this.mindcache = mc;
40
+ await this.initDB();
41
+ await this.load();
42
+ const listener = () => {
43
+ if (this.mindcache && !this.mindcache.isRemoteUpdate()) {
44
+ this.scheduleSave();
45
+ }
46
+ };
47
+ mc.subscribeToAll(listener);
48
+ this.unsubscribe = () => mc.unsubscribeFromAll(listener);
49
+ console.log("\u{1F5C4}\uFE0F IndexedDBAdapter: Attached to MindCache instance");
50
+ }
51
+ detach() {
52
+ if (this.unsubscribe) {
53
+ this.unsubscribe();
54
+ this.unsubscribe = null;
55
+ }
56
+ if (this.saveTimeout) {
57
+ clearTimeout(this.saveTimeout);
58
+ this.saveTimeout = null;
59
+ }
60
+ this.mindcache = null;
61
+ if (this.db) {
62
+ this.db.close();
63
+ this.db = null;
64
+ }
65
+ }
66
+ initDB() {
67
+ return new Promise((resolve, reject) => {
68
+ const request = indexedDB.open(this.dbName);
69
+ request.onerror = () => {
70
+ console.error("MindCache: IndexedDB error:", request.error);
71
+ reject(request.error);
72
+ };
73
+ request.onsuccess = () => {
74
+ const db = request.result;
75
+ if (!db.objectStoreNames.contains(this.storeName)) {
76
+ const currentVersion = db.version;
77
+ db.close();
78
+ const upgradeRequest = indexedDB.open(this.dbName, currentVersion + 1);
79
+ upgradeRequest.onerror = () => {
80
+ console.error("MindCache: IndexedDB upgrade error:", upgradeRequest.error);
81
+ reject(upgradeRequest.error);
82
+ };
83
+ upgradeRequest.onupgradeneeded = () => {
84
+ const upgradeDb = upgradeRequest.result;
85
+ if (!upgradeDb.objectStoreNames.contains(this.storeName)) {
86
+ upgradeDb.createObjectStore(this.storeName);
87
+ }
88
+ };
89
+ upgradeRequest.onsuccess = () => {
90
+ this.db = upgradeRequest.result;
91
+ resolve();
92
+ };
93
+ } else {
94
+ this.db = db;
95
+ resolve();
96
+ }
97
+ };
98
+ request.onupgradeneeded = () => {
99
+ const db = request.result;
100
+ if (!db.objectStoreNames.contains(this.storeName)) {
101
+ db.createObjectStore(this.storeName);
102
+ }
103
+ };
104
+ });
105
+ }
106
+ load() {
107
+ if (!this.db || !this.mindcache) {
108
+ return Promise.resolve();
109
+ }
110
+ return new Promise((resolve) => {
111
+ try {
112
+ const transaction = this.db.transaction([this.storeName], "readonly");
113
+ const store = transaction.objectStore(this.storeName);
114
+ const request = store.get(this.key);
115
+ request.onsuccess = () => {
116
+ if (request.result) {
117
+ this.mindcache.deserialize(request.result);
118
+ console.log("\u{1F5C4}\uFE0F IndexedDBAdapter: Loaded data from IndexedDB");
119
+ }
120
+ resolve();
121
+ };
122
+ request.onerror = () => {
123
+ console.error("MindCache: Failed to load from IndexedDB:", request.error);
124
+ resolve();
125
+ };
126
+ } catch (error) {
127
+ console.error("MindCache: Error accessing IndexedDB for load:", error);
128
+ resolve();
129
+ }
130
+ });
131
+ }
132
+ scheduleSave() {
133
+ if (this.saveTimeout) {
134
+ clearTimeout(this.saveTimeout);
135
+ }
136
+ this.saveTimeout = setTimeout(() => {
137
+ this.save();
138
+ this.saveTimeout = null;
139
+ }, this.config.debounceMs ?? 1e3);
140
+ }
141
+ save() {
142
+ if (!this.db || !this.mindcache) {
143
+ return;
144
+ }
145
+ try {
146
+ const data = this.mindcache.serialize();
147
+ const transaction = this.db.transaction([this.storeName], "readwrite");
148
+ const store = transaction.objectStore(this.storeName);
149
+ const request = store.put(data, this.key);
150
+ request.onsuccess = () => {
151
+ console.log("\u{1F5C4}\uFE0F IndexedDBAdapter: Saved to IndexedDB");
152
+ };
153
+ request.onerror = () => {
154
+ console.error("MindCache: Failed to save to IndexedDB:", request.error);
155
+ };
156
+ } catch (error) {
157
+ console.error("MindCache: Error accessing IndexedDB for save:", error);
158
+ }
159
+ }
160
+ };
161
+ }
162
+ });
163
+
13
164
  // src/cloud/CloudAdapter.ts
14
165
  var CloudAdapter_exports = {};
15
166
  __export(CloudAdapter_exports, {
@@ -328,8 +479,8 @@ var init_CloudAdapter = __esm({
328
479
  var DEFAULT_KEY_ATTRIBUTES = {
329
480
  type: "text",
330
481
  contentTags: [],
331
- systemTags: ["prompt"],
332
- // visible by default
482
+ systemTags: ["SystemPrompt", "LLMWrite"],
483
+ // visible in system prompt and writable by LLM by default
333
484
  zIndex: 0,
334
485
  // Legacy - derived from systemTags
335
486
  readonly: false,
@@ -346,6 +497,65 @@ var MindCache = class {
346
497
  globalListeners = [];
347
498
  // Internal flag to prevent sync loops when receiving remote updates
348
499
  _isRemoteUpdate = false;
500
+ /**
501
+ * Normalize system tags: migrate old tags to new ones
502
+ * - 'prompt' → 'SystemPrompt'
503
+ * - 'readonly' → remove 'LLMWrite' (or add if not readonly)
504
+ */
505
+ normalizeSystemTags(tags) {
506
+ const normalized = [];
507
+ let hasSystemPrompt = false;
508
+ let hasLLMRead = false;
509
+ let hasLLMWrite = false;
510
+ let hasReadonly = false;
511
+ for (const tag of tags) {
512
+ if (tag === "SystemPrompt" || tag === "prompt") {
513
+ hasSystemPrompt = true;
514
+ } else if (tag === "LLMRead") {
515
+ hasLLMRead = true;
516
+ } else if (tag === "LLMWrite") {
517
+ hasLLMWrite = true;
518
+ } else if (tag === "readonly") {
519
+ hasReadonly = true;
520
+ } else if (tag === "protected") {
521
+ normalized.push(tag);
522
+ } else if (tag === "ApplyTemplate" || tag === "template") {
523
+ normalized.push("ApplyTemplate");
524
+ }
525
+ }
526
+ if (hasSystemPrompt) {
527
+ normalized.push("SystemPrompt");
528
+ }
529
+ if (hasLLMRead) {
530
+ normalized.push("LLMRead");
531
+ }
532
+ if (hasReadonly) {
533
+ normalized.push("readonly");
534
+ } else if (hasLLMWrite) {
535
+ normalized.push("LLMWrite");
536
+ } else {
537
+ normalized.push("LLMWrite");
538
+ }
539
+ return normalized;
540
+ }
541
+ /**
542
+ * Check if key should be visible in system prompt
543
+ */
544
+ hasSystemPrompt(tags) {
545
+ return tags.includes("SystemPrompt") || tags.includes("prompt");
546
+ }
547
+ /**
548
+ * Check if key can be read by LLM (has LLMRead or SystemPrompt)
549
+ */
550
+ hasLLMRead(tags) {
551
+ return tags.includes("LLMRead") || tags.includes("SystemPrompt") || tags.includes("prompt");
552
+ }
553
+ /**
554
+ * Check if key can be written by LLM (has LLMWrite and not readonly)
555
+ */
556
+ hasLLMWrite(tags) {
557
+ return tags.includes("LLMWrite") && !tags.includes("readonly");
558
+ }
349
559
  // Cloud sync state
350
560
  _cloudAdapter = null;
351
561
  _connectionState = "disconnected";
@@ -359,11 +569,28 @@ var MindCache = class {
359
569
  if (options?.accessLevel) {
360
570
  this._accessLevel = options.accessLevel;
361
571
  }
572
+ if (options?.cloud && options?.indexedDB) {
573
+ throw new Error(
574
+ "MindCache: Cannot use both cloud and indexedDB together. Choose one persistence method to avoid data conflicts. Use cloud for real-time sync, or indexedDB for local-only persistence."
575
+ );
576
+ }
577
+ const initPromises = [];
362
578
  if (options?.cloud) {
363
579
  this._cloudConfig = options.cloud;
364
580
  this._isLoaded = false;
365
581
  this._connectionState = "disconnected";
366
- this._initPromise = this._initCloud();
582
+ initPromises.push(this._initCloud());
583
+ }
584
+ if (options?.indexedDB) {
585
+ this._isLoaded = false;
586
+ initPromises.push(this._initIndexedDB(options.indexedDB));
587
+ }
588
+ if (initPromises.length > 0) {
589
+ this._initPromise = Promise.all(initPromises).then(() => {
590
+ if (!this._cloudConfig) {
591
+ this._isLoaded = true;
592
+ }
593
+ });
367
594
  }
368
595
  }
369
596
  /**
@@ -443,6 +670,19 @@ var MindCache = class {
443
670
  this._isLoaded = true;
444
671
  }
445
672
  }
673
+ async _initIndexedDB(config) {
674
+ try {
675
+ const IndexedDBAdapter2 = await this._getIndexedDBAdapterClass();
676
+ const adapter = new IndexedDBAdapter2(config);
677
+ await adapter.attach(this);
678
+ } catch (error) {
679
+ console.error("MindCache: Failed to initialize IndexedDB:", error);
680
+ }
681
+ }
682
+ async _getIndexedDBAdapterClass() {
683
+ const { IndexedDBAdapter: IndexedDBAdapter2 } = await Promise.resolve().then(() => (init_IndexedDBAdapter(), IndexedDBAdapter_exports));
684
+ return IndexedDBAdapter2;
685
+ }
446
686
  /**
447
687
  * Get the current cloud connection state
448
688
  */
@@ -561,7 +801,7 @@ var MindCache = class {
561
801
  if (!entry) {
562
802
  return void 0;
563
803
  }
564
- if (entry.attributes.template) {
804
+ if (entry.attributes.systemTags?.includes("ApplyTemplate") || entry.attributes.systemTags?.includes("template") || entry.attributes.template) {
565
805
  const processingStack = _processingStack || /* @__PURE__ */ new Set();
566
806
  if (processingStack.has(key)) {
567
807
  return entry.value;
@@ -610,77 +850,87 @@ var MindCache = class {
610
850
  ...DEFAULT_KEY_ATTRIBUTES,
611
851
  contentTags: [],
612
852
  // Fresh array
613
- systemTags: ["prompt"],
853
+ systemTags: ["SystemPrompt", "LLMWrite"],
614
854
  // Fresh array with default
615
855
  tags: [],
616
856
  // Fresh array
617
857
  zIndex: 0
618
858
  };
619
859
  const finalAttributes = attributes ? { ...baseAttributes, ...attributes } : baseAttributes;
860
+ let systemTags = this.normalizeSystemTags(finalAttributes.systemTags || []);
620
861
  if (attributes) {
621
- let systemTags2 = [...finalAttributes.systemTags || []];
622
862
  if ("readonly" in attributes) {
623
- if (attributes.readonly && !systemTags2.includes("readonly")) {
624
- systemTags2.push("readonly");
625
- } else if (!attributes.readonly && !wasHardcoded) {
626
- systemTags2 = systemTags2.filter((t) => t !== "readonly");
863
+ if (attributes.readonly) {
864
+ systemTags = systemTags.filter((t) => t !== "LLMWrite");
865
+ if (!systemTags.includes("readonly")) {
866
+ systemTags.push("readonly");
867
+ }
868
+ } else if (!wasHardcoded) {
869
+ if (!systemTags.includes("LLMWrite")) {
870
+ systemTags.push("LLMWrite");
871
+ }
872
+ systemTags = systemTags.filter((t) => t !== "readonly");
627
873
  }
628
874
  }
629
875
  if ("visible" in attributes) {
630
- if (attributes.visible && !systemTags2.includes("prompt")) {
631
- systemTags2.push("prompt");
632
- } else if (!attributes.visible) {
633
- systemTags2 = systemTags2.filter((t) => t !== "prompt");
876
+ if (attributes.visible) {
877
+ if (!systemTags.includes("SystemPrompt")) {
878
+ systemTags.push("SystemPrompt");
879
+ }
880
+ systemTags = systemTags.filter((t) => t !== "prompt");
881
+ } else {
882
+ systemTags = systemTags.filter((t) => t !== "SystemPrompt" && t !== "prompt");
634
883
  }
635
884
  }
885
+ if ("systemTags" in attributes && Array.isArray(attributes.systemTags)) {
886
+ systemTags = this.normalizeSystemTags(attributes.systemTags);
887
+ }
636
888
  if ("hardcoded" in attributes) {
637
- if (attributes.hardcoded && !systemTags2.includes("protected")) {
638
- systemTags2.push("protected");
889
+ if (attributes.hardcoded && !systemTags.includes("protected")) {
890
+ systemTags.push("protected");
639
891
  } else if (!attributes.hardcoded && !wasHardcoded) {
640
- systemTags2 = systemTags2.filter((t) => t !== "protected");
892
+ systemTags = systemTags.filter((t) => t !== "protected");
641
893
  }
642
- if (wasHardcoded && !systemTags2.includes("protected")) {
643
- systemTags2.push("protected");
894
+ if (wasHardcoded && !systemTags.includes("protected")) {
895
+ systemTags.push("protected");
644
896
  }
645
897
  } else if (wasHardcoded) {
646
- if (!systemTags2.includes("protected")) {
647
- systemTags2.push("protected");
898
+ if (!systemTags.includes("protected")) {
899
+ systemTags.push("protected");
648
900
  }
649
901
  }
650
902
  if ("template" in attributes) {
651
- if (attributes.template && !wasHardcoded && !systemTags2.includes("template")) {
652
- systemTags2.push("template");
903
+ if (attributes.template && !wasHardcoded && !systemTags.includes("ApplyTemplate") && !systemTags.includes("template")) {
904
+ systemTags.push("ApplyTemplate");
653
905
  } else if (!attributes.template || wasHardcoded) {
654
- systemTags2 = systemTags2.filter((t) => t !== "template");
906
+ systemTags = systemTags.filter((t) => t !== "ApplyTemplate" && t !== "template");
655
907
  }
656
908
  }
657
- finalAttributes.systemTags = systemTags2;
658
909
  } else if (wasHardcoded) {
659
- let systemTags2 = [...finalAttributes.systemTags || []];
660
- if (!systemTags2.includes("protected")) {
661
- systemTags2.push("protected");
910
+ if (!systemTags.includes("protected")) {
911
+ systemTags.push("protected");
662
912
  }
663
- if (!systemTags2.includes("readonly")) {
664
- systemTags2.push("readonly");
913
+ systemTags = systemTags.filter((t) => t !== "LLMWrite");
914
+ if (!systemTags.includes("readonly")) {
915
+ systemTags.push("readonly");
665
916
  }
666
- systemTags2 = systemTags2.filter((t) => t !== "template");
667
- finalAttributes.systemTags = systemTags2;
917
+ systemTags = systemTags.filter((t) => t !== "template");
668
918
  }
669
- let systemTags = finalAttributes.systemTags || [];
670
919
  if (wasHardcoded && !systemTags.includes("protected")) {
671
- systemTags = [...systemTags, "protected"];
920
+ systemTags.push("protected");
672
921
  }
673
922
  if (systemTags.includes("protected")) {
923
+ systemTags = systemTags.filter((t) => t !== "LLMWrite");
674
924
  if (!systemTags.includes("readonly")) {
675
- systemTags = [...systemTags, "readonly"];
925
+ systemTags.push("readonly");
676
926
  }
677
927
  systemTags = systemTags.filter((t) => t !== "template");
678
- finalAttributes.systemTags = systemTags;
679
928
  }
680
- finalAttributes.readonly = systemTags.includes("readonly");
681
- finalAttributes.visible = systemTags.includes("prompt");
929
+ finalAttributes.systemTags = systemTags;
930
+ finalAttributes.readonly = systemTags.includes("readonly") || !systemTags.includes("LLMWrite");
931
+ finalAttributes.visible = this.hasSystemPrompt(systemTags);
682
932
  finalAttributes.hardcoded = wasHardcoded || systemTags.includes("protected");
683
- finalAttributes.template = systemTags.includes("template");
933
+ finalAttributes.template = systemTags.includes("ApplyTemplate") || systemTags.includes("template");
684
934
  if (attributes && "tags" in attributes && attributes.tags) {
685
935
  finalAttributes.contentTags = [...attributes.tags];
686
936
  }
@@ -701,21 +951,25 @@ var MindCache = class {
701
951
  return;
702
952
  }
703
953
  this._isRemoteUpdate = true;
704
- const systemTags = attributes.systemTags || [];
705
- if (!attributes.systemTags) {
954
+ let systemTags = attributes.systemTags || [];
955
+ if (!attributes.systemTags || systemTags.length === 0) {
956
+ systemTags = [];
706
957
  if (attributes.visible !== false) {
707
958
  systemTags.push("prompt");
708
959
  }
709
960
  if (attributes.readonly) {
710
961
  systemTags.push("readonly");
962
+ } else {
963
+ systemTags.push("LLMWrite");
711
964
  }
712
965
  if (attributes.hardcoded) {
713
966
  systemTags.push("protected");
714
967
  }
715
968
  if (attributes.template) {
716
- systemTags.push("template");
969
+ systemTags.push("ApplyTemplate");
717
970
  }
718
971
  }
972
+ systemTags = this.normalizeSystemTags(systemTags);
719
973
  const contentTags = attributes.contentTags || attributes.tags || [];
720
974
  this.stm[key] = {
721
975
  value,
@@ -725,10 +979,11 @@ var MindCache = class {
725
979
  systemTags,
726
980
  zIndex: attributes.zIndex ?? 0,
727
981
  tags: contentTags,
728
- readonly: systemTags.includes("readonly"),
729
- visible: systemTags.includes("prompt"),
982
+ // Sync legacy attributes FROM normalized systemTags
983
+ readonly: systemTags.includes("readonly") || !systemTags.includes("LLMWrite"),
984
+ visible: this.hasSystemPrompt(systemTags),
730
985
  hardcoded: systemTags.includes("protected"),
731
- template: systemTags.includes("template")
986
+ template: systemTags.includes("ApplyTemplate") || systemTags.includes("template")
732
987
  }
733
988
  };
734
989
  if (this.listeners[key]) {
@@ -783,39 +1038,55 @@ var MindCache = class {
783
1038
  }
784
1039
  }
785
1040
  entry.attributes = { ...entry.attributes, ...allowedAttributes };
786
- if ("readonly" in attributes || "visible" in attributes || "template" in attributes) {
787
- let newSystemTags = [];
788
- if (entry.attributes.readonly) {
789
- newSystemTags.push("readonly");
790
- }
791
- if (entry.attributes.visible) {
792
- newSystemTags.push("prompt");
793
- }
794
- if (entry.attributes.template) {
795
- newSystemTags.push("template");
796
- }
797
- if (wasHardcoded || entry.attributes.hardcoded) {
798
- newSystemTags.push("protected");
1041
+ if ("readonly" in attributes || "visible" in attributes || "template" in attributes || "systemTags" in attributes) {
1042
+ let newSystemTags = entry.attributes.systemTags || [];
1043
+ if ("systemTags" in attributes && Array.isArray(attributes.systemTags)) {
1044
+ newSystemTags = this.normalizeSystemTags(attributes.systemTags);
1045
+ } else {
1046
+ newSystemTags = [];
1047
+ if (!entry.attributes.readonly) {
1048
+ newSystemTags.push("LLMWrite");
1049
+ } else {
1050
+ newSystemTags.push("readonly");
1051
+ }
1052
+ if (entry.attributes.visible) {
1053
+ newSystemTags.push("SystemPrompt");
1054
+ }
1055
+ if (entry.attributes.template) {
1056
+ newSystemTags.push("ApplyTemplate");
1057
+ }
1058
+ if (wasHardcoded || entry.attributes.hardcoded) {
1059
+ newSystemTags.push("protected");
1060
+ }
1061
+ newSystemTags = this.normalizeSystemTags(newSystemTags);
799
1062
  }
800
1063
  if (newSystemTags.includes("protected")) {
1064
+ newSystemTags = newSystemTags.filter((t) => t !== "LLMWrite");
801
1065
  if (!newSystemTags.includes("readonly")) {
802
1066
  newSystemTags.push("readonly");
803
1067
  }
804
- newSystemTags = newSystemTags.filter((t) => t !== "template");
1068
+ newSystemTags = newSystemTags.filter((t) => t !== "ApplyTemplate" && t !== "template");
805
1069
  entry.attributes.readonly = true;
806
1070
  entry.attributes.template = false;
807
1071
  }
808
1072
  entry.attributes.systemTags = newSystemTags;
1073
+ entry.attributes.readonly = newSystemTags.includes("readonly") || !newSystemTags.includes("LLMWrite");
1074
+ entry.attributes.visible = this.hasSystemPrompt(newSystemTags);
1075
+ entry.attributes.template = newSystemTags.includes("ApplyTemplate") || newSystemTags.includes("template");
809
1076
  } else if (wasHardcoded) {
810
- let systemTags = [...entry.attributes.systemTags || []];
1077
+ let systemTags = this.normalizeSystemTags(entry.attributes.systemTags || []);
811
1078
  if (!systemTags.includes("protected")) {
812
1079
  systemTags.push("protected");
813
1080
  }
1081
+ systemTags = systemTags.filter((t) => t !== "LLMWrite");
814
1082
  if (!systemTags.includes("readonly")) {
815
1083
  systemTags.push("readonly");
816
1084
  }
817
- systemTags = systemTags.filter((t) => t !== "template");
1085
+ systemTags = systemTags.filter((t) => t !== "ApplyTemplate" && t !== "template");
818
1086
  entry.attributes.systemTags = systemTags;
1087
+ entry.attributes.readonly = true;
1088
+ entry.attributes.visible = this.hasSystemPrompt(systemTags);
1089
+ entry.attributes.template = false;
819
1090
  }
820
1091
  if (wasHardcoded) {
821
1092
  entry.attributes.hardcoded = true;
@@ -1057,8 +1328,9 @@ var MindCache = class {
1057
1328
  const sortedKeys = this.getSortedKeys();
1058
1329
  sortedKeys.forEach((key) => {
1059
1330
  const entry = this.stm[key];
1060
- if (entry.attributes.visible) {
1061
- const processedValue = entry.attributes.template ? this.get_value(key) : entry.value;
1331
+ if (this.hasLLMRead(entry.attributes.systemTags) || entry.attributes.visible) {
1332
+ const hasTemplate = entry.attributes.systemTags?.includes("ApplyTemplate") || entry.attributes.systemTags?.includes("template") || entry.attributes.template;
1333
+ const processedValue = hasTemplate ? this.get_value(key) : entry.value;
1062
1334
  apiData.push({
1063
1335
  key,
1064
1336
  value: processedValue,
@@ -1084,7 +1356,7 @@ var MindCache = class {
1084
1356
  const sortedKeys = this.getSortedKeys();
1085
1357
  sortedKeys.forEach((key) => {
1086
1358
  const entry = this.stm[key];
1087
- if (entry.attributes.visible && entry.attributes.type === "image" && entry.attributes.contentType) {
1359
+ if ((this.hasLLMRead(entry.attributes.systemTags) || entry.attributes.visible) && entry.attributes.type === "image" && entry.attributes.contentType) {
1088
1360
  const dataUrl = this.createDataUrl(entry.value, entry.attributes.contentType);
1089
1361
  imageParts.push({
1090
1362
  type: "file",
@@ -1123,6 +1395,7 @@ var MindCache = class {
1123
1395
  }
1124
1396
  deserialize(data) {
1125
1397
  if (typeof data === "object" && data !== null) {
1398
+ this._isRemoteUpdate = true;
1126
1399
  this.clear();
1127
1400
  Object.entries(data).forEach(([key, entry]) => {
1128
1401
  if (entry && typeof entry === "object" && "value" in entry && "attributes" in entry) {
@@ -1131,21 +1404,24 @@ var MindCache = class {
1131
1404
  return;
1132
1405
  }
1133
1406
  let systemTags = attrs.systemTags || [];
1134
- if (!attrs.systemTags) {
1407
+ if (!attrs.systemTags || systemTags.length === 0) {
1135
1408
  systemTags = [];
1136
1409
  if (attrs.visible !== false) {
1137
1410
  systemTags.push("prompt");
1138
1411
  }
1139
1412
  if (attrs.readonly) {
1140
1413
  systemTags.push("readonly");
1414
+ } else {
1415
+ systemTags.push("LLMWrite");
1141
1416
  }
1142
1417
  if (attrs.hardcoded) {
1143
1418
  systemTags.push("protected");
1144
1419
  }
1145
1420
  if (attrs.template) {
1146
- systemTags.push("template");
1421
+ systemTags.push("ApplyTemplate");
1147
1422
  }
1148
1423
  }
1424
+ systemTags = this.normalizeSystemTags(systemTags);
1149
1425
  const contentTags = attrs.contentTags || attrs.tags || [];
1150
1426
  this.stm[key] = {
1151
1427
  value: entry.value,
@@ -1154,17 +1430,18 @@ var MindCache = class {
1154
1430
  contentTags,
1155
1431
  systemTags,
1156
1432
  zIndex: attrs.zIndex ?? 0,
1157
- // Sync legacy attributes
1433
+ // Sync legacy attributes FROM normalized systemTags
1158
1434
  tags: contentTags,
1159
- readonly: systemTags.includes("readonly"),
1160
- visible: systemTags.includes("prompt"),
1435
+ readonly: systemTags.includes("readonly") || !systemTags.includes("LLMWrite"),
1436
+ visible: this.hasSystemPrompt(systemTags),
1161
1437
  hardcoded: systemTags.includes("protected"),
1162
- template: systemTags.includes("template")
1438
+ template: systemTags.includes("ApplyTemplate") || systemTags.includes("template")
1163
1439
  }
1164
1440
  };
1165
1441
  }
1166
1442
  });
1167
1443
  this.notifyGlobalListeners();
1444
+ this._isRemoteUpdate = false;
1168
1445
  }
1169
1446
  }
1170
1447
  get_system_prompt() {
@@ -1173,13 +1450,14 @@ var MindCache = class {
1173
1450
  const sortedKeys = this.getSortedKeys();
1174
1451
  sortedKeys.forEach((key) => {
1175
1452
  const entry = this.stm[key];
1176
- if (entry.attributes.visible) {
1453
+ if (this.hasLLMRead(entry.attributes.systemTags) || entry.attributes.visible) {
1177
1454
  if (entry.attributes.type === "image") {
1178
1455
  promptLines.push(`image ${key} available`);
1179
1456
  return;
1180
1457
  }
1181
1458
  if (entry.attributes.type === "file") {
1182
- if (entry.attributes.readonly) {
1459
+ const canWrite2 = this.hasLLMWrite(entry.attributes.systemTags) || !entry.attributes.readonly && !entry.attributes.systemTags.includes("readonly");
1460
+ if (!canWrite2) {
1183
1461
  promptLines.push(`${key}: [${entry.attributes.type.toUpperCase()}] - ${entry.attributes.contentType || "unknown format"}`);
1184
1462
  } else {
1185
1463
  const sanitizedKey = key.replace(/[^a-zA-Z0-9_-]/g, "_");
@@ -1189,7 +1467,8 @@ var MindCache = class {
1189
1467
  }
1190
1468
  const value = this.get_value(key);
1191
1469
  const formattedValue = typeof value === "object" && value !== null ? JSON.stringify(value) : String(value);
1192
- if (entry.attributes.readonly) {
1470
+ const canWrite = this.hasLLMWrite(entry.attributes.systemTags) || !entry.attributes.readonly && !entry.attributes.systemTags.includes("readonly");
1471
+ if (!canWrite) {
1193
1472
  promptLines.push(`${key}: ${formattedValue}`);
1194
1473
  } else {
1195
1474
  const sanitizedKey = key.replace(/[^a-zA-Z0-9_-]/g, "_");
@@ -1217,7 +1496,7 @@ var MindCache = class {
1217
1496
  const sortedKeys = this.getSortedKeys();
1218
1497
  const writableKeys = sortedKeys.filter((key) => {
1219
1498
  const entry = this.stm[key];
1220
- return !entry.attributes.readonly;
1499
+ return this.hasLLMWrite(entry.attributes.systemTags) || !entry.attributes.readonly && !entry.attributes.systemTags.includes("readonly");
1221
1500
  });
1222
1501
  writableKeys.forEach((key) => {
1223
1502
  const sanitizedKey = key.replace(/[^a-zA-Z0-9_-]/g, "_");
@@ -1292,7 +1571,8 @@ var MindCache = class {
1292
1571
  return null;
1293
1572
  }
1294
1573
  const entry = this.stm[originalKey];
1295
- if (entry && entry.attributes.readonly) {
1574
+ const canWrite = entry && (this.hasLLMWrite(entry.attributes.systemTags) || !entry.attributes.readonly && !entry.attributes.systemTags.includes("readonly"));
1575
+ if (!canWrite) {
1296
1576
  return null;
1297
1577
  }
1298
1578
  this.set_value(originalKey, value);
@@ -1539,7 +1819,7 @@ var MindCache = class {
1539
1819
  entry.attributes.readonly = tags.includes("readonly");
1540
1820
  entry.attributes.visible = tags.includes("prompt");
1541
1821
  entry.attributes.hardcoded = tags.includes("protected");
1542
- entry.attributes.template = tags.includes("template");
1822
+ entry.attributes.template = tags.includes("ApplyTemplate") || tags.includes("template");
1543
1823
  }
1544
1824
  toMarkdown() {
1545
1825
  const now = /* @__PURE__ */ new Date();
@@ -1780,6 +2060,8 @@ var MindCache = class {
1780
2060
  }
1781
2061
  if (attrs.readonly) {
1782
2062
  systemTags.push("readonly");
2063
+ } else {
2064
+ systemTags.push("LLMWrite");
1783
2065
  }
1784
2066
  if (attrs.hardcoded) {
1785
2067
  systemTags.push("protected");
@@ -1787,7 +2069,9 @@ var MindCache = class {
1787
2069
  if (attrs.template) {
1788
2070
  systemTags.push("template");
1789
2071
  }
1790
- attrs.systemTags = systemTags;
2072
+ attrs.systemTags = this.normalizeSystemTags(systemTags);
2073
+ } else {
2074
+ attrs.systemTags = this.normalizeSystemTags(attrs.systemTags);
1791
2075
  }
1792
2076
  if (!attrs.contentTags) {
1793
2077
  attrs.contentTags = [];
@@ -1795,6 +2079,11 @@ var MindCache = class {
1795
2079
  if (!attrs.tags) {
1796
2080
  attrs.tags = [...attrs.contentTags];
1797
2081
  }
2082
+ const normalizedTags = attrs.systemTags || [];
2083
+ attrs.readonly = normalizedTags.includes("readonly") || !normalizedTags.includes("LLMWrite");
2084
+ attrs.visible = this.hasSystemPrompt(normalizedTags);
2085
+ attrs.hardcoded = normalizedTags.includes("protected");
2086
+ attrs.template = normalizedTags.includes("ApplyTemplate") || normalizedTags.includes("template");
1798
2087
  this.stm[key] = {
1799
2088
  value: entry.value,
1800
2089
  attributes: attrs