@tyvm/knowhow 0.0.61 → 0.0.63

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.
Files changed (29) hide show
  1. package/package.json +1 -1
  2. package/src/chat/modules/AgentModule.ts +6 -6
  3. package/src/processors/JsonCompressor.ts +496 -0
  4. package/src/processors/TokenCompressor.ts +194 -125
  5. package/src/processors/ToolResponseCache.ts +64 -11
  6. package/src/processors/index.ts +1 -0
  7. package/tests/compressor/bigstring.test.ts +352 -2
  8. package/tests/compressor/githubjson.txt +1 -0
  9. package/tests/compressor/toolResponseCache.test.ts +303 -0
  10. package/ts_build/package.json +1 -1
  11. package/ts_build/src/chat/modules/AgentModule.js +5 -4
  12. package/ts_build/src/chat/modules/AgentModule.js.map +1 -1
  13. package/ts_build/src/processors/JsonCompressor.d.ts +36 -0
  14. package/ts_build/src/processors/JsonCompressor.js +295 -0
  15. package/ts_build/src/processors/JsonCompressor.js.map +1 -0
  16. package/ts_build/src/processors/TokenCompressor.d.ts +23 -5
  17. package/ts_build/src/processors/TokenCompressor.js +106 -70
  18. package/ts_build/src/processors/TokenCompressor.js.map +1 -1
  19. package/ts_build/src/processors/ToolResponseCache.d.ts +4 -2
  20. package/ts_build/src/processors/ToolResponseCache.js +50 -10
  21. package/ts_build/src/processors/ToolResponseCache.js.map +1 -1
  22. package/ts_build/src/processors/index.d.ts +1 -0
  23. package/ts_build/src/processors/index.js +3 -1
  24. package/ts_build/src/processors/index.js.map +1 -1
  25. package/ts_build/tests/compressor/bigstring.test.js +209 -0
  26. package/ts_build/tests/compressor/bigstring.test.js.map +1 -1
  27. package/ts_build/tests/compressor/toolResponseCache.test.d.ts +1 -0
  28. package/ts_build/tests/compressor/toolResponseCache.test.js +240 -0
  29. package/ts_build/tests/compressor/toolResponseCache.test.js.map +1 -0
