@exreve/exk 1.0.75 → 1.0.77
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/cli/agentSession.js
CHANGED
|
@@ -56,7 +56,7 @@ const symlinkAsync = promisify(fsSymlink);
|
|
|
56
56
|
// AI config - loaded from server after registration, stored in ~/.talk-to-code/ai-config.json
|
|
57
57
|
// (Do not read ANTHROPIC_* / CLAUDE_MODEL from the host environment — only this file + code default model.)
|
|
58
58
|
const AI_CONFIG_PATH = path.join(os.homedir(), '.talk-to-code', 'ai-config.json');
|
|
59
|
-
const DEFAULT_AI_MODEL = 'glm-5.
|
|
59
|
+
const DEFAULT_AI_MODEL = 'glm-5.2';
|
|
60
60
|
/** TTL cache for ai-config.json reads to avoid hitting disk on every call */
|
|
61
61
|
let _aiConfigCache = null;
|
|
62
62
|
const AI_CONFIG_TTL_MS = 5_000;
|
|
@@ -66,12 +66,12 @@ const PROVIDERS = {
|
|
|
66
66
|
zai: {
|
|
67
67
|
apiKey: process.env.ZHIPU_API_KEY || '',
|
|
68
68
|
baseUrl: process.env.CLI_AI_BASE_URL || 'https://api.z.ai/api/anthropic',
|
|
69
|
-
models: ['glm-5.
|
|
69
|
+
models: ['glm-5.2'],
|
|
70
70
|
},
|
|
71
71
|
minimax: {
|
|
72
72
|
apiKey: '',
|
|
73
73
|
baseUrl: 'https://api.minimax.io/anthropic',
|
|
74
|
-
models: ['MiniMax-
|
|
74
|
+
models: ['MiniMax-M3'],
|
|
75
75
|
},
|
|
76
76
|
openrouter: {
|
|
77
77
|
apiKey: '',
|
|
@@ -588,23 +588,43 @@ export class AgentSessionManager {
|
|
|
588
588
|
finalPrompt = `${skillContent}\n\n${effectivePrompt}`;
|
|
589
589
|
}
|
|
590
590
|
}
|
|
591
|
-
// Inject DB history if context was lost
|
|
591
|
+
// Inject compacted summary or raw DB history if context was lost
|
|
592
592
|
if (session.contextLost) {
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
593
|
+
if (session.compactionSummary) {
|
|
594
|
+
// Use AI-generated summary from compaction
|
|
595
|
+
console.log(`[agentSession] Injecting AI compaction summary for session ${sessionId}`);
|
|
596
|
+
const summaryPrefix = [
|
|
597
|
+
'[Compacted Session Context]',
|
|
598
|
+
'The following is an AI-generated summary of the previous conversation in this session.',
|
|
599
|
+
'Use it as context to continue where you left off.',
|
|
600
|
+
'',
|
|
601
|
+
session.compactionSummary,
|
|
602
|
+
'',
|
|
603
|
+
'[End of Compacted Context]',
|
|
604
|
+
'',
|
|
605
|
+
'',
|
|
606
|
+
].join('\n');
|
|
607
|
+
finalPrompt = summaryPrefix + finalPrompt;
|
|
608
|
+
session.compactionSummary = undefined; // Only inject once
|
|
609
|
+
}
|
|
610
|
+
else {
|
|
611
|
+
// Fallback: inject raw DB history
|
|
612
|
+
console.log(`[agentSession] No compaction summary, fetching DB history for session ${sessionId}`);
|
|
613
|
+
try {
|
|
614
|
+
const history = await this.fetchSessionHistory(sessionId);
|
|
615
|
+
if (history.length > 0) {
|
|
616
|
+
const historyPrefix = this.formatHistoryForPrompt(history);
|
|
617
|
+
finalPrompt = historyPrefix + finalPrompt;
|
|
618
|
+
console.log(`[agentSession] Injected ${history.length} history entries into prompt for session ${sessionId}`);
|
|
619
|
+
}
|
|
620
|
+
else {
|
|
621
|
+
console.log(`[agentSession] No DB history available for session ${sessionId}`);
|
|
622
|
+
}
|
|
600
623
|
}
|
|
601
|
-
|
|
602
|
-
console.
|
|
624
|
+
catch (err) {
|
|
625
|
+
console.error(`[agentSession] Failed to fetch/format history:`, err);
|
|
603
626
|
}
|
|
604
627
|
}
|
|
605
|
-
catch (err) {
|
|
606
|
-
console.error(`[agentSession] Failed to fetch/format history:`, err);
|
|
607
|
-
}
|
|
608
628
|
session.contextLost = false; // Reset after injection attempt
|
|
609
629
|
}
|
|
610
630
|
// Add user message to history
|
|
@@ -719,13 +739,13 @@ export class AgentSessionManager {
|
|
|
719
739
|
resumeSessionId = session.sdkSessionId;
|
|
720
740
|
}
|
|
721
741
|
}
|
|
722
|
-
// Enable auto-compaction: trigger when context reaches ~
|
|
742
|
+
// Enable auto-compaction: trigger when context reaches ~800k (of 1M), keep default target
|
|
723
743
|
if (effectiveSettings) {
|
|
724
744
|
effectiveSettings.autoCompactEnabled = true;
|
|
725
|
-
effectiveSettings.autoCompactWindow =
|
|
745
|
+
effectiveSettings.autoCompactWindow = 800000;
|
|
726
746
|
}
|
|
727
747
|
else {
|
|
728
|
-
effectiveSettings = { autoCompactEnabled: true, autoCompactWindow:
|
|
748
|
+
effectiveSettings = { autoCompactEnabled: true, autoCompactWindow: 800000 };
|
|
729
749
|
}
|
|
730
750
|
// Build backend config
|
|
731
751
|
const backendConfig = {
|
|
@@ -1088,23 +1108,127 @@ export class AgentSessionManager {
|
|
|
1088
1108
|
}
|
|
1089
1109
|
}
|
|
1090
1110
|
/**
|
|
1091
|
-
*
|
|
1092
|
-
*
|
|
1093
|
-
*
|
|
1111
|
+
* AI-powered session compaction.
|
|
1112
|
+
*
|
|
1113
|
+
* 1. Fetches full conversation history from the backend DB
|
|
1114
|
+
* 2. Writes it to a temp file
|
|
1115
|
+
* 3. Spawns a real prompt asking the model to summarize the conversation
|
|
1116
|
+
* 4. Captures the model's summary
|
|
1117
|
+
* 5. Clears the SDK session and stores the summary for injection on next prompt
|
|
1118
|
+
*
|
|
1119
|
+
* Returns true if the compaction prompt was queued successfully.
|
|
1120
|
+
* The `onCompactionComplete` callback fires when the model finishes summarizing.
|
|
1094
1121
|
*/
|
|
1095
|
-
compactSession(sessionId) {
|
|
1122
|
+
async compactSession(sessionId, projectPath, onOutput, onCompactionComplete) {
|
|
1096
1123
|
const session = this.sessions.get(sessionId);
|
|
1097
1124
|
if (!session)
|
|
1098
1125
|
return false;
|
|
1099
1126
|
// Don't compact while a prompt is actively running
|
|
1100
1127
|
if (session.isProcessingQueue && session.activeBackendStream)
|
|
1101
1128
|
return false;
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1129
|
+
// 1. Fetch conversation history from DB
|
|
1130
|
+
const history = await this.fetchSessionHistory(sessionId);
|
|
1131
|
+
if (history.length === 0) {
|
|
1132
|
+
console.log(`[AgentSessionManager] No history to compact for session ${sessionId}`);
|
|
1133
|
+
// Still allow compaction even without history — just clears context
|
|
1134
|
+
session.sdkSessionId = undefined;
|
|
1135
|
+
session.contextLost = true;
|
|
1136
|
+
session.messages = [];
|
|
1137
|
+
deleteSessionState(sessionId);
|
|
1138
|
+
onCompactionComplete?.(true, 'Session context cleared (no history available)');
|
|
1139
|
+
return true;
|
|
1140
|
+
}
|
|
1141
|
+
console.log(`[AgentSessionManager] Starting AI compaction for session ${sessionId} with ${history.length} history entries`);
|
|
1142
|
+
// 2. Build the conversation text
|
|
1143
|
+
const conversationLines = [];
|
|
1144
|
+
for (const entry of history) {
|
|
1145
|
+
const content = typeof entry.content === 'string' ? entry.content : JSON.stringify(entry.content);
|
|
1146
|
+
conversationLines.push(`=== ${entry.role.toUpperCase()} ===\n${content}`);
|
|
1147
|
+
}
|
|
1148
|
+
const conversationText = conversationLines.join('\n\n');
|
|
1149
|
+
// 3. Write conversation to a temp file
|
|
1150
|
+
const attachmentDir = path.join(os.tmpdir(), 'talk-to-code', 'compaction', sessionId);
|
|
1151
|
+
mkdirSync(attachmentDir, { recursive: true });
|
|
1152
|
+
const conversationFilePath = path.join(attachmentDir, 'conversation.md');
|
|
1153
|
+
writeFileSync(conversationFilePath, conversationText, 'utf-8');
|
|
1154
|
+
// 4. Build the compaction prompt
|
|
1155
|
+
const compactionPrompt = [
|
|
1156
|
+
'You are performing a CONTEXT COMPACTION for an ongoing coding session.',
|
|
1157
|
+
'',
|
|
1158
|
+
'Read the full conversation history in the attached file `conversation.md`.',
|
|
1159
|
+
'',
|
|
1160
|
+
'Your task: Create a comprehensive summary that captures:',
|
|
1161
|
+
'1. What the user is working on (project, goals, current task)',
|
|
1162
|
+
'2. All decisions made and their reasoning',
|
|
1163
|
+
'3. The current state of the codebase (what was changed, added, removed)',
|
|
1164
|
+
'4. Any open issues, bugs, or TODOs discussed',
|
|
1165
|
+
'5. Important technical details (file paths, configurations, API designs)',
|
|
1166
|
+
'6. The last thing the user was doing or about to do',
|
|
1167
|
+
'',
|
|
1168
|
+
'Be thorough but concise. Include specific file paths, code snippets, and technical details.',
|
|
1169
|
+
'This summary will be the ONLY context carried forward — everything else is lost.',
|
|
1170
|
+
'',
|
|
1171
|
+
'Format the summary as a structured document with clear sections.',
|
|
1172
|
+
'Write the summary directly — no preamble or meta-commentary.',
|
|
1173
|
+
].join('\n');
|
|
1174
|
+
// 5. Create a synthetic attachment for the conversation file
|
|
1175
|
+
const attachment = {
|
|
1176
|
+
filename: 'conversation.md',
|
|
1177
|
+
mimeType: 'text/markdown',
|
|
1178
|
+
content: Buffer.from(conversationText).toString('base64'),
|
|
1179
|
+
};
|
|
1180
|
+
// 6. Spawn a compaction prompt through the normal pipeline
|
|
1181
|
+
const compactionPromptId = `compact-${sessionId}-${Date.now()}`;
|
|
1182
|
+
let summaryParts = [];
|
|
1183
|
+
await this.sendPrompt(sessionId, compactionPrompt, [], {
|
|
1184
|
+
sessionId,
|
|
1185
|
+
projectPath,
|
|
1186
|
+
promptId: compactionPromptId,
|
|
1187
|
+
model: session.model,
|
|
1188
|
+
attachments: [attachment],
|
|
1189
|
+
onOutput: (output) => {
|
|
1190
|
+
// Forward to caller for UI display (shows compacting progress)
|
|
1191
|
+
onOutput?.(output);
|
|
1192
|
+
// Capture assistant text for the summary
|
|
1193
|
+
if (output.type === 'assistant' && output.data) {
|
|
1194
|
+
const d = output.data;
|
|
1195
|
+
const text = typeof output.data === 'string'
|
|
1196
|
+
? output.data
|
|
1197
|
+
: (d?.content?.[0]?.text || d?.text || '');
|
|
1198
|
+
if (text)
|
|
1199
|
+
summaryParts.push(text);
|
|
1200
|
+
}
|
|
1201
|
+
},
|
|
1202
|
+
onError: (error) => {
|
|
1203
|
+
console.error(`[AgentSessionManager] Compaction prompt error: ${error}`);
|
|
1204
|
+
onCompactionComplete?.(false, `Compaction failed: ${error}`);
|
|
1205
|
+
},
|
|
1206
|
+
onComplete: (exitCode) => {
|
|
1207
|
+
const summary = summaryParts.join('\n').trim();
|
|
1208
|
+
if (summary && exitCode === 0) {
|
|
1209
|
+
// Store summary and clear old context
|
|
1210
|
+
session.compactionSummary = summary;
|
|
1211
|
+
session.sdkSessionId = undefined;
|
|
1212
|
+
session.contextLost = true;
|
|
1213
|
+
session.messages = [];
|
|
1214
|
+
deleteSessionState(sessionId);
|
|
1215
|
+
console.log(`[AgentSessionManager] AI compaction complete for session ${sessionId} (${summary.length} chars summary)`);
|
|
1216
|
+
onCompactionComplete?.(true, 'Session context compacted with AI summary');
|
|
1217
|
+
}
|
|
1218
|
+
else {
|
|
1219
|
+
// Compaction prompt failed — fall back to simple clear
|
|
1220
|
+
session.sdkSessionId = undefined;
|
|
1221
|
+
session.contextLost = true;
|
|
1222
|
+
session.messages = [];
|
|
1223
|
+
deleteSessionState(sessionId);
|
|
1224
|
+
console.warn(`[AgentSessionManager] Compaction prompt failed (exit=${exitCode}), falling back to simple clear`);
|
|
1225
|
+
onCompactionComplete?.(true, 'Session context cleared (compaction prompt did not produce summary)');
|
|
1226
|
+
}
|
|
1227
|
+
},
|
|
1228
|
+
onStatusUpdate: () => {
|
|
1229
|
+
// Status updates from the compaction prompt — ignore
|
|
1230
|
+
},
|
|
1231
|
+
});
|
|
1108
1232
|
return true;
|
|
1109
1233
|
}
|
|
1110
1234
|
/**
|
|
@@ -262,7 +262,7 @@ async function runSdkBenchmark(provider) {
|
|
|
262
262
|
// ── Main ────────────────────────────────────────────────────────────
|
|
263
263
|
async function main() {
|
|
264
264
|
console.log(`\n${BOLD}╔══════════════════════════════════════════════════════════════════════╗${RESET}`);
|
|
265
|
-
console.log(`${BOLD}║ SDK Benchmark: MiniMax
|
|
265
|
+
console.log(`${BOLD}║ SDK Benchmark: MiniMax M3 vs Cerebras zai-glm-4.7 ║${RESET}`);
|
|
266
266
|
console.log(`${BOLD}║ Task: Generate a complete HTML real estate page ║${RESET}`);
|
|
267
267
|
console.log(`${BOLD}╚══════════════════════════════════════════════════════════════════════╝${RESET}\n`);
|
|
268
268
|
const config = loadConfig();
|
|
@@ -278,8 +278,8 @@ async function main() {
|
|
|
278
278
|
const providers = [];
|
|
279
279
|
if (minimaxKey) {
|
|
280
280
|
providers.push({
|
|
281
|
-
name: 'MiniMax
|
|
282
|
-
model: 'MiniMax-
|
|
281
|
+
name: 'MiniMax M3',
|
|
282
|
+
model: 'MiniMax-M3',
|
|
283
283
|
apiKey: minimaxKey,
|
|
284
284
|
baseUrl: 'https://api.minimax.io/anthropic',
|
|
285
285
|
needsProxy: false,
|
|
@@ -188,6 +188,8 @@ export class ClaudeBackend {
|
|
|
188
188
|
settingSources: ['project'],
|
|
189
189
|
permissionMode: 'bypassPermissions',
|
|
190
190
|
allowDangerouslySkipPermissions: true,
|
|
191
|
+
// Enable 1M token context window (GLM-5.2 supports 1M context via z.ai)
|
|
192
|
+
betas: ['context-1m-2025-08-07'],
|
|
191
193
|
mcpServers: { 'claude-voice-modules': mcpServer },
|
|
192
194
|
...(pathToClaudeCodeExecutable ? { pathToClaudeCodeExecutable } : {}),
|
|
193
195
|
spawnClaudeCodeProcess: (spawnOptions) => {
|
|
@@ -250,26 +250,58 @@ export function registerSessionHandlers(socket, foreground, activeSessions, getS
|
|
|
250
250
|
callback?.({ success: false, message: 'Missing sessionId' });
|
|
251
251
|
return;
|
|
252
252
|
}
|
|
253
|
+
const sessionInfo = activeSessions.get(sessionId);
|
|
254
|
+
if (!sessionInfo) {
|
|
255
|
+
callback?.({ success: false, message: 'Session not found' });
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
253
258
|
if (foreground) {
|
|
254
259
|
console.log(`[CLI] Compacting session: ${sessionId}`);
|
|
255
260
|
}
|
|
256
|
-
|
|
257
|
-
|
|
261
|
+
// Respond immediately — compaction runs in the background
|
|
262
|
+
callback?.({ success: true, message: 'Compaction started' });
|
|
263
|
+
const compacted = await agentSessionManager.compactSession(sessionId, sessionInfo.projectPath, (output) => {
|
|
264
|
+
// Forward compaction prompt output to the backend for UI display
|
|
265
|
+
const compactPromptId = `compact-${sessionId}`;
|
|
266
|
+
getSocket().emit('prompt:output', {
|
|
267
|
+
sessionId,
|
|
268
|
+
promptId: compactPromptId,
|
|
269
|
+
type: output.type,
|
|
270
|
+
data: output.data,
|
|
271
|
+
timestamp: output.timestamp,
|
|
272
|
+
metadata: { ...output.metadata, isCompaction: true },
|
|
273
|
+
});
|
|
274
|
+
}, (success, message) => {
|
|
275
|
+
// Compaction finished — notify UI
|
|
258
276
|
getSocket().emit('session:compacted', {
|
|
259
277
|
sessionId,
|
|
260
278
|
timestamp: Date.now(),
|
|
279
|
+
success,
|
|
280
|
+
message,
|
|
281
|
+
});
|
|
282
|
+
if (foreground) {
|
|
283
|
+
console.log(`[CLI] Compaction ${success ? 'complete' : 'failed'}: ${message}`);
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
if (!compacted) {
|
|
287
|
+
getSocket().emit('session:compacted', {
|
|
288
|
+
sessionId,
|
|
289
|
+
timestamp: Date.now(),
|
|
290
|
+
success: false,
|
|
291
|
+
message: 'Session not found or prompt is running',
|
|
261
292
|
});
|
|
262
|
-
callback?.({ success: true, message: 'Session context compacted' });
|
|
263
|
-
}
|
|
264
|
-
else {
|
|
265
|
-
callback?.({ success: false, message: 'Session not found or prompt is running' });
|
|
266
293
|
}
|
|
267
294
|
}
|
|
268
295
|
catch (error) {
|
|
269
296
|
if (foreground) {
|
|
270
297
|
console.error(`✗ Error compacting session: ${error.message}`);
|
|
271
298
|
}
|
|
272
|
-
|
|
299
|
+
getSocket().emit('session:compacted', {
|
|
300
|
+
sessionId: data.sessionId,
|
|
301
|
+
timestamp: Date.now(),
|
|
302
|
+
success: false,
|
|
303
|
+
message: error.message,
|
|
304
|
+
});
|
|
273
305
|
}
|
|
274
306
|
});
|
|
275
307
|
socket.on('emergency:stop', async (data, callback) => {
|
package/dist/ttc-cli.tar.gz
CHANGED
|
Binary file
|