mindcache 2.3.0 → 2.4.1

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