@@ -0,0 +1,295 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JsonCompressor = void 0;
4
+ class JsonCompressor {
5
+ deduplicationMap = new Map();
6
+ objectSeenCount = new Map();
7
+ propertyNamesMap = new Map();
8
+ propertyNamesSeenCount = new Map();
9
+ compressionThreshold;
10
+ maxTokens;
11
+ toolName;
12
+ storage;
13
+ constructor(storage, compressionThreshold, maxTokens, toolName) {
14
+ this.storage = storage;
15
+ this.compressionThreshold = compressionThreshold;
16
+ this.maxTokens = maxTokens;
17
+ this.toolName = toolName;
18
+ }
19
+ clearDeduplication() {
20
+ this.deduplicationMap.clear();
21
+ this.objectSeenCount.clear();
22
+ this.propertyNamesMap.clear();
23
+ this.propertyNamesSeenCount.clear();
24
+ }
25
+ updateSettings(compressionThreshold, maxTokens) {
26
+ this.compressionThreshold = compressionThreshold;
27
+ this.maxTokens = maxTokens;
28
+ }
29
+ tryParseJson(content) {
30
+ try {
31
+ const parsed = JSON.parse(content);
32
+ if (typeof parsed === 'string') {
33
+ try {
34
+ return this.tryParseJson(parsed);
35
+ }
36
+ catch (e) {
37
+ return parsed;
38
+ }
39
+ }
40
+ if (parsed &&
41
+ typeof parsed === 'object' &&
42
+ Array.isArray(parsed.content) &&
43
+ parsed.content.length > 0) {
44
+ const firstContent = parsed.content[0];
45
+ if (firstContent.type === 'text' && typeof firstContent.text === 'string') {
46
+ try {
47
+ const nestedData = this.tryParseJson(firstContent.text);
48
+ return {
49
+ _mcp_format: true,
50
+ _raw_structure: { content: [{ type: 'text' }] },
51
+ _data: nestedData
52
+ };
53
+ }
54
+ catch (e) {
55
+ return parsed;
56
+ }
57
+ }
58
+ }
59
+ return parsed;
60
+ }
61
+ catch {
62
+ return null;
63
+ }
64
+ }
65
+ generateSchema(obj, maxDepth = 3, currentDepth = 0) {
66
+ if (currentDepth > maxDepth) {
67
+ return { type: 'any' };
68
+ }
69
+ if (obj && typeof obj === 'object' && obj._mcp_format === true && obj._data) {
70
+ const dataSchema = this.generateSchema(obj._data, maxDepth, currentDepth);
71
+ return {
72
+ type: 'mcp_response',
73
+ properties: {
74
+ _data: dataSchema
75
+ }
76
+ };
77
+ }
78
+ if (obj === null) {
79
+ return { type: 'null' };
80
+ }
81
+ if (Array.isArray(obj)) {
82
+ if (obj.length === 0) {
83
+ return { type: 'array', items: { type: 'unknown' } };
84
+ }
85
+ const sample = obj.slice(0, 3);
86
+ const itemSchemas = sample.map(item => this.generateSchema(item, maxDepth, currentDepth + 1));
87
+ return { type: 'array', items: itemSchemas[0] };
88
+ }
89
+ if (typeof obj === 'object') {
90
+ const properties = {};
91
+ for (const [key, value] of Object.entries(obj)) {
92
+ properties[key] = this.generateSchema(value, maxDepth, currentDepth + 1);
93
+ }
94
+ return { type: 'object', properties };
95
+ }
96
+ return { type: typeof obj };
97
+ }
98
+ calculateSimilarity(str1, str2) {
99
+ const maxLen = Math.max(str1.length, str2.length);
100
+ if (maxLen === 0)
101
+ return 1.0;
102
+ let commonPrefixLen = 0;
103
+ const minLen = Math.min(str1.length, str2.length);
104
+ for (let i = 0; i < minLen; i++) {
105
+ if (str1[i] === str2[i]) {
106
+ commonPrefixLen++;
107
+ }
108
+ else {
109
+ break;
110
+ }
111
+ }
112
+ return commonPrefixLen / maxLen;
113
+ }
114
+ detectLowSignalProperties(obj) {
115
+ if (!obj || typeof obj !== 'object' || Array.isArray(obj)) {
116
+ return { lowSignal: [], metadata: {} };
117
+ }
118
+ const lowSignal = [];
119
+ const metadata = {};
120
+ const entries = Object.entries(obj);
121
+ const urlPattern = /^https?:\/\//;
122
+ const urlProps = [];
123
+ for (const [key, value] of entries) {
124
+ if (typeof value === 'string' && urlPattern.test(value)) {
125
+ urlProps.push(key);
126
+ }
127
+ }
128
+ if (urlProps.length >= 3) {
129
+ const urlValues = urlProps.map(key => obj[key]);
130
+ let totalSimilarity = 0;
131
+ let comparisons = 0;
132
+ for (let i = 0; i < urlValues.length - 1; i++) {
133
+ for (let j = i + 1; j < urlValues.length; j++) {
134
+ totalSimilarity += this.calculateSimilarity(urlValues[i], urlValues[j]);
135
+ comparisons++;
136
+ }
137
+ }
138
+ const avgSimilarity = comparisons > 0 ? totalSimilarity / comparisons : 0;
139
+ if (avgSimilarity > 0.6) {
140
+ lowSignal.push(...urlProps);
141
+ metadata.url_similarity = avgSimilarity;
142
+ metadata.url_count = urlProps.length;
143
+ }
144
+ }
145
+ const lowSignalPatterns = [/_url$/, /_id$/, /^node_id$/, /^avatar_url$/, /^gravatar_id$/];
146
+ for (const [key, value] of entries) {
147
+ if (lowSignalPatterns.some(pattern => pattern.test(key)) && !lowSignal.includes(key)) {
148
+ lowSignal.push(key);
149
+ }
150
+ }
151
+ return { lowSignal, metadata };
152
+ }
153
+ compressObjectWithLowSignalDetection(obj, path = "") {
154
+ if (!obj || typeof obj !== 'object' || Array.isArray(obj)) {
155
+ return obj;
156
+ }
157
+ const { lowSignal, metadata } = this.detectLowSignalProperties(obj);
158
+ if (lowSignal.length < 5) {
159
+ return obj;
160
+ }
161
+ const highSignal = {};
162
+ const compressed = {};
163
+ for (const [key, value] of Object.entries(obj)) {
164
+ if (lowSignal.includes(key)) {
165
+ compressed[key] = value;
166
+ }
167
+ else {
168
+ highSignal[key] = value;
169
+ }
170
+ }
171
+ const compressedHash = this.hashObject(compressed);
172
+ let compressedKey = this.deduplicationMap.get(compressedHash);
173
+ if (!compressedKey) {
174
+ compressedKey = this.storage.generateKey();
175
+ this.deduplicationMap.set(compressedHash, compressedKey);
176
+ const compressionMetadata = {
177
+ compressed_properties: compressed,
178
+ compression_reason: 'low_signal_detection',
179
+ similarity_score: metadata.url_similarity,
180
+ };
181
+ this.storage.storeString(compressedKey, JSON.stringify(compressionMetadata));
182
+ }
183
+ const propertyNamesHash = this.hashObject(lowSignal);
184
+ const propertyNamesSeenCount = this.propertyNamesSeenCount.get(propertyNamesHash) || 0;
185
+ this.propertyNamesSeenCount.set(propertyNamesHash, propertyNamesSeenCount + 1);
186
+ let propertyNamesValue = lowSignal;
187
+ if (propertyNamesSeenCount === 0) {
188
+ const propertyNamesKey = this.storage.generateKey();
189
+ this.propertyNamesMap.set(propertyNamesHash, propertyNamesKey);
190
+ this.storage.storeString(propertyNamesKey, JSON.stringify(lowSignal));
191
+ propertyNamesValue = lowSignal;
192
+ }
193
+ else if (propertyNamesSeenCount >= 1) {
194
+ const existingPropertyNamesKey = this.propertyNamesMap.get(propertyNamesHash);
195
+ propertyNamesValue = `[DEDUPLICATED_ARRAY]\nKey: ${existingPropertyNamesKey}`;
196
+ }
197
+ return {
198
+ ...highSignal,
199
+ _compressed_properties_key: compressedKey,
200
+ _compressed_property_names: propertyNamesValue,
201
+ _compression_info: `${lowSignal.length} low-signal properties compressed (URLs, IDs). Use expandTokens with key "${compressedKey}" to retrieve.`
202
+ };
203
+ }
204
+ hashObject(obj) {
205
+ const normalized = JSON.stringify(obj, Object.keys(obj).sort());
206
+ let hash = 0;
207
+ for (let i = 0; i < normalized.length; i++) {
208
+ const char = normalized.charCodeAt(i);
209
+ hash = ((hash << 5) - hash) + char;
210
+ hash = hash & hash;
211
+ }
212
+ return hash.toString(36);
213
+ }
214
+ compressJsonProperties(obj, path = "") {
215
+ if (path === "" &&
216
+ this.storage.estimateTokens(JSON.stringify(obj)) <= this.maxTokens) {
217
+ return obj;
218
+ }
219
+ if (Array.isArray(obj)) {
220
+ const processedItems = obj.map((item, index) => this.compressJsonProperties(item, `${path}[${index}]`));
221
+ const finalArray = [];
222
+ let currentChunk = [];
223
+ for (let i = processedItems.length - 1; i >= 0; i--) {
224
+ const item = processedItems[i];
225
+ currentChunk.unshift(item);
226
+ const chunkString = JSON.stringify(currentChunk);
227
+ const chunkTokens = this.storage.estimateTokens(chunkString);
228
+ if (chunkTokens > this.compressionThreshold) {
229
+ const key = this.storage.generateKey();
230
+ this.storage.storeString(key, chunkString);
231
+ const stub = `[COMPRESSED_JSON_ARRAY_CHUNK - ${chunkTokens} tokens, ${currentChunk.length} items]\nKey: ${key}\nPath: ${path}[${i}...${i + currentChunk.length - 1}]\nPreview: ${chunkString.substring(0, 100)}...\n[Use ${this.toolName} tool with key "${key}" to retrieve this chunk]`;
232
+ finalArray.unshift(stub);
233
+ currentChunk = [];
234
+ }
235
+ }
236
+ if (currentChunk.length > 0) {
237
+ finalArray.unshift(...currentChunk);
238
+ }
239
+ return finalArray;
240
+ }
241
+ if (obj && typeof obj === "object") {
242
+ const objHash = this.hashObject(obj);
243
+ const existingKey = this.deduplicationMap.get(objHash);
244
+ if (existingKey) {
245
+ return `[DEDUPLICATED_OBJECT]\nKey: ${existingKey}\nPath: ${path}\n[Use ${this.toolName} tool with key "${existingKey}" to retrieve content]`;
246
+ }
247
+ const seenCount = this.objectSeenCount.get(objHash) || 0;
248
+ this.objectSeenCount.set(objHash, seenCount + 1);
249
+ const isFirstOccurrence = seenCount === 1;
250
+ const objWithLowSignalCompressed = this.compressObjectWithLowSignalDetection(obj, path);
251
+ const objToProcess = objWithLowSignalCompressed !== obj ? objWithLowSignalCompressed : obj;
252
+ const result = {};
253
+ for (const [key, value] of Object.entries(objToProcess)) {
254
+ const newPath = path ? `${path}.${key}` : key;
255
+ result[key] = this.compressJsonProperties(value, newPath);
256
+ }
257
+ const objectAsString = JSON.stringify(result);
258
+ const tokens = this.storage.estimateTokens(objectAsString);
259
+ if (isFirstOccurrence && tokens > 100) {
260
+ const key = this.storage.generateKey();
261
+ this.deduplicationMap.set(objHash, key);
262
+ this.storage.storeString(key, objectAsString);
263
+ return result;
264
+ }
265
+ if (tokens > this.compressionThreshold) {
266
+ const key = this.storage.generateKey();
267
+ this.storage.storeString(key, objectAsString);
268
+ return `[COMPRESSED_JSON_OBJECT - ${tokens} tokens]\nKey: ${key}\nPath: ${path}\nKeys: ${Object.keys(result).join(", ")}\nPreview: ${objectAsString.substring(0, 200)}...\n[Use ${this.toolName} tool with key "${key}" to retrieve full content]`;
269
+ }
270
+ return result;
271
+ }
272
+ if (typeof obj === "string") {
273
+ const parsedJson = this.tryParseJson(obj);
274
+ if (parsedJson) {
275
+ const compressedJson = this.compressJsonProperties(parsedJson, path);
276
+ const compressedJsonString = JSON.stringify(compressedJson, null, 2);
277
+ const originalTokens = this.storage.estimateTokens(obj);
278
+ const compressedTokens = this.storage.estimateTokens(compressedJsonString);
279
+ if (compressedTokens < originalTokens * 0.8) {
280
+ return compressedJsonString;
281
+ }
282
+ }
283
+ const tokens = this.storage.estimateTokens(obj);
284
+ if (tokens > this.compressionThreshold) {
285
+ const key = this.storage.generateKey();
286
+ this.storage.storeString(key, obj);
287
+ return `[COMPRESSED_JSON_PROPERTY - ${tokens} tokens]\nKey: ${key}\nPath: ${path}\nPreview: ${obj.substring(0, 200)}...\n[Use ${this.toolName} tool with key "${key}" to retrieve full content]`;
288
+ }
289
+ return obj;
290
+ }
291
+ return obj;
292
+ }
293
+ }
294
+ exports.JsonCompressor = JsonCompressor;
295
+ //# sourceMappingURL=JsonCompressor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JsonCompressor.js","sourceRoot":"","sources":["../../../src/processors/JsonCompressor.ts"],"names":[],"mappings":"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"}
@@ -1,22 +1,35 @@
1
1
  import { Message, Tool } from "../clients/types";
