mindcache 3.1.0 → 3.3.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.
package/dist/index.js CHANGED
@@ -354,6 +354,8 @@ var init_CloudAdapter = __esm({
354
354
  } else if (msg.type === "auth_error" || msg.type === "error") {
355
355
  this._state = "error";
356
356
  this.emit("error", new Error(msg.error));
357
+ } else {
358
+ console.debug("MindCache Cloud: Received message type:", msg.type, msg);
357
359
  }
358
360
  } else {
359
361
  const encoder = encoding__namespace.createEncoder();
@@ -462,8 +464,6 @@ var MindCache = class {
462
464
  normalized.push("readonly");
463
465
  } else if (hasLLMWrite) {
464
466
  normalized.push("LLMWrite");
465
- } else {
466
- normalized.push("LLMWrite");
467
467
  }
468
468
  return normalized;
469
469
  }
@@ -686,14 +686,16 @@ var MindCache = class {
686
686
  }
687
687
  const CloudAdapter2 = await this._getCloudAdapterClass();
688
688
  if (!this._cloudConfig.baseUrl) ;
689
- const baseUrl = (this._cloudConfig.baseUrl || "https://api.mindcache.io").replace("https://", "wss://").replace("http://", "ws://");
689
+ const baseUrl = (this._cloudConfig.baseUrl || "https://api.mindcache.dev").replace("https://", "wss://").replace("http://", "ws://");
690
690
  const adapter = new CloudAdapter2({
691
691
  instanceId: this._cloudConfig.instanceId,
692
692
  projectId: this._cloudConfig.projectId || "default",
693
693
  baseUrl,
694
694
  apiKey: this._cloudConfig.apiKey
695
695
  });
