@loxia-labs/loxia-autopilot-one 1.0.1 → 1.0.3
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/README.md +44 -54
- package/bin/cli.js +1 -115
- package/bin/loxia-terminal-v2.js +3 -0
- package/bin/loxia-terminal.js +3 -0
- package/bin/start-with-terminal.js +3 -0
- package/package.json +14 -15
- package/scripts/install-scanners.js +1 -235
- package/src/analyzers/CSSAnalyzer.js +1 -297
- package/src/analyzers/ConfigValidator.js +1 -690
- package/src/analyzers/ESLintAnalyzer.js +1 -320
- package/src/analyzers/JavaScriptAnalyzer.js +1 -261
- package/src/analyzers/PrettierFormatter.js +1 -247
- package/src/analyzers/PythonAnalyzer.js +1 -266
- package/src/analyzers/SecurityAnalyzer.js +1 -729
- package/src/analyzers/TypeScriptAnalyzer.js +1 -247
- package/src/analyzers/codeCloneDetector/analyzer.js +1 -344
- package/src/analyzers/codeCloneDetector/detector.js +1 -203
- package/src/analyzers/codeCloneDetector/index.js +1 -160
- package/src/analyzers/codeCloneDetector/parser.js +1 -199
- package/src/analyzers/codeCloneDetector/reporter.js +1 -148
- package/src/analyzers/codeCloneDetector/scanner.js +1 -59
- package/src/core/agentPool.js +1 -1474
- package/src/core/agentScheduler.js +1 -2147
- package/src/core/contextManager.js +1 -709
- package/src/core/messageProcessor.js +1 -732
- package/src/core/orchestrator.js +1 -548
- package/src/core/stateManager.js +1 -877
- package/src/index.js +1 -631
- package/src/interfaces/cli.js +1 -549
- package/src/interfaces/terminal/__tests__/smoke/advancedFeatures.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/agentControl.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/agents.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/components.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/connection.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/enhancements.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/imports.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/messages.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/tools.test.js +1 -0
- package/src/interfaces/terminal/api/apiClient.js +1 -0
- package/src/interfaces/terminal/api/messageRouter.js +1 -0
- package/src/interfaces/terminal/api/session.js +1 -0
- package/src/interfaces/terminal/api/websocket.js +1 -0
- package/src/interfaces/terminal/components/AgentCreator.js +1 -0
- package/src/interfaces/terminal/components/AgentEditor.js +1 -0
- package/src/interfaces/terminal/components/AgentSwitcher.js +1 -0
- package/src/interfaces/terminal/components/ErrorBoundary.js +1 -0
- package/src/interfaces/terminal/components/ErrorPanel.js +1 -0
- package/src/interfaces/terminal/components/Header.js +1 -0
- package/src/interfaces/terminal/components/HelpPanel.js +1 -0
- package/src/interfaces/terminal/components/InputBox.js +1 -0
- package/src/interfaces/terminal/components/Layout.js +1 -0
- package/src/interfaces/terminal/components/LoadingSpinner.js +1 -0
- package/src/interfaces/terminal/components/MessageList.js +1 -0
- package/src/interfaces/terminal/components/MultilineTextInput.js +1 -0
- package/src/interfaces/terminal/components/SearchPanel.js +1 -0
- package/src/interfaces/terminal/components/SettingsPanel.js +1 -0
- package/src/interfaces/terminal/components/StatusBar.js +1 -0
- package/src/interfaces/terminal/components/TextInput.js +1 -0
- package/src/interfaces/terminal/config/agentEditorConstants.js +1 -0
- package/src/interfaces/terminal/config/constants.js +1 -0
- package/src/interfaces/terminal/index.js +1 -0
- package/src/interfaces/terminal/state/useAgentControl.js +1 -0
- package/src/interfaces/terminal/state/useAgents.js +1 -0
- package/src/interfaces/terminal/state/useConnection.js +1 -0
- package/src/interfaces/terminal/state/useMessages.js +1 -0
- package/src/interfaces/terminal/state/useTools.js +1 -0
- package/src/interfaces/terminal/utils/debugLogger.js +1 -0
- package/src/interfaces/terminal/utils/settingsStorage.js +1 -0
- package/src/interfaces/terminal/utils/theme.js +1 -0
- package/src/interfaces/webServer.js +1 -2162
- package/src/modules/fileExplorer/controller.js +1 -280
- package/src/modules/fileExplorer/index.js +1 -37
- package/src/modules/fileExplorer/middleware.js +1 -92
- package/src/modules/fileExplorer/routes.js +1 -125
- package/src/modules/fileExplorer/types.js +1 -44
- package/src/services/aiService.js +1 -1232
- package/src/services/apiKeyManager.js +1 -164
- package/src/services/benchmarkService.js +1 -366
- package/src/services/budgetService.js +1 -539
- package/src/services/contextInjectionService.js +1 -247
- package/src/services/conversationCompactionService.js +1 -637
- package/src/services/errorHandler.js +1 -810
- package/src/services/fileAttachmentService.js +1 -544
- package/src/services/modelRouterService.js +1 -366
- package/src/services/modelsService.js +1 -322
- package/src/services/qualityInspector.js +1 -796
- package/src/services/tokenCountingService.js +1 -536
- package/src/tools/agentCommunicationTool.js +1 -1344
- package/src/tools/agentDelayTool.js +1 -485
- package/src/tools/asyncToolManager.js +1 -604
- package/src/tools/baseTool.js +1 -800
- package/src/tools/browserTool.js +1 -920
- package/src/tools/cloneDetectionTool.js +1 -621
- package/src/tools/dependencyResolverTool.js +1 -1215
- package/src/tools/fileContentReplaceTool.js +1 -875
- package/src/tools/fileSystemTool.js +1 -1107
- package/src/tools/fileTreeTool.js +1 -853
- package/src/tools/imageTool.js +1 -901
- package/src/tools/importAnalyzerTool.js +1 -1060
- package/src/tools/jobDoneTool.js +1 -248
- package/src/tools/seekTool.js +1 -956
- package/src/tools/staticAnalysisTool.js +1 -1778
- package/src/tools/taskManagerTool.js +1 -2873
- package/src/tools/terminalTool.js +1 -2304
- package/src/tools/webTool.js +1 -1430
- package/src/types/agent.js +1 -519
- package/src/types/contextReference.js +1 -972
- package/src/types/conversation.js +1 -730
- package/src/types/toolCommand.js +1 -747
- package/src/utilities/attachmentValidator.js +1 -292
- package/src/utilities/configManager.js +1 -582
- package/src/utilities/constants.js +1 -722
- package/src/utilities/directoryAccessManager.js +1 -535
- package/src/utilities/fileProcessor.js +1 -307
- package/src/utilities/logger.js +1 -436
- package/src/utilities/tagParser.js +1 -1246
- package/src/utilities/toolConstants.js +1 -317
- package/web-ui/build/index.html +2 -2
- package/web-ui/build/static/{index-Dy2bYbOa.css → index-CClD1090.css} +1 -1
- package/web-ui/build/static/{index-CjkkcnFA.js → index-lCBai6dX.js} +66 -67
|
@@ -1,637 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ConversationCompactionService - Intelligent conversation compactization
|
|
3
|
-
*
|
|
4
|
-
* Purpose:
|
|
5
|
-
* - Compress long conversations while preserving critical information
|
|
6
|
-
* - Support multiple compaction strategies
|
|
7
|
-
* - Maintain conversation continuity and context
|
|
8
|
-
* - Enable agents to perform long-running tasks
|
|
9
|
-
*
|
|
10
|
-
* Strategies:
|
|
11
|
-
* 1. Summarization - AI-based intelligent summary (sandwich approach)
|
|
12
|
-
* 2. Truncation - Fast extraction for model switching
|
|
13
|
-
* 3. Aggressive - More aggressive summarization for retry scenarios
|
|
14
|
-
*
|
|
15
|
-
* Key Features:
|
|
16
|
-
* - Token-aware segment identification
|
|
17
|
-
* - Preservation guidelines (high/medium/low priority)
|
|
18
|
-
* - Quality validation
|
|
19
|
-
* - Model switching support
|
|
20
|
-
* - Comprehensive metadata tracking
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
import {
|
|
24
|
-
COMPACTION_CONFIG,
|
|
25
|
-
COMPACTION_STRATEGIES,
|
|
26
|
-
TOKEN_COUNTING_MODES,
|
|
27
|
-
} from '../utilities/constants.js';
|
|
28
|
-
|
|
29
|
-
class ConversationCompactionService {
|
|
30
|
-
constructor(tokenCountingService, aiService, logger) {
|
|
31
|
-
this.tokenCountingService = tokenCountingService;
|
|
32
|
-
this.aiService = aiService;
|
|
33
|
-
this.logger = logger;
|
|
34
|
-
|
|
35
|
-
// Summary generation prompt template
|
|
36
|
-
this.summaryPromptTemplate = this._createSummaryPromptTemplate();
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Main compaction entry point - determines strategy and executes
|
|
41
|
-
* @param {Array} messages - Original messages array
|
|
42
|
-
* @param {string} currentModel - Current model being used
|
|
43
|
-
* @param {string} targetModel - Target model (may differ if switching)
|
|
44
|
-
* @param {Object} options - Compaction options
|
|
45
|
-
* @returns {Promise<Object>} Compaction result with messages and metadata
|
|
46
|
-
*/
|
|
47
|
-
async compactConversation(messages, currentModel, targetModel, options = {}) {
|
|
48
|
-
const startTime = Date.now();
|
|
49
|
-
|
|
50
|
-
try {
|
|
51
|
-
// Validate inputs
|
|
52
|
-
if (!Array.isArray(messages) || messages.length === 0) {
|
|
53
|
-
throw new Error('Messages array is required and cannot be empty');
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (messages.length < COMPACTION_CONFIG.MIN_MESSAGES_FOR_COMPACTION) {
|
|
57
|
-
this.logger.warn('Too few messages for compaction', {
|
|
58
|
-
messageCount: messages.length,
|
|
59
|
-
minimum: COMPACTION_CONFIG.MIN_MESSAGES_FOR_COMPACTION
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
return {
|
|
63
|
-
compactedMessages: messages,
|
|
64
|
-
strategy: 'none',
|
|
65
|
-
originalTokenCount: 0,
|
|
66
|
-
compactedTokenCount: 0,
|
|
67
|
-
reductionPercent: 0,
|
|
68
|
-
skipped: true,
|
|
69
|
-
reason: 'Too few messages'
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Determine strategy
|
|
74
|
-
const isModelSwitch = currentModel !== targetModel;
|
|
75
|
-
const isRetry = options.isRetry || false;
|
|
76
|
-
|
|
77
|
-
let strategy;
|
|
78
|
-
if (isModelSwitch) {
|
|
79
|
-
strategy = COMPACTION_STRATEGIES.TRUNCATION;
|
|
80
|
-
} else if (isRetry) {
|
|
81
|
-
strategy = COMPACTION_STRATEGIES.AGGRESSIVE;
|
|
82
|
-
} else {
|
|
83
|
-
strategy = options.strategy || COMPACTION_STRATEGIES.SUMMARIZATION;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
this.logger.info('Starting conversation compaction', {
|
|
87
|
-
messageCount: messages.length,
|
|
88
|
-
currentModel,
|
|
89
|
-
targetModel,
|
|
90
|
-
strategy,
|
|
91
|
-
isModelSwitch,
|
|
92
|
-
isRetry
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
// Execute strategy
|
|
96
|
-
let result;
|
|
97
|
-
switch (strategy) {
|
|
98
|
-
case COMPACTION_STRATEGIES.SUMMARIZATION:
|
|
99
|
-
result = await this._compactWithSummarization(messages, currentModel, options);
|
|
100
|
-
break;
|
|
101
|
-
|
|
102
|
-
case COMPACTION_STRATEGIES.TRUNCATION:
|
|
103
|
-
result = await this._compactWithTruncation(messages, targetModel, options);
|
|
104
|
-
break;
|
|
105
|
-
|
|
106
|
-
case COMPACTION_STRATEGIES.AGGRESSIVE:
|
|
107
|
-
result = await this._compactWithAggressiveSummarization(messages, currentModel, options);
|
|
108
|
-
break;
|
|
109
|
-
|
|
110
|
-
default:
|
|
111
|
-
throw new Error(`Unknown compaction strategy: ${strategy}`);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Add execution metadata
|
|
115
|
-
const executionTime = Date.now() - startTime;
|
|
116
|
-
result.executionTime = executionTime;
|
|
117
|
-
result.timestamp = new Date().toISOString();
|
|
118
|
-
|
|
119
|
-
this.logger.info('Compaction completed successfully', {
|
|
120
|
-
strategy: result.strategy,
|
|
121
|
-
originalMessages: messages.length,
|
|
122
|
-
compactedMessages: result.compactedMessages.length,
|
|
123
|
-
originalTokens: result.originalTokenCount,
|
|
124
|
-
compactedTokens: result.compactedTokenCount,
|
|
125
|
-
reductionPercent: result.reductionPercent.toFixed(2),
|
|
126
|
-
executionTime: `${executionTime}ms`
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
return result;
|
|
130
|
-
|
|
131
|
-
} catch (error) {
|
|
132
|
-
const executionTime = Date.now() - startTime;
|
|
133
|
-
|
|
134
|
-
this.logger.error('Compaction failed', {
|
|
135
|
-
error: error.message,
|
|
136
|
-
messageCount: messages.length,
|
|
137
|
-
currentModel,
|
|
138
|
-
targetModel,
|
|
139
|
-
executionTime: `${executionTime}ms`
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
throw error;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Strategy 1: Intelligent summarization with sandwich approach
|
|
148
|
-
* Preserves beginning (15%) + AI summary of middle + end (35%)
|
|
149
|
-
* @private
|
|
150
|
-
*/
|
|
151
|
-
async _compactWithSummarization(messages, model, options) {
|
|
152
|
-
const strategy = COMPACTION_STRATEGIES.SUMMARIZATION;
|
|
153
|
-
|
|
154
|
-
// Count tokens in original conversation
|
|
155
|
-
const originalTokenCount = await this.tokenCountingService.estimateConversationTokens(
|
|
156
|
-
messages,
|
|
157
|
-
model,
|
|
158
|
-
TOKEN_COUNTING_MODES.ACCURATE
|
|
159
|
-
);
|
|
160
|
-
|
|
161
|
-
// Identify segments using token-based boundaries
|
|
162
|
-
const segments = await this._identifySegments(
|
|
163
|
-
messages,
|
|
164
|
-
model,
|
|
165
|
-
COMPACTION_CONFIG.BEGINNING_SEGMENT_PERCENTAGE,
|
|
166
|
-
COMPACTION_CONFIG.END_SEGMENT_PERCENTAGE
|
|
167
|
-
);
|
|
168
|
-
|
|
169
|
-
this.logger.debug('Segments identified for summarization', {
|
|
170
|
-
beginningMessages: segments.beginning.length,
|
|
171
|
-
middleMessages: segments.middle.length,
|
|
172
|
-
endMessages: segments.end.length,
|
|
173
|
-
middleStartIndex: segments.middleStartIndex,
|
|
174
|
-
middleEndIndex: segments.middleEndIndex,
|
|
175
|
-
totalMessages: messages.length
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
// Generate summary of middle segment
|
|
179
|
-
const summary = await this._generateSummary(
|
|
180
|
-
segments.middle,
|
|
181
|
-
model,
|
|
182
|
-
{
|
|
183
|
-
...options,
|
|
184
|
-
middleStartIndex: segments.middleStartIndex,
|
|
185
|
-
middleEndIndex: segments.middleEndIndex
|
|
186
|
-
}
|
|
187
|
-
);
|
|
188
|
-
|
|
189
|
-
// Construct compacted conversation
|
|
190
|
-
const compactedMessages = [
|
|
191
|
-
...segments.beginning,
|
|
192
|
-
summary,
|
|
193
|
-
...segments.end
|
|
194
|
-
];
|
|
195
|
-
|
|
196
|
-
// Count tokens in compacted conversation
|
|
197
|
-
const compactedTokenCount = await this.tokenCountingService.estimateConversationTokens(
|
|
198
|
-
compactedMessages,
|
|
199
|
-
model,
|
|
200
|
-
TOKEN_COUNTING_MODES.ACCURATE
|
|
201
|
-
);
|
|
202
|
-
|
|
203
|
-
// Calculate reduction
|
|
204
|
-
const reductionPercent = ((originalTokenCount - compactedTokenCount) / originalTokenCount) * 100;
|
|
205
|
-
|
|
206
|
-
return {
|
|
207
|
-
compactedMessages,
|
|
208
|
-
strategy,
|
|
209
|
-
originalTokenCount,
|
|
210
|
-
compactedTokenCount,
|
|
211
|
-
reductionPercent,
|
|
212
|
-
segments: {
|
|
213
|
-
beginningCount: segments.beginning.length,
|
|
214
|
-
middleCount: segments.middle.length,
|
|
215
|
-
endCount: segments.end.length,
|
|
216
|
-
summaryInserted: true
|
|
217
|
-
}
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* Strategy 2: Fast truncation for model switching
|
|
223
|
-
* Preserves beginning (30%) + separator + end (50%)
|
|
224
|
-
* No AI call required - fast extraction
|
|
225
|
-
* @private
|
|
226
|
-
*/
|
|
227
|
-
async _compactWithTruncation(messages, targetModel, options) {
|
|
228
|
-
const strategy = COMPACTION_STRATEGIES.TRUNCATION;
|
|
229
|
-
|
|
230
|
-
// Get target context window
|
|
231
|
-
const targetContextWindow = this.tokenCountingService.getModelContextWindow(targetModel);
|
|
232
|
-
const targetTokenCount = Math.floor(targetContextWindow * 0.8); // Use 80% of context
|
|
233
|
-
|
|
234
|
-
// Count tokens in original conversation
|
|
235
|
-
const originalTokenCount = await this.tokenCountingService.estimateConversationTokens(
|
|
236
|
-
messages,
|
|
237
|
-
targetModel,
|
|
238
|
-
TOKEN_COUNTING_MODES.ACCURATE
|
|
239
|
-
);
|
|
240
|
-
|
|
241
|
-
// Identify segments using token-based boundaries (30% + 50%)
|
|
242
|
-
const segments = await this._identifySegments(
|
|
243
|
-
messages,
|
|
244
|
-
targetModel,
|
|
245
|
-
COMPACTION_CONFIG.TRUNCATION_BEGINNING_PERCENTAGE,
|
|
246
|
-
COMPACTION_CONFIG.TRUNCATION_END_PERCENTAGE
|
|
247
|
-
);
|
|
248
|
-
|
|
249
|
-
this.logger.debug('Segments identified for truncation', {
|
|
250
|
-
beginningMessages: segments.beginning.length,
|
|
251
|
-
middleMessages: segments.middle.length,
|
|
252
|
-
endMessages: segments.end.length,
|
|
253
|
-
targetTokenCount,
|
|
254
|
-
originalTokenCount
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
// Create separator message
|
|
258
|
-
const separatorMessage = {
|
|
259
|
-
role: 'system',
|
|
260
|
-
content: COMPACTION_CONFIG.COMPACTION_SEPARATOR_MESSAGE,
|
|
261
|
-
type: 'separator',
|
|
262
|
-
timestamp: new Date().toISOString(),
|
|
263
|
-
metadata: {
|
|
264
|
-
truncatedMessages: segments.middle.length,
|
|
265
|
-
reason: 'Model switch - middle section removed to fit target context window'
|
|
266
|
-
}
|
|
267
|
-
};
|
|
268
|
-
|
|
269
|
-
// Construct compacted conversation
|
|
270
|
-
const compactedMessages = [
|
|
271
|
-
...segments.beginning,
|
|
272
|
-
separatorMessage,
|
|
273
|
-
...segments.end
|
|
274
|
-
];
|
|
275
|
-
|
|
276
|
-
// Count tokens in compacted conversation
|
|
277
|
-
const compactedTokenCount = await this.tokenCountingService.estimateConversationTokens(
|
|
278
|
-
compactedMessages,
|
|
279
|
-
targetModel,
|
|
280
|
-
TOKEN_COUNTING_MODES.ACCURATE
|
|
281
|
-
);
|
|
282
|
-
|
|
283
|
-
// Calculate reduction
|
|
284
|
-
const reductionPercent = ((originalTokenCount - compactedTokenCount) / originalTokenCount) * 100;
|
|
285
|
-
|
|
286
|
-
return {
|
|
287
|
-
compactedMessages,
|
|
288
|
-
strategy,
|
|
289
|
-
originalTokenCount,
|
|
290
|
-
compactedTokenCount,
|
|
291
|
-
reductionPercent,
|
|
292
|
-
segments: {
|
|
293
|
-
beginningCount: segments.beginning.length,
|
|
294
|
-
middleCount: segments.middle.length,
|
|
295
|
-
endCount: segments.end.length,
|
|
296
|
-
summaryInserted: false
|
|
297
|
-
}
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
/**
|
|
302
|
-
* Strategy 3: Aggressive summarization for retry scenarios
|
|
303
|
-
* More aggressive compression: 10% beginning + summary + 30% end
|
|
304
|
-
* @private
|
|
305
|
-
*/
|
|
306
|
-
async _compactWithAggressiveSummarization(messages, model, options) {
|
|
307
|
-
const strategy = COMPACTION_STRATEGIES.AGGRESSIVE;
|
|
308
|
-
|
|
309
|
-
// Count tokens in original conversation
|
|
310
|
-
const originalTokenCount = await this.tokenCountingService.estimateConversationTokens(
|
|
311
|
-
messages,
|
|
312
|
-
model,
|
|
313
|
-
TOKEN_COUNTING_MODES.ACCURATE
|
|
314
|
-
);
|
|
315
|
-
|
|
316
|
-
// Identify segments with aggressive percentages
|
|
317
|
-
const segments = await this._identifySegments(
|
|
318
|
-
messages,
|
|
319
|
-
model,
|
|
320
|
-
COMPACTION_CONFIG.AGGRESSIVE_BEGINNING_PERCENTAGE,
|
|
321
|
-
COMPACTION_CONFIG.AGGRESSIVE_END_PERCENTAGE
|
|
322
|
-
);
|
|
323
|
-
|
|
324
|
-
this.logger.debug('Segments identified for aggressive compaction', {
|
|
325
|
-
beginningMessages: segments.beginning.length,
|
|
326
|
-
middleMessages: segments.middle.length,
|
|
327
|
-
endMessages: segments.end.length,
|
|
328
|
-
middleStartIndex: segments.middleStartIndex,
|
|
329
|
-
middleEndIndex: segments.middleEndIndex
|
|
330
|
-
});
|
|
331
|
-
|
|
332
|
-
// Generate summary with more aggressive compression instruction
|
|
333
|
-
const summary = await this._generateSummary(segments.middle, model, {
|
|
334
|
-
...options,
|
|
335
|
-
aggressive: true,
|
|
336
|
-
middleStartIndex: segments.middleStartIndex,
|
|
337
|
-
middleEndIndex: segments.middleEndIndex
|
|
338
|
-
});
|
|
339
|
-
|
|
340
|
-
// Construct compacted conversation
|
|
341
|
-
const compactedMessages = [
|
|
342
|
-
...segments.beginning,
|
|
343
|
-
summary,
|
|
344
|
-
...segments.end
|
|
345
|
-
];
|
|
346
|
-
|
|
347
|
-
// Count tokens in compacted conversation
|
|
348
|
-
const compactedTokenCount = await this.tokenCountingService.estimateConversationTokens(
|
|
349
|
-
compactedMessages,
|
|
350
|
-
model,
|
|
351
|
-
TOKEN_COUNTING_MODES.ACCURATE
|
|
352
|
-
);
|
|
353
|
-
|
|
354
|
-
// Calculate reduction
|
|
355
|
-
const reductionPercent = ((originalTokenCount - compactedTokenCount) / originalTokenCount) * 100;
|
|
356
|
-
|
|
357
|
-
return {
|
|
358
|
-
compactedMessages,
|
|
359
|
-
strategy,
|
|
360
|
-
originalTokenCount,
|
|
361
|
-
compactedTokenCount,
|
|
362
|
-
reductionPercent,
|
|
363
|
-
segments: {
|
|
364
|
-
beginningCount: segments.beginning.length,
|
|
365
|
-
middleCount: segments.middle.length,
|
|
366
|
-
endCount: segments.end.length,
|
|
367
|
-
summaryInserted: true
|
|
368
|
-
}
|
|
369
|
-
};
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
/**
|
|
373
|
-
* Identify conversation segments based on token counts
|
|
374
|
-
* @private
|
|
375
|
-
*/
|
|
376
|
-
async _identifySegments(messages, model, beginningPercent, endPercent) {
|
|
377
|
-
// Calculate total tokens
|
|
378
|
-
const totalTokens = await this.tokenCountingService.estimateConversationTokens(
|
|
379
|
-
messages,
|
|
380
|
-
model,
|
|
381
|
-
TOKEN_COUNTING_MODES.ACCURATE
|
|
382
|
-
);
|
|
383
|
-
|
|
384
|
-
// Calculate target tokens for each segment
|
|
385
|
-
const beginningTargetTokens = Math.floor(totalTokens * beginningPercent);
|
|
386
|
-
const endTargetTokens = Math.floor(totalTokens * endPercent);
|
|
387
|
-
|
|
388
|
-
// Identify beginning segment (from start)
|
|
389
|
-
let beginningTokens = 0;
|
|
390
|
-
let beginningEndIndex = 0;
|
|
391
|
-
|
|
392
|
-
for (let i = 0; i < messages.length; i++) {
|
|
393
|
-
const messageTokens = await this.tokenCountingService.countTokens(
|
|
394
|
-
messages[i].content,
|
|
395
|
-
model,
|
|
396
|
-
TOKEN_COUNTING_MODES.CACHED
|
|
397
|
-
);
|
|
398
|
-
|
|
399
|
-
if (beginningTokens + messageTokens > beginningTargetTokens && i >= 2) {
|
|
400
|
-
// Ensure at least 2 messages in beginning (as per design doc)
|
|
401
|
-
break;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
beginningTokens += messageTokens;
|
|
405
|
-
beginningEndIndex = i + 1;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
// Identify end segment (from end, working backwards)
|
|
409
|
-
let endTokens = 0;
|
|
410
|
-
let endStartIndex = messages.length;
|
|
411
|
-
|
|
412
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
413
|
-
const messageTokens = await this.tokenCountingService.countTokens(
|
|
414
|
-
messages[i].content,
|
|
415
|
-
model,
|
|
416
|
-
TOKEN_COUNTING_MODES.CACHED
|
|
417
|
-
);
|
|
418
|
-
|
|
419
|
-
if (endTokens + messageTokens > endTargetTokens) {
|
|
420
|
-
break;
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
endTokens += messageTokens;
|
|
424
|
-
endStartIndex = i;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
// Ensure no overlap
|
|
428
|
-
if (endStartIndex < beginningEndIndex) {
|
|
429
|
-
endStartIndex = beginningEndIndex;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
// Extract segments
|
|
433
|
-
const beginning = messages.slice(0, beginningEndIndex);
|
|
434
|
-
const middle = messages.slice(beginningEndIndex, endStartIndex);
|
|
435
|
-
const end = messages.slice(endStartIndex);
|
|
436
|
-
|
|
437
|
-
return {
|
|
438
|
-
beginning,
|
|
439
|
-
middle,
|
|
440
|
-
end,
|
|
441
|
-
middleStartIndex: beginningEndIndex,
|
|
442
|
-
middleEndIndex: endStartIndex - 1 // Inclusive end index
|
|
443
|
-
};
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
/**
|
|
447
|
-
* Generate AI summary of middle segment using GPT-4o-mini
|
|
448
|
-
* @private
|
|
449
|
-
*/
|
|
450
|
-
async _generateSummary(middleMessages, model, options = {}) {
|
|
451
|
-
if (middleMessages.length === 0) {
|
|
452
|
-
return {
|
|
453
|
-
role: 'system',
|
|
454
|
-
content: `${COMPACTION_CONFIG.COMPACTION_SUMMARY_PREFIX} No messages to summarize.`,
|
|
455
|
-
type: 'summary',
|
|
456
|
-
timestamp: new Date().toISOString()
|
|
457
|
-
};
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
// Format middle messages for summarization
|
|
461
|
-
const middleContent = middleMessages
|
|
462
|
-
.map(msg => `${msg.role}: ${msg.content}`)
|
|
463
|
-
.join('\n\n');
|
|
464
|
-
|
|
465
|
-
// Build summary prompt
|
|
466
|
-
const summaryPrompt = this.summaryPromptTemplate
|
|
467
|
-
.replace('{middle_segment}', middleContent)
|
|
468
|
-
.replace('{aggressive_instruction}', options.aggressive
|
|
469
|
-
? '\n\nIMPORTANT: Be VERY aggressive in compression. Prioritize only the most critical information. Aim for maximum brevity while maintaining essential context.'
|
|
470
|
-
: '');
|
|
471
|
-
|
|
472
|
-
// Try primary model and fallbacks
|
|
473
|
-
const modelsToTry = [
|
|
474
|
-
COMPACTION_CONFIG.COMPACTION_MODEL,
|
|
475
|
-
...COMPACTION_CONFIG.COMPACTION_MODEL_FALLBACKS
|
|
476
|
-
];
|
|
477
|
-
|
|
478
|
-
let lastError = null;
|
|
479
|
-
|
|
480
|
-
for (const compactionModel of modelsToTry) {
|
|
481
|
-
try {
|
|
482
|
-
this.logger.debug('Generating summary', {
|
|
483
|
-
compactionModel,
|
|
484
|
-
middleMessageCount: middleMessages.length,
|
|
485
|
-
middleContentLength: middleContent.length,
|
|
486
|
-
aggressive: options.aggressive
|
|
487
|
-
});
|
|
488
|
-
|
|
489
|
-
// Call AI service
|
|
490
|
-
const response = await this.aiService.sendMessage(
|
|
491
|
-
compactionModel,
|
|
492
|
-
summaryPrompt,
|
|
493
|
-
{
|
|
494
|
-
systemPrompt: 'You are a conversation summarization expert. Your goal is to compress conversations while preserving critical information for continued interaction.',
|
|
495
|
-
maxTokens: COMPACTION_CONFIG.MAX_SUMMARY_TOKENS,
|
|
496
|
-
temperature: 0.3, // Lower temperature for consistency
|
|
497
|
-
sessionId: options.sessionId,
|
|
498
|
-
platformProvided: true // Use Loxia API key
|
|
499
|
-
}
|
|
500
|
-
);
|
|
501
|
-
|
|
502
|
-
const summaryContent = response.content.trim();
|
|
503
|
-
|
|
504
|
-
// Build index range string
|
|
505
|
-
const indexRange = (options.middleStartIndex !== undefined && options.middleEndIndex !== undefined)
|
|
506
|
-
? `original messages ${options.middleStartIndex}-${options.middleEndIndex}`
|
|
507
|
-
: `${middleMessages.length} messages`;
|
|
508
|
-
|
|
509
|
-
this.logger.info('Summary generated successfully', {
|
|
510
|
-
compactionModel,
|
|
511
|
-
originalLength: middleContent.length,
|
|
512
|
-
summaryLength: summaryContent.length,
|
|
513
|
-
compressionRatio: (summaryContent.length / middleContent.length * 100).toFixed(2) + '%',
|
|
514
|
-
indexRange
|
|
515
|
-
});
|
|
516
|
-
|
|
517
|
-
// Return formatted summary message
|
|
518
|
-
return {
|
|
519
|
-
role: 'system',
|
|
520
|
-
content: `${COMPACTION_CONFIG.COMPACTION_SUMMARY_PREFIX} - ${indexRange}]\n\n${summaryContent}\n\n${COMPACTION_CONFIG.COMPACTION_SUMMARY_SUFFIX}`,
|
|
521
|
-
type: 'summary',
|
|
522
|
-
timestamp: new Date().toISOString(),
|
|
523
|
-
metadata: {
|
|
524
|
-
originalMessageCount: middleMessages.length,
|
|
525
|
-
originalStartIndex: options.middleStartIndex,
|
|
526
|
-
originalEndIndex: options.middleEndIndex,
|
|
527
|
-
compactionModel: compactionModel,
|
|
528
|
-
aggressive: options.aggressive || false
|
|
529
|
-
}
|
|
530
|
-
};
|
|
531
|
-
|
|
532
|
-
} catch (error) {
|
|
533
|
-
lastError = error;
|
|
534
|
-
this.logger.warn('Summary generation failed with model, trying next fallback', {
|
|
535
|
-
compactionModel,
|
|
536
|
-
error: error.message,
|
|
537
|
-
middleMessageCount: middleMessages.length
|
|
538
|
-
});
|
|
539
|
-
// Continue to next model
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
// All models failed, use fallback summary
|
|
544
|
-
this.logger.error('All summary generation attempts failed', {
|
|
545
|
-
modelsAttempted: modelsToTry.length,
|
|
546
|
-
lastError: lastError?.message,
|
|
547
|
-
middleMessageCount: middleMessages.length
|
|
548
|
-
});
|
|
549
|
-
|
|
550
|
-
// Fallback to simple truncated summary
|
|
551
|
-
const fallbackSummary = this._createFallbackSummary(middleMessages);
|
|
552
|
-
|
|
553
|
-
// Build index range string for fallback
|
|
554
|
-
const indexRange = (options.middleStartIndex !== undefined && options.middleEndIndex !== undefined)
|
|
555
|
-
? `original messages ${options.middleStartIndex}-${options.middleEndIndex}`
|
|
556
|
-
: `${middleMessages.length} messages`;
|
|
557
|
-
|
|
558
|
-
return {
|
|
559
|
-
role: 'system',
|
|
560
|
-
content: `${COMPACTION_CONFIG.COMPACTION_SUMMARY_PREFIX} - ${indexRange}]\n\n${fallbackSummary}\n\n${COMPACTION_CONFIG.COMPACTION_SUMMARY_SUFFIX}`,
|
|
561
|
-
type: 'summary',
|
|
562
|
-
timestamp: new Date().toISOString(),
|
|
563
|
-
metadata: {
|
|
564
|
-
originalMessageCount: middleMessages.length,
|
|
565
|
-
originalStartIndex: options.middleStartIndex,
|
|
566
|
-
originalEndIndex: options.middleEndIndex,
|
|
567
|
-
fallback: true,
|
|
568
|
-
error: lastError?.message,
|
|
569
|
-
modelsAttempted: modelsToTry
|
|
570
|
-
}
|
|
571
|
-
};
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
/**
|
|
575
|
-
* Create fallback summary when AI generation fails
|
|
576
|
-
* @private
|
|
577
|
-
*/
|
|
578
|
-
_createFallbackSummary(messages) {
|
|
579
|
-
const messageCount = messages.length;
|
|
580
|
-
const roles = messages.map(m => m.role);
|
|
581
|
-
const userCount = roles.filter(r => r === 'user').length;
|
|
582
|
-
const assistantCount = roles.filter(r => r === 'assistant').length;
|
|
583
|
-
|
|
584
|
-
return `[${messageCount} messages summarized - ${userCount} user messages, ${assistantCount} assistant responses. ` +
|
|
585
|
-
`Summary generation unavailable - middle section compressed for context management.]`;
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
/**
|
|
589
|
-
* Create summary prompt template with preservation guidelines
|
|
590
|
-
* @private
|
|
591
|
-
*/
|
|
592
|
-
_createSummaryPromptTemplate() {
|
|
593
|
-
return `You are compacting a conversation to preserve critical information while reducing token count.
|
|
594
|
-
|
|
595
|
-
CONTEXT: This is part of a longer conversation that needs compactization for continued processing.
|
|
596
|
-
|
|
597
|
-
PRESERVATION GUIDELINES:
|
|
598
|
-
|
|
599
|
-
HIGH PRIORITY (Always Preserve):
|
|
600
|
-
- Future reference value: Information likely to be referenced again
|
|
601
|
-
- Decisions and reasoning: WHY things were decided, not just what
|
|
602
|
-
- API signatures and interfaces: Function definitions, method calls
|
|
603
|
-
- Active dependencies: Information that ongoing work relies on
|
|
604
|
-
- Error patterns and solutions: What failed and how it was fixed
|
|
605
|
-
- Key facts and data: Specific numbers, names, configurations
|
|
606
|
-
|
|
607
|
-
MEDIUM PRIORITY (Compress Intelligently):
|
|
608
|
-
- Code blocks: Keep function signatures + brief description, compress implementation details
|
|
609
|
-
- Working solutions: Essence and outcome, not every implementation step
|
|
610
|
-
- Failed attempts: Brief mention of what didn't work and why, skip detailed troubleshooting
|
|
611
|
-
- Repetitive content: Consolidate similar examples or explanations
|
|
612
|
-
|
|
613
|
-
LOW PRIORITY (Heavily Compress/Remove):
|
|
614
|
-
- Completed calculations: Keep results, skip intermediate steps
|
|
615
|
-
- Verbose explanations: Summarize well-known concepts
|
|
616
|
-
- Debug output: Skip terminal logs and error messages that served their purpose
|
|
617
|
-
- Trial-and-error sequences: Skip multiple failed attempts with no lasting value
|
|
618
|
-
- Acknowledgments and pleasantries: Skip "thank you", "sure", "okay" type exchanges
|
|
619
|
-
|
|
620
|
-
CONVERSATION SEGMENT TO SUMMARIZE:
|
|
621
|
-
{middle_segment}
|
|
622
|
-
|
|
623
|
-
TASK: Create a concise summary that preserves logical flow and critical information. Focus on:
|
|
624
|
-
1. Key decisions and their reasoning
|
|
625
|
-
2. Important facts, data, and configurations
|
|
626
|
-
3. Active context needed for continuation
|
|
627
|
-
4. Problem-solving outcomes (skip the debugging process)
|
|
628
|
-
5. Dependencies and interfaces that code/work relies on
|
|
629
|
-
|
|
630
|
-
Someone reading this should understand the conversation progression and have all information needed for effective continuation.
|
|
631
|
-
{aggressive_instruction}
|
|
632
|
-
|
|
633
|
-
OUTPUT: Provide ONLY the summary text without preamble, explanation, or meta-commentary.`;
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
export default ConversationCompactionService;
|
|
1
|
+
const a0_0x326bbd=a0_0x2594;(function(_0x17b374,_0x28f83d){const _0x5ff9a7=a0_0x2594,_0x4015a1=_0x17b374();while(!![]){try{const _0x5c7ce1=parseInt(_0x5ff9a7(0x14f))/0x1+parseInt(_0x5ff9a7(0x173))/0x2+-parseInt(_0x5ff9a7(0x16a))/0x3*(-parseInt(_0x5ff9a7(0x16d))/0x4)+-parseInt(_0x5ff9a7(0x156))/0x5+parseInt(_0x5ff9a7(0x159))/0x6+-parseInt(_0x5ff9a7(0x186))/0x7+-parseInt(_0x5ff9a7(0x175))/0x8;if(_0x5c7ce1===_0x28f83d)break;else _0x4015a1['push'](_0x4015a1['shift']());}catch(_0x391b31){_0x4015a1['push'](_0x4015a1['shift']());}}}(a0_0x453c,0x67769));function a0_0x2594(_0x4c0d1f,_0xeea24d){_0x4c0d1f=_0x4c0d1f-0x145;const _0x453c69=a0_0x453c();let _0x259453=_0x453c69[_0x4c0d1f];if(a0_0x2594['QUcoLx']===undefined){var _0xf14bd4=function(_0x2f5453){const _0x4dd054='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x5cf063='',_0x53e930='';for(let _0x21802e=0x0,_0x5c79ec,_0x116073,_0x40c4ab=0x0;_0x116073=_0x2f5453['charAt'](_0x40c4ab++);~_0x116073&&(_0x5c79ec=_0x21802e%0x4?_0x5c79ec*0x40+_0x116073:_0x116073,_0x21802e++%0x4)?_0x5cf063+=String['fromCharCode'](0xff&_0x5c79ec>>(-0x2*_0x21802e&0x6)):0x0){_0x116073=_0x4dd054['indexOf'](_0x116073);}for(let _0x76ea65=0x0,_0x548d6f=_0x5cf063['length'];_0x76ea65<_0x548d6f;_0x76ea65++){_0x53e930+='%'+('00'+_0x5cf063['charCodeAt'](_0x76ea65)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x53e930);};a0_0x2594['Rofsvz']=_0xf14bd4,a0_0x2594['nhJQzU']={},a0_0x2594['QUcoLx']=!![];}const _0x69b2d0=_0x453c69[0x0],_0x316f83=_0x4c0d1f+_0x69b2d0,_0x44a459=a0_0x2594['nhJQzU'][_0x316f83];return!_0x44a459?(_0x259453=a0_0x2594['Rofsvz'](_0x259453),a0_0x2594['nhJQzU'][_0x316f83]=_0x259453):_0x259453=_0x44a459,_0x259453;}function a0_0x453c(){const _0x36593e=['x2nVBxbHy3rxAxrOvhj1BMnHDgLVBG','zw5K','u1vntufssvPbveLptG','zMLSDgvY','BgvUz3rO','u3rHCNrPBMCGy29UDMvYC2f0Aw9UignVBxbHy3rPB24','CM9Szq','ru5ex1nfr01ftLrFuevsq0vovefhrq','BwvZC2fNzq','y291BNruB2TLBNm','ie5Vig1LC3nHz2vZihrVihn1Bw1HCML6zs4','E2fNz3jLC3nPDMvFAw5ZDhj1y3rPB259','ywDNCMvZC2L2zq','C3vTBwfYEq','y29UDgvUDa','D2fYBG','xqOk','nJK3mJi0DwjTz0TS','quDhuKvtu0Lwrv9ftKrFuevsq0vovefhrq','ic0G','x2LKzw50Awz5u2vNBwvUDhm','u2vNBwvUDhmGAwrLBNrPzMLLzcbMB3iGywDNCMvZC2L2zsbJB21Wywn0Aw9U','igfZC2LZDgfUDcbYzxnWB25ZzxmUia','BM93','mJq1ntK5nw5fsfruqq','q09nuefdveLptL9nt0rfta','x2nVBxbHy3rxAxrOu3vTBwfYAxPHDgLVBG','nZGWnZHwr1Pds00','Aw5MBW','Bg9Nz2vY','q09nuefdveLptL9tvu1nqvjzx1nvrKzjwa','twvZC2fNzxmGyxjYyxKGAxmGCMvXDwLYzwqGyw5KignHBM5VDcbIzsbLBxb0Eq','zxHLy3v0Aw9UvgLTzq','yMvNAw5UAw5N','q0fdseve','ywLtzxj2AwnL','C2XPy2u','vw5RBM93BIbJB21Wywn0Aw9Uihn0CMf0zwD5oIa','r2vUzxjHDgLUzYbZDw1Tyxj5','y29TCgfJDgvKtwvZC2fNzxm','vg9VigzLDYbTzxnZywDLCYbMB3iGy29TCgfJDgLVBG','z2v0tw9KzwXdB250zxH0v2LUzg93','u3vTBwfYEsbNzw5LCMf0Aw9UihvUyxzHAwXHyMXLic0GBwLKzgXLihnLy3rPB24Gy29TChjLC3nLzcbMB3iGy29UDgv4DcbTyw5Hz2vTzw50lL0','Dg9gAxHLza','nZC5odjyA0v4tfe','C3rYyxrLz3K','vfjvtKnbveLptG','mtaWC3bXwwPO','x2DLBMvYyxrLu3vTBwfYEq','BwLKzgXL','zxn0Aw1HDgvdB252zxjZyxrPB25uB2TLBNm','zgvIDwC','q09nuefdveLptL9trvbbuKfut1jFtuvtu0fhrq','mta3nJGZnLrPDvnVBG','BwLKzgXLrw5Ksw5KzxG','nZuYnZaYngjTCxjJBW','Dg9Rzw5dB3vUDgLUz1nLCNzPy2u','Dg9ju09tDhjPBMC','quDhuKvtu0Lwrq','qundvvjbveu','yxnZAxn0yw50','ig1LC3nHz2vZ','C3LZDgvT','q09nuefdveLptL9tvu1nqvjzx1bsruzjwa','u2vNBwvUDhmGAwrLBNrPzMLLzcbMB3iGDhj1BMnHDgLVBG','BwLKzgXLu3rHCNrjBMrLEa','C3vTBwfYEvbYB21WDfrLBxbSyxrL','zMXVB3i','u2vNBwvUDhmGAwrLBNrPzMLLzcbMB3iGC3vTBwfYAxPHDgLVBG','x2nYzwf0zvn1Bw1HCNLqCM9TChruzw1WBgf0zq','tufyx1nvtu1buLLFve9lru5t','x2nYzwf0zuzHBgXIywnRu3vTBwfYEq','mJK4ntaXug1YAgXV','zxjYB3i'];a0_0x453c=function(){return _0x36593e;};return a0_0x453c();}import{COMPACTION_CONFIG,COMPACTION_STRATEGIES,TOKEN_COUNTING_MODES}from'../utilities/constants.js';class ConversationCompactionService{constructor(_0x5cf063,_0x53e930,_0x21802e){const _0x4c1ba8=a0_0x2594;this['tokenCountingService']=_0x5cf063,this['aiService']=_0x53e930,this[_0x4c1ba8(0x15b)]=_0x21802e,this[_0x4c1ba8(0x180)]=this[_0x4c1ba8(0x183)]();}async['compactConversation'](_0x5c79ec,_0x116073,_0x40c4ab,_0x76ea65={}){const _0x5aa8c7=a0_0x2594,_0x548d6f=Date['now']();try{if(!Array['isArray'](_0x5c79ec)||_0x5c79ec[_0x5aa8c7(0x18c)]===0x0)throw new Error(_0x5aa8c7(0x15d));if(_0x5c79ec[_0x5aa8c7(0x18c)]<COMPACTION_CONFIG['MIN_MESSAGES_FOR_COMPACTION'])return this[_0x5aa8c7(0x15b)]['warn'](_0x5aa8c7(0x166),{'messageCount':_0x5c79ec['length'],'minimum':COMPACTION_CONFIG['MIN_MESSAGES_FOR_COMPACTION']}),{'compactedMessages':_0x5c79ec,'strategy':'none','originalTokenCount':0x0,'compactedTokenCount':0x0,'reductionPercent':0x0,'skipped':!![],'reason':'Too\x20few\x20messages'};const _0x107223=_0x116073!==_0x40c4ab,_0x481774=_0x76ea65['isRetry']||![];let _0x235ac0;if(_0x107223)_0x235ac0=COMPACTION_STRATEGIES[_0x5aa8c7(0x16c)];else _0x481774?_0x235ac0=COMPACTION_STRATEGIES['AGGRESSIVE']:_0x235ac0=_0x76ea65[_0x5aa8c7(0x16b)]||COMPACTION_STRATEGIES[_0x5aa8c7(0x18a)];this['logger'][_0x5aa8c7(0x15a)](_0x5aa8c7(0x18d),{'messageCount':_0x5c79ec['length'],'currentModel':_0x116073,'targetModel':_0x40c4ab,'strategy':_0x235ac0,'isModelSwitch':_0x107223,'isRetry':_0x481774});let _0x457526;switch(_0x235ac0){case COMPACTION_STRATEGIES['SUMMARIZATION']:_0x457526=await this[_0x5aa8c7(0x158)](_0x5c79ec,_0x116073,_0x76ea65);break;case COMPACTION_STRATEGIES['TRUNCATION']:_0x457526=await this[_0x5aa8c7(0x188)](_0x5c79ec,_0x40c4ab,_0x76ea65);break;case COMPACTION_STRATEGIES['AGGRESSIVE']:_0x457526=await this['_compactWithAggressiveSummarization'](_0x5c79ec,_0x116073,_0x76ea65);break;default:throw new Error(_0x5aa8c7(0x163)+_0x235ac0);}const _0x50c20d=Date[_0x5aa8c7(0x155)]()-_0x548d6f;return _0x457526[_0x5aa8c7(0x15e)]=_0x50c20d,_0x457526['timestamp']=new Date()['toISOString'](),this['logger']['info']('Compaction\x20completed\x20successfully',{'strategy':_0x457526['strategy'],'originalMessages':_0x5c79ec[_0x5aa8c7(0x18c)],'compactedMessages':_0x457526[_0x5aa8c7(0x165)][_0x5aa8c7(0x18c)],'originalTokens':_0x457526['originalTokenCount'],'compactedTokens':_0x457526['compactedTokenCount'],'reductionPercent':_0x457526['reductionPercent'][_0x5aa8c7(0x169)](0x2),'executionTime':_0x50c20d+'ms'}),_0x457526;}catch(_0x2126ba){const _0x5d04db=Date['now']()-_0x548d6f;this[_0x5aa8c7(0x15b)][_0x5aa8c7(0x187)]('Compaction\x20failed',{'error':_0x2126ba['message'],'messageCount':_0x5c79ec['length'],'currentModel':_0x116073,'targetModel':_0x40c4ab,'executionTime':_0x5d04db+'ms'});throw _0x2126ba;}}async[a0_0x326bbd(0x158)](_0x3ee115,_0x3f1cf7,_0x14753e){const _0x36e5e5=a0_0x326bbd,_0x86e1fd=COMPACTION_STRATEGIES[_0x36e5e5(0x18a)],_0x349acf=await this[_0x36e5e5(0x176)]['estimateConversationTokens'](_0x3ee115,_0x3f1cf7,TOKEN_COUNTING_MODES['ACCURATE']),_0x1408b8=await this[_0x36e5e5(0x152)](_0x3ee115,_0x3f1cf7,COMPACTION_CONFIG['BEGINNING_SEGMENT_PERCENTAGE'],COMPACTION_CONFIG[_0x36e5e5(0x145)]);this[_0x36e5e5(0x15b)]['debug'](_0x36e5e5(0x182),{'beginningMessages':_0x1408b8['beginning']['length'],'middleMessages':_0x1408b8['middle']['length'],'endMessages':_0x1408b8['end'][_0x36e5e5(0x18c)],'middleStartIndex':_0x1408b8['middleStartIndex'],'middleEndIndex':_0x1408b8[_0x36e5e5(0x174)],'totalMessages':_0x3ee115['length']});const _0x2b5a6b=await this['_generateSummary'](_0x1408b8[_0x36e5e5(0x16f)],_0x3f1cf7,{..._0x14753e,'middleStartIndex':_0x1408b8[_0x36e5e5(0x17f)],'middleEndIndex':_0x1408b8['middleEndIndex']}),_0x5ad03f=[..._0x1408b8['beginning'],_0x2b5a6b,..._0x1408b8[_0x36e5e5(0x189)]],_0x4c620f=await this[_0x36e5e5(0x176)]['estimateConversationTokens'](_0x5ad03f,_0x3f1cf7,TOKEN_COUNTING_MODES[_0x36e5e5(0x179)]),_0x122d8e=(_0x349acf-_0x4c620f)/_0x349acf*0x64;return{'compactedMessages':_0x5ad03f,'strategy':_0x86e1fd,'originalTokenCount':_0x349acf,'compactedTokenCount':_0x4c620f,'reductionPercent':_0x122d8e,'segments':{'beginningCount':_0x1408b8[_0x36e5e5(0x15f)]['length'],'middleCount':_0x1408b8[_0x36e5e5(0x16f)][_0x36e5e5(0x18c)],'endCount':_0x1408b8[_0x36e5e5(0x189)]['length'],'summaryInserted':!![]}};}async['_compactWithTruncation'](_0x2d27ef,_0x1837e8,_0x23a9a3){const _0x1010f6=a0_0x326bbd,_0x34b3b9=COMPACTION_STRATEGIES['TRUNCATION'],_0x10f3f2=this['tokenCountingService'][_0x1010f6(0x167)](_0x1837e8),_0x39feda=Math[_0x1010f6(0x181)](_0x10f3f2*0.8),_0x5d3661=await this[_0x1010f6(0x176)]['estimateConversationTokens'](_0x2d27ef,_0x1837e8,TOKEN_COUNTING_MODES[_0x1010f6(0x179)]),_0x74a5d2=await this['_identifySegments'](_0x2d27ef,_0x1837e8,COMPACTION_CONFIG['TRUNCATION_BEGINNING_PERCENTAGE'],COMPACTION_CONFIG['TRUNCATION_END_PERCENTAGE']);this[_0x1010f6(0x15b)][_0x1010f6(0x171)](_0x1010f6(0x17e),{'beginningMessages':_0x74a5d2[_0x1010f6(0x15f)][_0x1010f6(0x18c)],'middleMessages':_0x74a5d2[_0x1010f6(0x16f)][_0x1010f6(0x18c)],'endMessages':_0x74a5d2[_0x1010f6(0x189)]['length'],'targetTokenCount':_0x39feda,'originalTokenCount':_0x5d3661});const _0x2b4874={'role':'system','content':COMPACTION_CONFIG[_0x1010f6(0x172)],'type':'separator','timestamp':new Date()['toISOString'](),'metadata':{'truncatedMessages':_0x74a5d2['middle']['length'],'reason':'Model\x20switch\x20-\x20middle\x20section\x20removed\x20to\x20fit\x20target\x20context\x20window'}},_0x2fe2b2=[..._0x74a5d2['beginning'],_0x2b4874,..._0x74a5d2['end']],_0x5bdf5d=await this['tokenCountingService'][_0x1010f6(0x170)](_0x2fe2b2,_0x1837e8,TOKEN_COUNTING_MODES['ACCURATE']),_0xa9458c=(_0x5d3661-_0x5bdf5d)/_0x5d3661*0x64;return{'compactedMessages':_0x2fe2b2,'strategy':_0x34b3b9,'originalTokenCount':_0x5d3661,'compactedTokenCount':_0x5bdf5d,'reductionPercent':_0xa9458c,'segments':{'beginningCount':_0x74a5d2['beginning'][_0x1010f6(0x18c)],'middleCount':_0x74a5d2[_0x1010f6(0x16f)][_0x1010f6(0x18c)],'endCount':_0x74a5d2[_0x1010f6(0x189)]['length'],'summaryInserted':![]}};}async['_compactWithAggressiveSummarization'](_0x4671a2,_0x33f930,_0x2ef352){const _0x83c6d8=a0_0x326bbd,_0x9eb486=COMPACTION_STRATEGIES[_0x83c6d8(0x178)],_0x4b4b41=await this['tokenCountingService']['estimateConversationTokens'](_0x4671a2,_0x33f930,TOKEN_COUNTING_MODES['ACCURATE']),_0x486e44=await this[_0x83c6d8(0x152)](_0x4671a2,_0x33f930,COMPACTION_CONFIG['AGGRESSIVE_BEGINNING_PERCENTAGE'],COMPACTION_CONFIG[_0x83c6d8(0x150)]);this[_0x83c6d8(0x15b)][_0x83c6d8(0x171)](_0x83c6d8(0x153),{'beginningMessages':_0x486e44['beginning']['length'],'middleMessages':_0x486e44['middle'][_0x83c6d8(0x18c)],'endMessages':_0x486e44['end'][_0x83c6d8(0x18c)],'middleStartIndex':_0x486e44[_0x83c6d8(0x17f)],'middleEndIndex':_0x486e44['middleEndIndex']});const _0x4ef31d=await this[_0x83c6d8(0x16e)](_0x486e44[_0x83c6d8(0x16f)],_0x33f930,{..._0x2ef352,'aggressive':!![],'middleStartIndex':_0x486e44['middleStartIndex'],'middleEndIndex':_0x486e44['middleEndIndex']}),_0x5c3e0f=[..._0x486e44[_0x83c6d8(0x15f)],_0x4ef31d,..._0x486e44[_0x83c6d8(0x189)]],_0x31ad8d=await this['tokenCountingService']['estimateConversationTokens'](_0x5c3e0f,_0x33f930,TOKEN_COUNTING_MODES['ACCURATE']),_0x12199a=(_0x4b4b41-_0x31ad8d)/_0x4b4b41*0x64;return{'compactedMessages':_0x5c3e0f,'strategy':_0x9eb486,'originalTokenCount':_0x4b4b41,'compactedTokenCount':_0x31ad8d,'reductionPercent':_0x12199a,'segments':{'beginningCount':_0x486e44['beginning'][_0x83c6d8(0x18c)],'middleCount':_0x486e44[_0x83c6d8(0x16f)][_0x83c6d8(0x18c)],'endCount':_0x486e44[_0x83c6d8(0x189)]['length'],'summaryInserted':!![]}};}async['_identifySegments'](_0x919b79,_0x51decd,_0xdbf18b,_0x47a866){const _0x3c6624=a0_0x326bbd,_0x18f386=await this['tokenCountingService'][_0x3c6624(0x170)](_0x919b79,_0x51decd,TOKEN_COUNTING_MODES[_0x3c6624(0x179)]),_0x28d97f=Math['floor'](_0x18f386*_0xdbf18b),_0x51d7c6=Math[_0x3c6624(0x181)](_0x18f386*_0x47a866);let _0x4b952e=0x0,_0x2897ba=0x0;for(let _0x5b78bb=0x0;_0x5b78bb<_0x919b79[_0x3c6624(0x18c)];_0x5b78bb++){const _0x2fef1e=await this['tokenCountingService']['countTokens'](_0x919b79[_0x5b78bb]['content'],_0x51decd,TOKEN_COUNTING_MODES[_0x3c6624(0x160)]);if(_0x4b952e+_0x2fef1e>_0x28d97f&&_0x5b78bb>=0x2)break;_0x4b952e+=_0x2fef1e,_0x2897ba=_0x5b78bb+0x1;}let _0xbc26ed=0x0,_0x327354=_0x919b79[_0x3c6624(0x18c)];for(let _0x1172b8=_0x919b79['length']-0x1;_0x1172b8>=0x0;_0x1172b8--){const _0x50428e=await this['tokenCountingService'][_0x3c6624(0x147)](_0x919b79[_0x1172b8][_0x3c6624(0x14c)],_0x51decd,TOKEN_COUNTING_MODES['CACHED']);if(_0xbc26ed+_0x50428e>_0x51d7c6)break;_0xbc26ed+=_0x50428e,_0x327354=_0x1172b8;}_0x327354<_0x2897ba&&(_0x327354=_0x2897ba);const _0x1ac372=_0x919b79['slice'](0x0,_0x2897ba),_0x38b435=_0x919b79['slice'](_0x2897ba,_0x327354),_0x447b43=_0x919b79[_0x3c6624(0x162)](_0x327354);return{'beginning':_0x1ac372,'middle':_0x38b435,'end':_0x447b43,'middleStartIndex':_0x2897ba,'middleEndIndex':_0x327354-0x1};}async['_generateSummary'](_0x401b38,_0x3b280c,_0x752f56={}){const _0x53e58b=a0_0x326bbd;if(_0x401b38['length']===0x0)return{'role':_0x53e58b(0x17c),'content':COMPACTION_CONFIG[_0x53e58b(0x17d)]+_0x53e58b(0x148),'type':'summary','timestamp':new Date()[_0x53e58b(0x177)]()};const _0x490a15=_0x401b38['map'](_0x2e3f83=>_0x2e3f83[_0x53e58b(0x18e)]+':\x20'+_0x2e3f83[_0x53e58b(0x14c)])['join']('\x0a\x0a'),_0x4b0344=this[_0x53e58b(0x180)]['replace']('{middle_segment}',_0x490a15)['replace'](_0x53e58b(0x149),_0x752f56[_0x53e58b(0x14a)]?'\x0a\x0aIMPORTANT:\x20Be\x20VERY\x20aggressive\x20in\x20compression.\x20Prioritize\x20only\x20the\x20most\x20critical\x20information.\x20Aim\x20for\x20maximum\x20brevity\x20while\x20maintaining\x20essential\x20context.':''),_0x20e68d=[COMPACTION_CONFIG[_0x53e58b(0x157)],...COMPACTION_CONFIG['COMPACTION_MODEL_FALLBACKS']];let _0x2757f6=null;for(const _0x1096b5 of _0x20e68d){try{this[_0x53e58b(0x15b)]['debug'](_0x53e58b(0x164),{'compactionModel':_0x1096b5,'middleMessageCount':_0x401b38['length'],'middleContentLength':_0x490a15[_0x53e58b(0x18c)],'aggressive':_0x752f56['aggressive']});const _0x54dcc6=await this[_0x53e58b(0x161)]['sendMessage'](_0x1096b5,_0x4b0344,{'systemPrompt':'You\x20are\x20a\x20conversation\x20summarization\x20expert.\x20Your\x20goal\x20is\x20to\x20compress\x20conversations\x20while\x20preserving\x20critical\x20information\x20for\x20continued\x20interaction.','maxTokens':COMPACTION_CONFIG[_0x53e58b(0x184)],'temperature':0.3,'sessionId':_0x752f56['sessionId'],'platformProvided':!![]}),_0x2b87ac=_0x54dcc6['content']['trim'](),_0x8cb8b9=_0x752f56[_0x53e58b(0x17f)]!==undefined&&_0x752f56['middleEndIndex']!==undefined?'original\x20messages\x20'+_0x752f56[_0x53e58b(0x17f)]+'-'+_0x752f56['middleEndIndex']:_0x401b38['length']+_0x53e58b(0x17b);return this[_0x53e58b(0x15b)][_0x53e58b(0x15a)]('Summary\x20generated\x20successfully',{'compactionModel':_0x1096b5,'originalLength':_0x490a15[_0x53e58b(0x18c)],'summaryLength':_0x2b87ac['length'],'compressionRatio':(_0x2b87ac['length']/_0x490a15['length']*0x64)[_0x53e58b(0x169)](0x2)+'%','indexRange':_0x8cb8b9}),{'role':_0x53e58b(0x17c),'content':COMPACTION_CONFIG[_0x53e58b(0x17d)]+_0x53e58b(0x151)+_0x8cb8b9+_0x53e58b(0x14e)+_0x2b87ac+'\x0a\x0a'+COMPACTION_CONFIG['COMPACTION_SUMMARY_SUFFIX'],'type':_0x53e58b(0x14b),'timestamp':new Date()[_0x53e58b(0x177)](),'metadata':{'originalMessageCount':_0x401b38[_0x53e58b(0x18c)],'originalStartIndex':_0x752f56[_0x53e58b(0x17f)],'originalEndIndex':_0x752f56['middleEndIndex'],'compactionModel':_0x1096b5,'aggressive':_0x752f56[_0x53e58b(0x14a)]||![]}};}catch(_0x56738f){_0x2757f6=_0x56738f,this[_0x53e58b(0x15b)][_0x53e58b(0x14d)]('Summary\x20generation\x20failed\x20with\x20model,\x20trying\x20next\x20fallback',{'compactionModel':_0x1096b5,'error':_0x56738f[_0x53e58b(0x146)],'middleMessageCount':_0x401b38[_0x53e58b(0x18c)]});}}this[_0x53e58b(0x15b)]['error']('All\x20summary\x20generation\x20attempts\x20failed',{'modelsAttempted':_0x20e68d['length'],'lastError':_0x2757f6?.['message'],'middleMessageCount':_0x401b38['length']});const _0x302a4d=this[_0x53e58b(0x185)](_0x401b38),_0x53c11b=_0x752f56[_0x53e58b(0x17f)]!==undefined&&_0x752f56[_0x53e58b(0x174)]!==undefined?'original\x20messages\x20'+_0x752f56['middleStartIndex']+'-'+_0x752f56[_0x53e58b(0x174)]:_0x401b38['length']+'\x20messages';return{'role':'system','content':COMPACTION_CONFIG['COMPACTION_SUMMARY_PREFIX']+_0x53e58b(0x151)+_0x53c11b+']\x0a\x0a'+_0x302a4d+'\x0a\x0a'+COMPACTION_CONFIG[_0x53e58b(0x15c)],'type':'summary','timestamp':new Date()['toISOString'](),'metadata':{'originalMessageCount':_0x401b38[_0x53e58b(0x18c)],'originalStartIndex':_0x752f56['middleStartIndex'],'originalEndIndex':_0x752f56[_0x53e58b(0x174)],'fallback':!![],'error':_0x2757f6?.['message'],'modelsAttempted':_0x20e68d}};}[a0_0x326bbd(0x185)](_0x1c412c){const _0x4ac97f=a0_0x326bbd,_0x2eb65d=_0x1c412c[_0x4ac97f(0x18c)],_0x55c0e8=_0x1c412c['map'](_0x25f69a=>_0x25f69a['role']),_0x2364a4=_0x55c0e8['filter'](_0xb39f01=>_0xb39f01==='user')['length'],_0x2325bf=_0x55c0e8[_0x4ac97f(0x18b)](_0x5bcf36=>_0x5bcf36===_0x4ac97f(0x17a))[_0x4ac97f(0x18c)];return'['+_0x2eb65d+'\x20messages\x20summarized\x20-\x20'+_0x2364a4+'\x20user\x20messages,\x20'+_0x2325bf+_0x4ac97f(0x154)+_0x4ac97f(0x168);}['_createSummaryPromptTemplate'](){return'You\x20are\x20compacting\x20a\x20conversation\x20to\x20preserve\x20critical\x20information\x20while\x20reducing\x20token\x20count.\x0a\x0aCONTEXT:\x20This\x20is\x20part\x20of\x20a\x20longer\x20conversation\x20that\x20needs\x20compactization\x20for\x20continued\x20processing.\x0a\x0aPRESERVATION\x20GUIDELINES:\x0a\x0aHIGH\x20PRIORITY\x20(Always\x20Preserve):\x0a-\x20Future\x20reference\x20value:\x20Information\x20likely\x20to\x20be\x20referenced\x20again\x0a-\x20Decisions\x20and\x20reasoning:\x20WHY\x20things\x20were\x20decided,\x20not\x20just\x20what\x0a-\x20API\x20signatures\x20and\x20interfaces:\x20Function\x20definitions,\x20method\x20calls\x0a-\x20Active\x20dependencies:\x20Information\x20that\x20ongoing\x20work\x20relies\x20on\x0a-\x20Error\x20patterns\x20and\x20solutions:\x20What\x20failed\x20and\x20how\x20it\x20was\x20fixed\x0a-\x20Key\x20facts\x20and\x20data:\x20Specific\x20numbers,\x20names,\x20configurations\x0a\x0aMEDIUM\x20PRIORITY\x20(Compress\x20Intelligently):\x0a-\x20Code\x20blocks:\x20Keep\x20function\x20signatures\x20+\x20brief\x20description,\x20compress\x20implementation\x20details\x0a-\x20Working\x20solutions:\x20Essence\x20and\x20outcome,\x20not\x20every\x20implementation\x20step\x0a-\x20Failed\x20attempts:\x20Brief\x20mention\x20of\x20what\x20didn\x27t\x20work\x20and\x20why,\x20skip\x20detailed\x20troubleshooting\x0a-\x20Repetitive\x20content:\x20Consolidate\x20similar\x20examples\x20or\x20explanations\x0a\x0aLOW\x20PRIORITY\x20(Heavily\x20Compress/Remove):\x0a-\x20Completed\x20calculations:\x20Keep\x20results,\x20skip\x20intermediate\x20steps\x0a-\x20Verbose\x20explanations:\x20Summarize\x20well-known\x20concepts\x0a-\x20Debug\x20output:\x20Skip\x20terminal\x20logs\x20and\x20error\x20messages\x20that\x20served\x20their\x20purpose\x0a-\x20Trial-and-error\x20sequences:\x20Skip\x20multiple\x20failed\x20attempts\x20with\x20no\x20lasting\x20value\x0a-\x20Acknowledgments\x20and\x20pleasantries:\x20Skip\x20\x22thank\x20you\x22,\x20\x22sure\x22,\x20\x22okay\x22\x20type\x20exchanges\x0a\x0aCONVERSATION\x20SEGMENT\x20TO\x20SUMMARIZE:\x0a{middle_segment}\x0a\x0aTASK:\x20Create\x20a\x20concise\x20summary\x20that\x20preserves\x20logical\x20flow\x20and\x20critical\x20information.\x20Focus\x20on:\x0a1.\x20Key\x20decisions\x20and\x20their\x20reasoning\x0a2.\x20Important\x20facts,\x20data,\x20and\x20configurations\x0a3.\x20Active\x20context\x20needed\x20for\x20continuation\x0a4.\x20Problem-solving\x20outcomes\x20(skip\x20the\x20debugging\x20process)\x0a5.\x20Dependencies\x20and\x20interfaces\x20that\x20code/work\x20relies\x20on\x0a\x0aSomeone\x20reading\x20this\x20should\x20understand\x20the\x20conversation\x20progression\x20and\x20have\x20all\x20information\x20needed\x20for\x20effective\x20continuation.\x0a{aggressive_instruction}\x0a\x0aOUTPUT:\x20Provide\x20ONLY\x20the\x20summary\x20text\x20without\x20preamble,\x20explanation,\x20or\x20meta-commentary.';}}export default ConversationCompactionService;
|