2
2
  import { MessageProcessorFunction } from "../services/MessageProcessor";
3
3
  import { ToolsService } from "../services";
4
- export declare class TokenCompressor {
4
+ import { JsonSchema, JsonCompressorStorage } from "./JsonCompressor";
5
+ export interface KeyInfo {
6
+ key: string;
7
+ size: number;
8
+ preview: string;
9
+ tokens?: number;
10
+ type?: string;
11
+ depth?: number;
12
+ childKeys?: string[];
13
+ nextChunkKey?: string;
14
+ }
15
+ export declare class TokenCompressor implements JsonCompressorStorage {
5
16
  private storage;
6
17
  private keyPrefix;
7
18
  private toolName;
8
19
  private compressionThreshold;
9
20
  private characterLimit;
10
- private maxTokens;
21
+ maxTokens: number;
22
+ private jsonCompressor;
11
23
  constructor(toolsService?: ToolsService);
12
- private estimateTokens;
24
+ estimateTokens(text: string): number;
13
25
  setCompressionThreshold(threshold: number): void;
14
26
  private setMaxTokens;
15
- private tryParseJson;
27
+ tryParseJson(content: string): any | null;
16
28
  compressStringInChunks(content: string, path?: string): string;
29
+ private isAlreadyCompressed;
17
30
  compressContent(content: string, path?: string): string;
18
31
  compressJsonProperties(obj: any, path?: string): any;
19
- private generateKey;
32
+ generateKey(): string;
20
33
  compressMessage(message: Message): Promise<void>;
21
34
  createProcessor(filterFn?: (msg: Message) => boolean): MessageProcessorFunction;
22
35
  retrieveString(key: string): string | null;
@@ -25,5 +38,10 @@ export declare class TokenCompressor {
25
38
  getStorageKeys(): string[];
26
39
  getStorageSize(): number;
27
40
  registerTool(toolsService?: ToolsService): void;
41
+ getSchema(key: string): JsonSchema | null;
42
+ getCompressedProperties(key: string): any | null;
43
+ getFullObject(mainObj: any, compressedKey: string): any;
44
+ extractKeys(content: string): string[];
45
+ getKeyChain(key: string): KeyInfo[];
28
46
  }
29
47
  export declare const expandTokensDefinition: Tool;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.expandTokensDefinition = exports.TokenCompressor = void 0;
4
+ const JsonCompressor_1 = require("./JsonCompressor");
4
5
  class TokenCompressor {
5
6
  storage = {};
6
7
  keyPrefix = "compressed_";
@@ -8,7 +9,9 @@ class TokenCompressor {
8
9
  compressionThreshold = 4000;
9
10
  characterLimit = this.compressionThreshold * 4;
10
11
  maxTokens = this.compressionThreshold * 2;
12
+ jsonCompressor;
11
13
  constructor(toolsService) {
14
+ this.jsonCompressor = new JsonCompressor_1.JsonCompressor(this, this.compressionThreshold, this.maxTokens, this.toolName);
12
15
  this.registerTool(toolsService);
13
16
  }
14
17
  estimateTokens(text) {
@@ -17,19 +20,16 @@ class TokenCompressor {
17
20
  setCompressionThreshold(threshold) {
18
21
  this.compressionThreshold = threshold;
19
22
  this.characterLimit = threshold * 4;
23
+ this.jsonCompressor.updateSettings(threshold, this.maxTokens);
20
24
  }
21
25
  setMaxTokens(maxTokens) {
22
26
  if (maxTokens > this.maxTokens) {
23
27
  this.maxTokens = maxTokens;
28
+ this.jsonCompressor.updateSettings(this.compressionThreshold, maxTokens);
24
29
  }
25
30
  }
26
31
  tryParseJson(content) {
27
- try {
28
- return JSON.parse(content);
29
- }
30
- catch {
31
- return null;
32
- }
32
+ return this.jsonCompressor.tryParseJson(content);
33
33
  }
34
34
  compressStringInChunks(content, path = "") {
35
35
  if (content.length <= this.characterLimit) {
@@ -64,7 +64,20 @@ class TokenCompressor {
64
64
  const chunkCount = chunks.length;
65
65
  return `[COMPRESSED_STRING - ${totalTokens} tokens in ${chunkCount} chunks]\nKey: ${firstKey}\nPath: ${path}\nPreview: ${content.substring(0, 200)}...\n[Use ${this.toolName} tool with key "${firstKey}" to retrieve content. Follow NEXT_CHUNK_KEY references for complete content]`;
66
66
  }
67
+ isAlreadyCompressed(content) {
68
+ if (content.includes("[COMPRESSED_STRING")) {
69
+ return true;
70
+ }
71
+ const parsed = this.tryParseJson(content);
72
+ if (parsed && parsed._schema_key && typeof parsed._schema_key === "string") {
73
+ return true;
74
+ }
75
+ return false;
76
+ }
67
77
  compressContent(content, path = "") {
78
+ if (this.isAlreadyCompressed(content)) {
79
+ return content;
80
+ }
68
81
  const tokens = this.estimateTokens(content);
69
82
  const thresholdToUse = path === "" ? this.compressionThreshold : this.maxTokens;
70
83
  if (tokens <= thresholdToUse) {
@@ -72,77 +85,33 @@ class TokenCompressor {
72
85
  }
73
86
  const jsonObj = this.tryParseJson(content);
74
87
  if (jsonObj) {
75
- const compressedObj = this.compressJsonProperties(jsonObj, path);
76
- const compressedContent = JSON.stringify(compressedObj, null, 2);
88
+ const dataToCompress = jsonObj._mcp_format ? jsonObj._data : jsonObj;
89
+ const schema = this.jsonCompressor.generateSchema(jsonObj);
90
+ const schemaKey = this.generateKey();
91
+ this.storeString(schemaKey, JSON.stringify(schema));
92
+ const compressedObj = this.compressJsonProperties(dataToCompress, path || "data");
93
+ const finalCompressedObj = jsonObj._mcp_format
94
+ ? {
95
+ _mcp_format: true,
96
+ _raw_structure: jsonObj._raw_structure,
97
+ _data: compressedObj,
98
+ }
99
+ : compressedObj;
100
+ const resultWithSchema = typeof finalCompressedObj === "object" &&
101
+ !Array.isArray(finalCompressedObj)
102
+ ? { ...finalCompressedObj, _schema_key: schemaKey }
103
+ : { _schema_key: schemaKey, data: finalCompressedObj };
104
+ const compressedContent = JSON.stringify(resultWithSchema, null, 2);
77
105
  const compressedTokens = this.estimateTokens(compressedContent);
78
- if (compressedTokens < tokens * 0.8) {
106
+ const compressionThreshold = 0.6;
107
+ if (compressedTokens < tokens * compressionThreshold) {
79
108
  return compressedContent;
80
109
  }
81
110
  }
82
111
  return this.compressStringInChunks(content, path);
83
112
  }
84
113
  compressJsonProperties(obj, path = "") {
85
- if (path === "" &&
86
- this.estimateTokens(JSON.stringify(obj)) <= this.maxTokens) {
87
- return obj;
88
- }
89
- if (Array.isArray(obj)) {
90
- const processedItems = obj.map((item, index) => this.compressJsonProperties(item, `${path}[${index}]`));
91
- const finalArray = [];
92
- let currentChunk = [];
93
- for (let i = processedItems.length - 1; i >= 0; i--) {
94
- const item = processedItems[i];
95
- currentChunk.unshift(item);
96
- const chunkString = JSON.stringify(currentChunk);
97
- const chunkTokens = this.estimateTokens(chunkString);
98
- if (chunkTokens > this.compressionThreshold) {
99
- const key = this.generateKey();
100
- this.storeString(key, chunkString);
101
- const stub = `[COMPRESSED_JSON_ARRAY_CHUNK - ${chunkTokens} tokens, ${currentChunk.length} items]\nKey: ${key}\nPath: ${path}[${i}...${i + currentChunk.length - 1}]\nPreview: ${chunkString.substring(0, 100)}...\n[Use ${this.toolName} tool with key "${key}" to retrieve this chunk]`;
102
- finalArray.unshift(stub);
103
- currentChunk = [];
104
- }
105
- }
106
- if (currentChunk.length > 0) {
107
- finalArray.unshift(...currentChunk);
108
- }
109
- return finalArray;
110
- }
111
- if (obj && typeof obj === "object") {
112
- const result = {};
113
- for (const [key, value] of Object.entries(obj)) {
114
- const newPath = path ? `${path}.${key}` : key;
115
- result[key] = this.compressJsonProperties(value, newPath);
116
- }
117
- const objectAsString = JSON.stringify(result);
118
- const tokens = this.estimateTokens(objectAsString);
119
- if (tokens > this.compressionThreshold) {
120
- const key = this.generateKey();
121
- this.storeString(key, objectAsString);
122
- return `[COMPRESSED_JSON_OBJECT - ${tokens} tokens]\nKey: ${key}\nPath: ${path}\nKeys: ${Object.keys(result).join(", ")}\nPreview: ${objectAsString.substring(0, 200)}...\n[Use ${this.toolName} tool with key "${key}" to retrieve full content]`;
123
- }
124
- return result;
125
- }
126
- if (typeof obj === "string") {
127
- const parsedJson = this.tryParseJson(obj);
128
- if (parsedJson) {
129
- const compressedJson = this.compressJsonProperties(parsedJson, path);
130
- const compressedJsonString = JSON.stringify(compressedJson, null, 2);
131
- const originalTokens = this.estimateTokens(obj);
132
- const compressedTokens = this.estimateTokens(compressedJsonString);
133
- if (compressedTokens < originalTokens * 0.8) {
134
- return compressedJsonString;
135
- }
136
- }
137
- const tokens = this.estimateTokens(obj);
138
- if (tokens > this.compressionThreshold) {
139
- const key = this.generateKey();
140
- this.storeString(key, obj);
141
- return `[COMPRESSED_JSON_PROPERTY - ${tokens} tokens]\nKey: ${key}\nPath: ${path}\nPreview: ${obj.substring(0, 200)}...\n[Use ${this.toolName} tool with key "${key}" to retrieve full content]`;
142
- }
143
- return obj;
144
- }
145
- return obj;
114
+ return this.jsonCompressor.compressJsonProperties(obj, path);
146
115
  }
147
116
  generateKey() {
148
117
  return `${this.keyPrefix}${Date.now()}_${Math.random()
@@ -182,6 +151,7 @@ class TokenCompressor {
182
151
  }
183
152
  clearStorage() {
184
153
  this.storage = {};
154
+ this.jsonCompressor.clearDeduplication();
185
155
  }
186
156
  getStorageKeys() {
187
157
  return Object.keys(this.storage);
@@ -203,6 +173,72 @@ class TokenCompressor {
203
173
  });
204
174
  }
205
175
  }
176
+ getSchema(key) {
177
+ const schemaKey = `${key}_schema`;
178
+ const schemaStr = this.storage[schemaKey];
179
+ if (!schemaStr) {
180
+ return null;
181
+ }
182
+ try {
183
+ return JSON.parse(schemaStr);
184
+ }
185
+ catch (e) {
186
+ return null;
187
+ }
188
+ }
189
+ getCompressedProperties(key) {
190
+ const content = this.storage[key];
191
+ if (!content) {
192
+ return null;
193
+ }
194
+ try {
195
+ const metadata = JSON.parse(content);
196
+ return metadata.compressed_properties || null;
197
+ }
198
+ catch (e) {
199
+ return null;
200
+ }
201
+ }
202
+ getFullObject(mainObj, compressedKey) {
203
+ if (!mainObj || typeof mainObj !== "object") {
204
+ return mainObj;
205
+ }
206
+ const compressed = this.getCompressedProperties(compressedKey);
207
+ if (!compressed) {
208
+ return mainObj;
209
+ }
210
+ const { _compressed_properties_key, _compressed_property_names, _compression_info, ...highSignal } = mainObj;
211
+ return { ...highSignal, ...compressed };
212
+ }
213
+ extractKeys(content) {
214
+ const keys = [];
215
+ const keyPattern = /\$expandTokens\[([^\]]+)\]|Key:\s*([^\s\n]+)/g;
216
+ let match;
217
+ while ((match = keyPattern.exec(content)) !== null) {
218
+ const key = match[1] || match[2];
219
+ if (key && !keys.includes(key)) {
220
+ keys.push(key);
221
+ }
222
+ }
223
+ return keys;
224
+ }
225
+ getKeyChain(key) {
226
+ const chain = [];
227
+ let currentKey = key;
228
+ while (currentKey) {
229
+ const content = this.storage[currentKey];
230
+ if (!content)
231
+ break;
232
+ chain.push({
233
+ key: currentKey,
234
+ size: content.length,
235
+ preview: content.substring(0, 100),
236
+ });
237
+ const nextMatch = content.match(/NEXT_CHUNK_KEY:\s*([^\s\n]+)/);
238
+ currentKey = nextMatch ? nextMatch[1] : null;
239
+ }
240
+ return chain;
241
+ }
206
242
  }
207
243
  exports.TokenCompressor = TokenCompressor;
208
244
  exports.expandTokensDefinition = {