696
- if (this._cloudConfig.tokenEndpoint) {
696
+ if (this._cloudConfig.tokenProvider) {
697
+ adapter.setTokenProvider(this._cloudConfig.tokenProvider);
698
+ } else if (this._cloudConfig.tokenEndpoint) {
697
699
  const tokenEndpoint = this._cloudConfig.tokenEndpoint;
698
700
  const instanceId = this._cloudConfig.instanceId;
699
701
  let resolvedBaseUrl;
@@ -827,18 +829,35 @@ var MindCache = class {
827
829
  }
828
830
  // Deserialize state (for IndexedDBAdapter compatibility)
829
831
  deserialize(data) {
832
+ if (!data || typeof data !== "object") {
833
+ return;
834
+ }
830
835
  this.doc.transact(() => {
836
+ for (const key of this.rootMap.keys()) {
837
+ this.rootMap.delete(key);
838
+ }
831
839
  for (const [key, entry] of Object.entries(data)) {
832
840
  if (key.startsWith("$")) {
833
841
  continue;
834
842
  }
835
- let entryMap = this.rootMap.get(key);
836
- if (!entryMap) {
837
- entryMap = new Y__namespace.Map();
838
- this.rootMap.set(key, entryMap);
839
- }
843
+ const entryMap = new Y__namespace.Map();
844
+ this.rootMap.set(key, entryMap);
840
845
  entryMap.set("value", entry.value);
841
- entryMap.set("attributes", entry.attributes);
846
+ const attrs = entry.attributes || {};
847
+ const normalizedAttrs = {
848
+ type: attrs.type || "text",
849
+ contentTags: attrs.contentTags || [],
850
+ systemTags: attrs.systemTags || this.normalizeSystemTags(attrs.visible !== false ? ["prompt"] : []),
851
+ zIndex: attrs.zIndex ?? 0,
852
+ // Legacy fields
853
+ readonly: attrs.readonly ?? false,
854
+ visible: attrs.visible ?? true,
855
+ hardcoded: attrs.hardcoded ?? false,
856
+ template: attrs.template ?? false,
857
+ tags: attrs.tags || [],
858
+ contentType: attrs.contentType
859
+ };
860
+ entryMap.set("attributes", normalizedAttrs);
842
861
  }
843
862
  });
844
863
  }
@@ -876,16 +895,46 @@ var MindCache = class {
876
895
  }
877
896
  return false;
878
897
  }
879
- // InjectSTM replacement
880
- injectSTM(template, _processingStack) {
898
+ // InjectSTM replacement (private helper)
899
+ _injectSTMInternal(template, _processingStack) {
881
900
  return template.replace(/\{\{([^}]+)\}\}/g, (_, key) => {
882
901
  const val = this.get_value(key.trim(), _processingStack);
883
902
  return val !== void 0 ? String(val) : `{{${key}}}`;
884
903
  });
885
904
  }
905
+ /**
906
+ * Replace {{key}} placeholders in a template string with values from MindCache.
907
+ * @param template The template string with {{key}} placeholders
908
+ * @returns The template with placeholders replaced by values
909
+ */
910
+ injectSTM(template) {
911
+ return this._injectSTMInternal(template, /* @__PURE__ */ new Set());
912
+ }
886
913
  // Public API Methods
887
914
  getAll() {
888
- return this.serialize();
915
+ const result = {};
916
+ for (const [key] of this.rootMap) {
917
+ result[key] = this.get_value(key);
918
+ }
919
+ result["$date"] = this.get_value("$date");
920
+ result["$time"] = this.get_value("$time");
921
+ return result;
922
+ }
923
+ /**
924
+ * Get all entries with their full structure (value + attributes).
925
+ * Use this for UI/admin interfaces that need to display key properties.
926
+ * Unlike serialize(), this format is stable and won't change.
927
+ */
928
+ getAllEntries() {
929
+ const result = {};
930
+ for (const [key] of this.rootMap) {
931
+ const value = this.get_value(key);
932
+ const attributes = this.get_attributes(key);
933
+ if (attributes) {
934
+ result[key] = { value, attributes };
935
+ }
936
+ }
937
+ return result;
889
938
  }
890
939
  get_value(key, _processingStack) {
891
940
  if (key === "$date") {
@@ -915,7 +964,7 @@ var MindCache = class {
915
964
  if (typeof value === "string") {
916
965
  const stack = _processingStack || /* @__PURE__ */ new Set();
917
966
  stack.add(key);
918
- return this.injectSTM(value, stack);
967
+ return this._injectSTMInternal(value, stack);
919
968
  }
920
969
  }
921
970
  return value;
@@ -937,6 +986,27 @@ var MindCache = class {
937
986
  const entryMap = this.rootMap.get(key);
938
987
  return entryMap ? entryMap.get("attributes") : void 0;
939
988
  }
989
+ /**
990
+ * Update only the attributes of a key without modifying the value.
991
+ * Useful for updating tags, permissions etc. on document type keys.
992
+ */
993
+ set_attributes(key, attributes) {
994
+ if (key === "$date" || key === "$time" || key === "$version") {
995
+ return;
996
+ }
997
+ const entryMap = this.rootMap.get(key);
998
+ if (!entryMap) {
999
+ return;
1000
+ }
1001
+ this.doc.transact(() => {
1002
+ const existingAttrs = entryMap.get("attributes");
1003
+ const mergedAttrs = { ...existingAttrs, ...attributes };
1004
+ if (mergedAttrs.systemTags) {
1005
+ mergedAttrs.systemTags = this.normalizeSystemTags(mergedAttrs.systemTags);
1006
+ }
1007
+ entryMap.set("attributes", mergedAttrs);
1008
+ });
1009
+ }
940
1010
  set_value(key, value, attributes) {
941
1011
  if (key === "$date" || key === "$time" || key === "$version") {
942
1012
  return;
@@ -992,6 +1062,638 @@ var MindCache = class {
992
1062
  keys.forEach((k) => this.rootMap.delete(k));
993
1063
  });
994
1064
  }
1065
+ // ============================================
1066
+ // Restored Methods (from v2.x)
1067
+ // ============================================
1068
+ /**
1069
+ * Check if a key exists in MindCache.
1070
+ */
1071
+ has(key) {
1072
+ if (key === "$date" || key === "$time" || key === "$version") {
1073
+ return true;
1074
+ }
1075
+ return this.rootMap.has(key);
1076
+ }
1077
+ /**
1078
+ * Delete a key from MindCache.
1079
+ * @returns true if the key existed and was deleted
1080
+ */
1081
+ delete(key) {
1082
+ if (key === "$date" || key === "$time" || key === "$version") {
1083
+ return false;
1084
+ }
1085
+ if (!this.rootMap.has(key)) {
1086
+ return false;
1087
+ }
1088
+ this.rootMap.delete(key);
1089
+ this.notifyGlobalListeners();
1090
+ if (this.listeners[key]) {
1091
+ this.listeners[key].forEach((listener) => listener(void 0));
1092
+ }
1093
+ return true;
1094
+ }
1095
+ /** @deprecated Use get_value instead */
1096
+ get(key) {
1097
+ return this.get_value(key);
1098
+ }
1099
+ /** @deprecated Use set_value instead */
1100
+ set(key, value) {
1101
+ this.set_value(key, value);
1102
+ }
1103
+ /**
1104
+ * Update multiple values at once from an object.
1105
+ * @deprecated Use set_value for individual keys
1106
+ */
1107
+ update(data) {
1108
+ this.doc.transact(() => {
1109
+ for (const [key, value] of Object.entries(data)) {
1110
+ if (key !== "$date" && key !== "$time" && key !== "$version") {
1111
+ this.set_value(key, value);
1112
+ }
1113
+ }
1114
+ });
1115
+ this.notifyGlobalListeners();
1116
+ }
1117
+ /**
1118
+ * Get the number of keys in MindCache.
1119
+ */
1120
+ size() {
1121
+ return this.rootMap.size + 2;
1122
+ }
1123
+ /**
1124
+ * Get all keys in MindCache (including temporal keys).
1125
+ */
1126
+ keys() {
1127
+ const keys = Array.from(this.rootMap.keys());
1128
+ keys.push("$date", "$time");
1129
+ return keys;
1130
+ }
1131
+ /**
1132
+ * Get all values in MindCache (including temporal values).
1133
+ */
1134
+ values() {
1135
+ const result = [];
1136
+ for (const [key] of this.rootMap) {
1137
+ result.push(this.get_value(key));
1138
+ }
1139
+ result.push(this.get_value("$date"));
1140
+ result.push(this.get_value("$time"));
1141
+ return result;
1142
+ }
1143
+ /**
1144
+ * Get all key-value entries (including temporal entries).
1145
+ */
1146
+ entries() {
1147
+ const result = [];
1148
+ for (const [key] of this.rootMap) {
1149
+ result.push([key, this.get_value(key)]);
1150
+ }
1151
+ result.push(["$date", this.get_value("$date")]);
1152
+ result.push(["$time", this.get_value("$time")]);
1153
+ return result;
1154
+ }
1155
+ /**
1156
+ * Unsubscribe from key changes.
1157
+ * @deprecated Use the cleanup function returned by subscribe() instead
1158
+ */
1159
+ unsubscribe(key, listener) {
1160
+ if (this.listeners[key]) {
1161
+ this.listeners[key] = this.listeners[key].filter((l) => l !== listener);
1162
+ }
1163
+ }
1164
+ /**
1165
+ * Get the STM as a formatted string for LLM context.
1166
+ * @deprecated Use get_system_prompt() instead
1167
+ */
1168
+ getSTM() {
1169
+ return this.get_system_prompt();
1170
+ }
1171
+ /**
1172
+ * Get the STM as an object with values directly (no attributes).
1173
+ * Includes system keys ($date, $time).
1174
+ * @deprecated Use getAll() for full STM format
1175
+ */
1176
+ getSTMObject() {
1177
+ const result = {};
1178
+ for (const [key] of this.rootMap) {
1179
+ result[key] = this.get_value(key);
1180
+ }
1181
+ result["$date"] = this.get_value("$date");
1182
+ result["$time"] = this.get_value("$time");
1183
+ return result;
1184
+ }
1185
+ /**
1186
+ * Add a content tag to a key.
1187
+ * @returns true if the tag was added, false if key doesn't exist or tag already exists
1188
+ */
1189
+ addTag(key, tag) {
1190
+ if (key === "$date" || key === "$time" || key === "$version") {
1191
+ return false;
1192
+ }
1193
+ const entryMap = this.rootMap.get(key);
1194
+ if (!entryMap) {
1195
+ return false;
1196
+ }
1197
+ const attributes = entryMap.get("attributes");
1198
+ const contentTags = attributes?.contentTags || [];
1199
+ if (contentTags.includes(tag)) {
1200
+ return false;
1201
+ }
1202
+ this.doc.transact(() => {
1203
+ const newContentTags = [...contentTags, tag];
1204
+ entryMap.set("attributes", {
1205
+ ...attributes,
1206
+ contentTags: newContentTags,
1207
+ tags: newContentTags
1208
+ // Sync legacy tags array
1209
+ });
1210
+ });
1211
+ this.notifyGlobalListeners();
1212
+ return true;
1213
+ }
1214
+ /**
1215
+ * Remove a content tag from a key.
1216
+ * @returns true if the tag was removed
1217
+ */
1218
+ removeTag(key, tag) {
1219
+ if (key === "$date" || key === "$time" || key === "$version") {
1220
+ return false;
1221
+ }
1222
+ const entryMap = this.rootMap.get(key);
1223
+ if (!entryMap) {
1224
+ return false;
1225
+ }
1226
+ const attributes = entryMap.get("attributes");
1227
+ const contentTags = attributes?.contentTags || [];
1228
+ const tagIndex = contentTags.indexOf(tag);
1229
+ if (tagIndex === -1) {
1230
+ return false;
1231
+ }
1232
+ this.doc.transact(() => {
1233
+ const newContentTags = contentTags.filter((t) => t !== tag);
1234
+ entryMap.set("attributes", {
1235
+ ...attributes,
1236
+ contentTags: newContentTags,
1237
+ tags: newContentTags
1238
+ // Sync legacy tags array
1239
+ });
1240
+ });
1241
+ this.notifyGlobalListeners();
1242
+ return true;
1243
+ }
1244
+ /**
1245
+ * Get all content tags for a key.
1246
+ */
1247
+ getTags(key) {
1248
+ if (key === "$date" || key === "$time" || key === "$version") {
1249
+ return [];
1250
+ }
1251
+ const entryMap = this.rootMap.get(key);
1252
+ if (!entryMap) {
1253
+ return [];
1254
+ }
1255
+ const attributes = entryMap.get("attributes");
1256
+ return attributes?.contentTags || [];
1257
+ }
1258
+ /**
1259
+ * Get all unique content tags across all keys.
1260
+ */
1261
+ getAllTags() {
1262
+ const allTags = /* @__PURE__ */ new Set();
1263
+ for (const [, val] of this.rootMap) {
1264
+ const entryMap = val;
1265
+ const attributes = entryMap.get("attributes");
1266
+ if (attributes?.contentTags) {
1267
+ attributes.contentTags.forEach((tag) => allTags.add(tag));
1268
+ }
1269
+ }
1270
+ return Array.from(allTags);
1271
+ }
1272
+ /**
1273
+ * Check if a key has a specific content tag.
1274
+ */
1275
+ hasTag(key, tag) {
1276
+ if (key === "$date" || key === "$time" || key === "$version") {
1277
+ return false;
1278
+ }
1279
+ const entryMap = this.rootMap.get(key);
1280
+ if (!entryMap) {
1281
+ return false;
1282
+ }
1283
+ const attributes = entryMap.get("attributes");
1284
+ return attributes?.contentTags?.includes(tag) || false;
1285
+ }
1286
+ /**
1287
+ * Get all keys with a specific content tag as formatted string.
1288
+ */
1289
+ getTagged(tag) {
1290
+ const entries = [];
1291
+ const keys = this.getSortedKeys();
1292
+ keys.forEach((key) => {
1293
+ if (this.hasTag(key, tag)) {
1294
+ entries.push([key, this.get_value(key)]);
1295
+ }
1296
+ });
1297
+ return entries.map(([key, value]) => `${key}: ${value}`).join(", ");
1298
+ }
1299
+ /**
1300
+ * Get array of keys with a specific content tag.
1301
+ */
1302
+ getKeysByTag(tag) {
1303
+ const keys = this.getSortedKeys();
1304
+ return keys.filter((key) => this.hasTag(key, tag));
1305
+ }
1306
+ // ============================================
1307
+ // System Tag Methods (requires system access level)
1308
+ // ============================================
1309
+ /**
1310
+ * Add a system tag to a key (requires system access).
1311
+ * System tags: 'SystemPrompt', 'LLMRead', 'LLMWrite', 'readonly', 'protected', 'ApplyTemplate'
1312
+ */
1313
+ systemAddTag(key, tag) {
1314
+ if (!this.hasSystemAccess) {
1315
+ console.warn("MindCache: systemAddTag requires system access level");
1316
+ return false;
1317
+ }
1318
+ if (key === "$date" || key === "$time" || key === "$version") {
1319
+ return false;
1320
+ }
1321
+ const entryMap = this.rootMap.get(key);
1322
+ if (!entryMap) {
1323
+ return false;
1324
+ }
1325
+ const attributes = entryMap.get("attributes");
1326
+ const systemTags = attributes?.systemTags || [];
1327
+ if (systemTags.includes(tag)) {
1328
+ return false;
1329
+ }
1330
+ this.doc.transact(() => {
1331
+ const newSystemTags = [...systemTags, tag];
1332
+ const normalizedTags = this.normalizeSystemTags(newSystemTags);
1333
+ entryMap.set("attributes", {
1334
+ ...attributes,
1335
+ systemTags: normalizedTags
1336
+ });
1337
+ });
1338
+ this.notifyGlobalListeners();
1339
+ return true;
1340
+ }
1341
+ /**
1342
+ * Remove a system tag from a key (requires system access).
1343
+ */
1344
+ systemRemoveTag(key, tag) {
1345
+ if (!this.hasSystemAccess) {
1346
+ console.warn("MindCache: systemRemoveTag requires system access level");
1347
+ return false;
1348
+ }
1349
+ if (key === "$date" || key === "$time" || key === "$version") {
1350
+ return false;
1351
+ }
1352
+ const entryMap = this.rootMap.get(key);
1353
+ if (!entryMap) {
1354
+ return false;
1355
+ }
1356
+ const attributes = entryMap.get("attributes");
1357
+ const systemTags = attributes?.systemTags || [];
1358
+ const tagIndex = systemTags.indexOf(tag);
1359
+ if (tagIndex === -1) {
1360
+ return false;
1361
+ }
1362
+ this.doc.transact(() => {
1363
+ const newSystemTags = systemTags.filter((t) => t !== tag);
1364
+ entryMap.set("attributes", {
1365
+ ...attributes,
1366
+ systemTags: newSystemTags
1367
+ });
1368
+ });
1369
+ this.notifyGlobalListeners();
1370
+ return true;
1371
+ }
1372
+ /**
1373
+ * Get all system tags for a key (requires system access).
1374
+ */
1375
+ systemGetTags(key) {
1376
+ if (!this.hasSystemAccess) {
1377
+ console.warn("MindCache: systemGetTags requires system access level");
1378
+ return [];
1379
+ }
1380
+ if (key === "$date" || key === "$time" || key === "$version") {
1381
+ return [];
1382
+ }
1383
+ const entryMap = this.rootMap.get(key);
1384
+ if (!entryMap) {
1385
+ return [];
1386
+ }
1387
+ const attributes = entryMap.get("attributes");
1388
+ return attributes?.systemTags || [];
1389
+ }
1390
+ /**
1391
+ * Check if a key has a specific system tag (requires system access).
1392
+ */
1393
+ systemHasTag(key, tag) {
1394
+ if (!this.hasSystemAccess) {
1395
+ console.warn("MindCache: systemHasTag requires system access level");
1396
+ return false;
1397
+ }
1398
+ if (key === "$date" || key === "$time" || key === "$version") {
1399
+ return false;
1400
+ }
1401
+ const entryMap = this.rootMap.get(key);
1402
+ if (!entryMap) {
1403
+ return false;
1404
+ }
1405
+ const attributes = entryMap.get("attributes");
1406
+ return attributes?.systemTags?.includes(tag) || false;
1407
+ }
1408
+ /**
1409
+ * Set all system tags for a key at once (requires system access).
1410
+ */
1411
+ systemSetTags(key, tags) {
1412
+ if (!this.hasSystemAccess) {
1413
+ console.warn("MindCache: systemSetTags requires system access level");
1414
+ return false;
1415
+ }
1416
+ if (key === "$date" || key === "$time" || key === "$version") {
1417
+ return false;
1418
+ }
1419
+ const entryMap = this.rootMap.get(key);
1420
+ if (!entryMap) {
1421
+ return false;
1422
+ }
1423
+ this.doc.transact(() => {
1424
+ const attributes = entryMap.get("attributes");
1425
+ entryMap.set("attributes", {
1426
+ ...attributes,
1427
+ systemTags: [...tags]
1428
+ });
1429
+ });
1430
+ this.notifyGlobalListeners();
1431
+ return true;
1432
+ }
1433
+ /**
1434
+ * Get all keys with a specific system tag (requires system access).
1435
+ */
1436
+ systemGetKeysByTag(tag) {
1437
+ if (!this.hasSystemAccess) {
1438
+ console.warn("MindCache: systemGetKeysByTag requires system access level");
1439
+ return [];
1440
+ }
1441
+ const keys = this.getSortedKeys();
1442
+ return keys.filter((key) => this.systemHasTag(key, tag));
1443
+ }
1444
+ /**
1445
+ * Helper to get sorted keys (by zIndex).
1446
+ */
1447
+ getSortedKeys() {
1448
+ const entries = [];
1449
+ for (const [key, val] of this.rootMap) {
1450
+ const entryMap = val;
1451
+ const attributes = entryMap.get("attributes");
1452
+ entries.push({ key, zIndex: attributes?.zIndex ?? 0 });
1453
+ }
1454
+ return entries.sort((a, b) => a.zIndex - b.zIndex).map((e) => e.key);
1455
+ }
1456
+ /**
1457
+ * Serialize to JSON string.
1458
+ */
1459
+ toJSON() {
1460
+ return JSON.stringify(this.serialize());
1461
+ }
1462
+ /**
1463
+ * Deserialize from JSON string.
1464
+ */
1465
+ fromJSON(jsonString) {
1466
+ try {
1467
+ const data = JSON.parse(jsonString);
1468
+ this.deserialize(data);
1469
+ } catch (error) {
1470
+ console.error("MindCache: Failed to deserialize JSON:", error);
1471
+ }
1472
+ }
1473
+ /**
1474
+ * Export to Markdown format.
1475
+ */
1476
+ toMarkdown() {
1477
+ const now = /* @__PURE__ */ new Date();
1478
+ const lines = [];
1479
+ const appendixEntries = [];
1480
+ let appendixCounter = 0;
1481
+ lines.push("# MindCache STM Export");
1482
+ lines.push("");
1483
+ lines.push(`Export Date: ${now.toISOString().split("T")[0]}`);
1484
+ lines.push("");
1485
+ lines.push("---");
1486
+ lines.push("");
1487
+ lines.push("## STM Entries");
1488
+ lines.push("");
1489
+ const sortedKeys = this.getSortedKeys();
1490
+ sortedKeys.forEach((key) => {
1491
+ const entryMap = this.rootMap.get(key);
1492
+ if (!entryMap) {
1493
+ return;
1494
+ }
1495
+ const attributes = entryMap.get("attributes");
1496
+ const value = entryMap.get("value");
1497
+ if (attributes?.hardcoded) {
1498
+ return;
1499
+ }
1500
+ lines.push(`### ${key}`);
1501
+ const entryType = attributes?.type || "text";
1502
+ lines.push(`- **Type**: \`${entryType}\``);
1503
+ lines.push(`- **Readonly**: \`${attributes?.readonly ?? false}\``);
1504
+ lines.push(`- **Visible**: \`${attributes?.visible ?? true}\``);
1505
+ lines.push(`- **Template**: \`${attributes?.template ?? false}\``);
1506
+ lines.push(`- **Z-Index**: \`${attributes?.zIndex ?? 0}\``);
1507
+ if (attributes?.contentTags && attributes.contentTags.length > 0) {
1508
+ lines.push(`- **Tags**: \`${attributes.contentTags.join("`, `")}\``);
1509
+ }
1510
+ if (attributes?.contentType) {
1511
+ lines.push(`- **Content Type**: \`${attributes.contentType}\``);
1512
+ }
1513
+ if (entryType === "image" || entryType === "file") {
1514
+ const label = String.fromCharCode(65 + appendixCounter);
1515
+ appendixCounter++;
1516
+ lines.push(`- **Value**: [See Appendix ${label}]`);
1517
+ appendixEntries.push({
1518
+ key,
1519
+ type: entryType,
1520
+ contentType: attributes?.contentType || "application/octet-stream",
1521
+ base64: value,
1522
+ label
1523
+ });
1524
+ } else if (entryType === "json") {
1525
+ lines.push("- **Value**:");
1526
+ lines.push("```json");
1527
+ try {
1528
+ const jsonValue = typeof value === "string" ? value : JSON.stringify(value, null, 2);
1529
+ lines.push(jsonValue);
1530
+ } catch {
1531
+ lines.push(String(value));
1532
+ }
1533
+ lines.push("```");
1534
+ } else {
1535
+ lines.push(`- **Value**: ${value}`);
1536
+ }
1537
+ lines.push("");
1538
+ });
1539
+ if (appendixEntries.length > 0) {
1540
+ lines.push("---");
1541
+ lines.push("");
1542
+ lines.push("## Appendix: Binary Data");
1543
+ lines.push("");
1544
+ appendixEntries.forEach((entry) => {
1545
+ lines.push(`### Appendix ${entry.label}: ${entry.key}`);
1546
+ lines.push(`- **Type**: \`${entry.type}\``);
1547
+ lines.push(`- **Content Type**: \`${entry.contentType}\``);
1548
+ lines.push("- **Base64 Data**:");
1549
+ lines.push("```");
1550
+ lines.push(entry.base64);
1551
+ lines.push("```");
1552
+ lines.push("");
1553
+ });
1554
+ }
1555
+ return lines.join("\n");
1556
+ }
1557
+ /**
1558
+ * Import from Markdown format.
1559
+ */
1560
+ fromMarkdown(markdown) {
1561
+ const lines = markdown.split("\n");
1562
+ let currentKey = null;
1563
+ let currentAttributes = {};
1564
+ let currentValue = null;
1565
+ let inCodeBlock = false;
1566
+ let codeBlockContent = [];
1567
+ for (const line of lines) {
1568
+ if (line.startsWith("### ") && !line.startsWith("### Appendix")) {
1569
+ if (currentKey && currentValue !== null) {
1570
+ this.set_value(currentKey, currentValue, currentAttributes);
1571
+ }
1572
+ currentKey = line.substring(4).trim();
1573
+ currentAttributes = {};
1574
+ currentValue = null;
1575
+ continue;
1576
+ }
1577
+ if (line.startsWith("### Appendix ")) {
1578
+ const match = line.match(/### Appendix ([A-Z]): (.+)/);
1579
+ if (match) {
1580
+ currentKey = match[2];
1581
+ }
1582
+ continue;
1583
+ }
1584
+ if (line.startsWith("- **Type**:")) {
1585
+ const type = line.match(/`(.+)`/)?.[1];
1586
+ if (type) {
1587
+ currentAttributes.type = type;
1588
+ }
1589
+ continue;
1590
+ }
1591
+ if (line.startsWith("- **Readonly**:")) {
1592
+ currentAttributes.readonly = line.includes("`true`");
1593
+ continue;
1594
+ }
1595
+ if (line.startsWith("- **Visible**:")) {
1596
+ currentAttributes.visible = line.includes("`true`");
1597
+ continue;
1598
+ }
1599
+ if (line.startsWith("- **Template**:")) {
1600
+ currentAttributes.template = line.includes("`true`");
1601
+ continue;
1602
+ }
1603
+ if (line.startsWith("- **Z-Index**:")) {
1604
+ const zIndex = parseInt(line.match(/`(\d+)`/)?.[1] || "0", 10);
1605
+ currentAttributes.zIndex = zIndex;
1606
+ continue;
1607
+ }
1608
+ if (line.startsWith("- **Tags**:")) {
1609
+ const tags = line.match(/`([^`]+)`/g)?.map((t) => t.slice(1, -1)) || [];
1610
+ currentAttributes.contentTags = tags;
1611
+ currentAttributes.tags = tags;
1612
+ continue;
1613
+ }
1614
+ if (line.startsWith("- **Content Type**:")) {
1615
+ currentAttributes.contentType = line.match(/`(.+)`/)?.[1];
1616
+ continue;
1617
+ }
1618
+ if (line.startsWith("- **Value**:") && !line.includes("[See Appendix")) {
1619
+ currentValue = line.substring(12).trim();
1620
+ continue;
1621
+ }
1622
+ if (line === "```json" || line === "```") {
1623
+ if (inCodeBlock) {
1624
+ inCodeBlock = false;
1625
+ if (currentKey && codeBlockContent.length > 0) {
1626
+ currentValue = codeBlockContent.join("\n");
1627
+ }
1628
+ codeBlockContent = [];
1629
+ } else {
1630
+ inCodeBlock = true;
1631
+ }
1632
+ continue;
1633
+ }
1634
+ if (inCodeBlock) {
1635
+ codeBlockContent.push(line);
1636
+ }
1637
+ }
1638
+ if (currentKey && currentValue !== null) {
1639
+ this.set_value(currentKey, currentValue, currentAttributes);
1640
+ }
1641
+ }
1642
+ /**
1643
+ * Set base64 binary data.
1644
+ */
1645
+ set_base64(key, base64Data, contentType, type = "file", attributes) {
1646
+ if (!this.validateContentType(type, contentType)) {
1647
+ throw new Error(`Invalid content type ${contentType} for type ${type}`);
1648
+ }
1649
+ const fileAttributes = {
1650
+ type,
1651
+ contentType,
1652
+ ...attributes
1653
+ };
1654
+ this.set_value(key, base64Data, fileAttributes);
1655
+ }
1656
+ /**
1657
+ * Add an image from base64 data.
1658
+ */
1659
+ add_image(key, base64Data, contentType = "image/jpeg", attributes) {
1660
+ if (!contentType.startsWith("image/")) {
1661
+ throw new Error(`Invalid image content type: ${contentType}. Must start with 'image/'`);
1662
+ }
1663
+ this.set_base64(key, base64Data, contentType, "image", attributes);
1664
+ }
1665
+ /**
1666
+ * Get the data URL for an image or file key.
1667
+ */
1668
+ get_data_url(key) {
1669
+ const entryMap = this.rootMap.get(key);
1670
+ if (!entryMap) {
1671
+ return void 0;
1672
+ }
1673
+ const attributes = entryMap.get("attributes");
1674
+ if (attributes?.type !== "image" && attributes?.type !== "file") {
1675
+ return void 0;
1676
+ }
1677
+ if (!attributes?.contentType) {
1678
+ return void 0;
1679
+ }
1680
+ const value = entryMap.get("value");
1681
+ return this.createDataUrl(value, attributes.contentType);
1682
+ }
1683
+ /**
1684
+ * Get the base64 data for an image or file key.
1685
+ */
1686
+ get_base64(key) {
1687
+ const entryMap = this.rootMap.get(key);
1688
+ if (!entryMap) {
1689
+ return void 0;
1690
+ }
1691
+ const attributes = entryMap.get("attributes");
1692
+ if (attributes?.type !== "image" && attributes?.type !== "file") {
1693
+ return void 0;
1694
+ }
1695
+ return entryMap.get("value");
1696
+ }
995
1697
  // File methods
996
1698
  async set_file(key, file, attributes) {
997
1699
  const base64 = await this.encodeFileToBase64(file);
@@ -1312,10 +2014,14 @@ var MindCache = class {
1312
2014
  const sanitizedKey = this.sanitizeKeyForTool(key);
1313
2015
  if (isWritable) {
1314
2016
  if (isDocument) {
1315
- lines.push(`${key}: ${displayValue}. Document tools: write_${sanitizedKey}, append_${sanitizedKey}, edit_${sanitizedKey}`);
2017
+ lines.push(
2018
+ `${key}: ${displayValue}. Document tools: write_${sanitizedKey}, append_${sanitizedKey}, edit_${sanitizedKey}`
2019
+ );
1316
2020
  } else {
1317
2021
  const oldValueHint = displayValue ? ` This tool DOES NOT append \u2014 start your response with the old value (${displayValue})` : "";
1318
- lines.push(`${key}: ${displayValue}. You can rewrite "${key}" by using the write_${sanitizedKey} tool.${oldValueHint}`);
2022
+ lines.push(
2023
+ `${key}: ${displayValue}. You can rewrite "${key}" by using the write_${sanitizedKey} tool.${oldValueHint}`
2024
+ );
1319
2025
  }
1320
2026
  } else {
1321
2027
  lines.push(`${key}: ${displayValue}`);
@@ -1456,8 +2162,12 @@ function useMindCache(options) {
1456
2162
  };
1457
2163
  }
1458
2164
 
2165
+ // src/index.ts
2166
+ var mindcache = new MindCache();
2167
+
1459
2168
  exports.DEFAULT_KEY_ATTRIBUTES = DEFAULT_KEY_ATTRIBUTES;
1460
2169
  exports.MindCache = MindCache;
2170
+ exports.mindcache = mindcache;
1461
2171
  exports.useMindCache = useMindCache;
1462
2172
  //# sourceMappingURL=index.js.map
1463
2173
  //# sourceMappingURL=index.js.map