claudia-orchestrator 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +109 -0
- package/dist/cli-parser.d.ts +11 -0
- package/dist/cli-parser.d.ts.map +1 -0
- package/dist/cli-parser.js +57 -0
- package/dist/cli-parser.js.map +1 -0
- package/dist/cui-server.d.ts +69 -0
- package/dist/cui-server.d.ts.map +1 -0
- package/dist/cui-server.js +705 -0
- package/dist/cui-server.js.map +1 -0
- package/dist/mcp-server/claudia-tools.d.ts +15 -0
- package/dist/mcp-server/claudia-tools.d.ts.map +1 -0
- package/dist/mcp-server/claudia-tools.js +366 -0
- package/dist/mcp-server/claudia-tools.js.map +1 -0
- package/dist/mcp-server/index.d.ts +3 -0
- package/dist/mcp-server/index.d.ts.map +1 -0
- package/dist/mcp-server/index.js +176 -0
- package/dist/mcp-server/index.js.map +1 -0
- package/dist/middleware/auth.d.ts +18 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +136 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/cors-setup.d.ts +7 -0
- package/dist/middleware/cors-setup.d.ts.map +1 -0
- package/dist/middleware/cors-setup.js +8 -0
- package/dist/middleware/cors-setup.js.map +1 -0
- package/dist/middleware/error-handler.d.ts +4 -0
- package/dist/middleware/error-handler.d.ts.map +1 -0
- package/dist/middleware/error-handler.js +27 -0
- package/dist/middleware/error-handler.js.map +1 -0
- package/dist/middleware/query-parser.d.ts +11 -0
- package/dist/middleware/query-parser.d.ts.map +1 -0
- package/dist/middleware/query-parser.js +68 -0
- package/dist/middleware/query-parser.js.map +1 -0
- package/dist/middleware/request-logger.d.ts +4 -0
- package/dist/middleware/request-logger.d.ts.map +1 -0
- package/dist/middleware/request-logger.js +29 -0
- package/dist/middleware/request-logger.js.map +1 -0
- package/dist/process-daemon/index.d.ts +14 -0
- package/dist/process-daemon/index.d.ts.map +1 -0
- package/dist/process-daemon/index.js +51 -0
- package/dist/process-daemon/index.js.map +1 -0
- package/dist/process-daemon/process-daemon.d.ts +78 -0
- package/dist/process-daemon/process-daemon.d.ts.map +1 -0
- package/dist/process-daemon/process-daemon.js +568 -0
- package/dist/process-daemon/process-daemon.js.map +1 -0
- package/dist/process-daemon/process-manager-client.d.ts +108 -0
- package/dist/process-daemon/process-manager-client.d.ts.map +1 -0
- package/dist/process-daemon/process-manager-client.js +314 -0
- package/dist/process-daemon/process-manager-client.js.map +1 -0
- package/dist/process-daemon/process-manager-interface.d.ts +47 -0
- package/dist/process-daemon/process-manager-interface.d.ts.map +1 -0
- package/dist/process-daemon/process-manager-interface.js +8 -0
- package/dist/process-daemon/process-manager-interface.js.map +1 -0
- package/dist/process-daemon/test-daemon.d.ts +12 -0
- package/dist/process-daemon/test-daemon.d.ts.map +1 -0
- package/dist/process-daemon/test-daemon.js +81 -0
- package/dist/process-daemon/test-daemon.js.map +1 -0
- package/dist/process-daemon/types.d.ts +85 -0
- package/dist/process-daemon/types.d.ts.map +1 -0
- package/dist/process-daemon/types.js +8 -0
- package/dist/process-daemon/types.js.map +1 -0
- package/dist/routes/claudia.routes.d.ts +10 -0
- package/dist/routes/claudia.routes.d.ts.map +1 -0
- package/dist/routes/claudia.routes.js +123 -0
- package/dist/routes/claudia.routes.js.map +1 -0
- package/dist/routes/config.routes.d.ts +4 -0
- package/dist/routes/config.routes.d.ts.map +1 -0
- package/dist/routes/config.routes.js +27 -0
- package/dist/routes/config.routes.js.map +1 -0
- package/dist/routes/conversation.routes.d.ts +8 -0
- package/dist/routes/conversation.routes.d.ts.map +1 -0
- package/dist/routes/conversation.routes.js +870 -0
- package/dist/routes/conversation.routes.js.map +1 -0
- package/dist/routes/filesystem.routes.d.ts +4 -0
- package/dist/routes/filesystem.routes.d.ts.map +1 -0
- package/dist/routes/filesystem.routes.js +86 -0
- package/dist/routes/filesystem.routes.js.map +1 -0
- package/dist/routes/gemini.routes.d.ts +4 -0
- package/dist/routes/gemini.routes.d.ts.map +1 -0
- package/dist/routes/gemini.routes.js +93 -0
- package/dist/routes/gemini.routes.js.map +1 -0
- package/dist/routes/insights.routes.d.ts +17 -0
- package/dist/routes/insights.routes.d.ts.map +1 -0
- package/dist/routes/insights.routes.js +417 -0
- package/dist/routes/insights.routes.js.map +1 -0
- package/dist/routes/license.routes.d.ts +3 -0
- package/dist/routes/license.routes.d.ts.map +1 -0
- package/dist/routes/license.routes.js +111 -0
- package/dist/routes/license.routes.js.map +1 -0
- package/dist/routes/log.routes.d.ts +3 -0
- package/dist/routes/log.routes.d.ts.map +1 -0
- package/dist/routes/log.routes.js +65 -0
- package/dist/routes/log.routes.js.map +1 -0
- package/dist/routes/notifications.routes.d.ts +4 -0
- package/dist/routes/notifications.routes.d.ts.map +1 -0
- package/dist/routes/notifications.routes.js +71 -0
- package/dist/routes/notifications.routes.js.map +1 -0
- package/dist/routes/permission.routes.d.ts +4 -0
- package/dist/routes/permission.routes.d.ts.map +1 -0
- package/dist/routes/permission.routes.js +116 -0
- package/dist/routes/permission.routes.js.map +1 -0
- package/dist/routes/question.routes.d.ts +8 -0
- package/dist/routes/question.routes.d.ts.map +1 -0
- package/dist/routes/question.routes.js +82 -0
- package/dist/routes/question.routes.js.map +1 -0
- package/dist/routes/streaming.routes.d.ts +4 -0
- package/dist/routes/streaming.routes.d.ts.map +1 -0
- package/dist/routes/streaming.routes.js +28 -0
- package/dist/routes/streaming.routes.js.map +1 -0
- package/dist/routes/system.routes.d.ts +5 -0
- package/dist/routes/system.routes.d.ts.map +1 -0
- package/dist/routes/system.routes.js +103 -0
- package/dist/routes/system.routes.js.map +1 -0
- package/dist/routes/working-directories.routes.d.ts +4 -0
- package/dist/routes/working-directories.routes.d.ts.map +1 -0
- package/dist/routes/working-directories.routes.js +25 -0
- package/dist/routes/working-directories.routes.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +34 -0
- package/dist/server.js.map +1 -0
- package/dist/services/ToolMetricsService.d.ts +53 -0
- package/dist/services/ToolMetricsService.d.ts.map +1 -0
- package/dist/services/ToolMetricsService.js +230 -0
- package/dist/services/ToolMetricsService.js.map +1 -0
- package/dist/services/anthropic-service.d.ts +186 -0
- package/dist/services/anthropic-service.d.ts.map +1 -0
- package/dist/services/anthropic-service.js +1132 -0
- package/dist/services/anthropic-service.js.map +1 -0
- package/dist/services/claude-history-reader.d.ts +126 -0
- package/dist/services/claude-history-reader.d.ts.map +1 -0
- package/dist/services/claude-history-reader.js +717 -0
- package/dist/services/claude-history-reader.js.map +1 -0
- package/dist/services/claude-process-manager.d.ts +108 -0
- package/dist/services/claude-process-manager.d.ts.map +1 -0
- package/dist/services/claude-process-manager.js +909 -0
- package/dist/services/claude-process-manager.js.map +1 -0
- package/dist/services/claude-router-service.d.ts +19 -0
- package/dist/services/claude-router-service.d.ts.map +1 -0
- package/dist/services/claude-router-service.js +160 -0
- package/dist/services/claude-router-service.js.map +1 -0
- package/dist/services/claudia-service.d.ts +77 -0
- package/dist/services/claudia-service.d.ts.map +1 -0
- package/dist/services/claudia-service.js +194 -0
- package/dist/services/claudia-service.js.map +1 -0
- package/dist/services/commands-service.d.ts +18 -0
- package/dist/services/commands-service.d.ts.map +1 -0
- package/dist/services/commands-service.js +76 -0
- package/dist/services/commands-service.js.map +1 -0
- package/dist/services/config-service.d.ts +68 -0
- package/dist/services/config-service.d.ts.map +1 -0
- package/dist/services/config-service.js +429 -0
- package/dist/services/config-service.js.map +1 -0
- package/dist/services/conversation-cache.d.ts +86 -0
- package/dist/services/conversation-cache.d.ts.map +1 -0
- package/dist/services/conversation-cache.js +235 -0
- package/dist/services/conversation-cache.js.map +1 -0
- package/dist/services/conversation-status-manager.d.ts +98 -0
- package/dist/services/conversation-status-manager.d.ts.map +1 -0
- package/dist/services/conversation-status-manager.js +295 -0
- package/dist/services/conversation-status-manager.js.map +1 -0
- package/dist/services/cost-tracker.d.ts +87 -0
- package/dist/services/cost-tracker.d.ts.map +1 -0
- package/dist/services/cost-tracker.js +335 -0
- package/dist/services/cost-tracker.js.map +1 -0
- package/dist/services/file-system-service.d.ts +61 -0
- package/dist/services/file-system-service.d.ts.map +1 -0
- package/dist/services/file-system-service.js +348 -0
- package/dist/services/file-system-service.js.map +1 -0
- package/dist/services/gemini-service.d.ts +72 -0
- package/dist/services/gemini-service.d.ts.map +1 -0
- package/dist/services/gemini-service.js +431 -0
- package/dist/services/gemini-service.js.map +1 -0
- package/dist/services/insight-queue.d.ts +99 -0
- package/dist/services/insight-queue.d.ts.map +1 -0
- package/dist/services/insight-queue.js +277 -0
- package/dist/services/insight-queue.js.map +1 -0
- package/dist/services/insights-service.d.ts +102 -0
- package/dist/services/insights-service.d.ts.map +1 -0
- package/dist/services/insights-service.js +1152 -0
- package/dist/services/insights-service.js.map +1 -0
- package/dist/services/json-lines-parser.d.ts +19 -0
- package/dist/services/json-lines-parser.d.ts.map +1 -0
- package/dist/services/json-lines-parser.js +56 -0
- package/dist/services/json-lines-parser.js.map +1 -0
- package/dist/services/license-service.d.ts +69 -0
- package/dist/services/license-service.d.ts.map +1 -0
- package/dist/services/license-service.js +330 -0
- package/dist/services/license-service.js.map +1 -0
- package/dist/services/log-formatter.d.ts +5 -0
- package/dist/services/log-formatter.d.ts.map +1 -0
- package/dist/services/log-formatter.js +77 -0
- package/dist/services/log-formatter.js.map +1 -0
- package/dist/services/log-stream-buffer.d.ts +11 -0
- package/dist/services/log-stream-buffer.d.ts.map +1 -0
- package/dist/services/log-stream-buffer.js +36 -0
- package/dist/services/log-stream-buffer.js.map +1 -0
- package/dist/services/logger.d.ts +71 -0
- package/dist/services/logger.d.ts.map +1 -0
- package/dist/services/logger.js +215 -0
- package/dist/services/logger.js.map +1 -0
- package/dist/services/mcp-config-generator.d.ts +32 -0
- package/dist/services/mcp-config-generator.d.ts.map +1 -0
- package/dist/services/mcp-config-generator.js +126 -0
- package/dist/services/mcp-config-generator.js.map +1 -0
- package/dist/services/message-filter.d.ts +22 -0
- package/dist/services/message-filter.d.ts.map +1 -0
- package/dist/services/message-filter.js +57 -0
- package/dist/services/message-filter.js.map +1 -0
- package/dist/services/notification-service.d.ts +45 -0
- package/dist/services/notification-service.d.ts.map +1 -0
- package/dist/services/notification-service.js +184 -0
- package/dist/services/notification-service.js.map +1 -0
- package/dist/services/permission-tracker.d.ts +67 -0
- package/dist/services/permission-tracker.d.ts.map +1 -0
- package/dist/services/permission-tracker.js +161 -0
- package/dist/services/permission-tracker.js.map +1 -0
- package/dist/services/process-manager-factory.d.ts +81 -0
- package/dist/services/process-manager-factory.d.ts.map +1 -0
- package/dist/services/process-manager-factory.js +211 -0
- package/dist/services/process-manager-factory.js.map +1 -0
- package/dist/services/question-tracker.d.ts +47 -0
- package/dist/services/question-tracker.d.ts.map +1 -0
- package/dist/services/question-tracker.js +105 -0
- package/dist/services/question-tracker.js.map +1 -0
- package/dist/services/session-activity-watcher.d.ts +33 -0
- package/dist/services/session-activity-watcher.d.ts.map +1 -0
- package/dist/services/session-activity-watcher.js +194 -0
- package/dist/services/session-activity-watcher.js.map +1 -0
- package/dist/services/session-info-service.d.ts +228 -0
- package/dist/services/session-info-service.d.ts.map +1 -0
- package/dist/services/session-info-service.js +920 -0
- package/dist/services/session-info-service.js.map +1 -0
- package/dist/services/session-insights-service.d.ts +119 -0
- package/dist/services/session-insights-service.d.ts.map +1 -0
- package/dist/services/session-insights-service.js +889 -0
- package/dist/services/session-insights-service.js.map +1 -0
- package/dist/services/stream-manager.d.ts +62 -0
- package/dist/services/stream-manager.d.ts.map +1 -0
- package/dist/services/stream-manager.js +239 -0
- package/dist/services/stream-manager.js.map +1 -0
- package/dist/services/web-push-service.d.ts +48 -0
- package/dist/services/web-push-service.d.ts.map +1 -0
- package/dist/services/web-push-service.js +186 -0
- package/dist/services/web-push-service.js.map +1 -0
- package/dist/services/working-directories-service.d.ts +19 -0
- package/dist/services/working-directories-service.d.ts.map +1 -0
- package/dist/services/working-directories-service.js +103 -0
- package/dist/services/working-directories-service.js.map +1 -0
- package/dist/types/config.d.ts +111 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +14 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/express.d.ts +5 -0
- package/dist/types/express.d.ts.map +1 -0
- package/dist/types/express.js +2 -0
- package/dist/types/express.js.map +1 -0
- package/dist/types/index.d.ts +325 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +18 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/insights.d.ts +99 -0
- package/dist/types/insights.d.ts.map +1 -0
- package/dist/types/insights.js +7 -0
- package/dist/types/insights.js.map +1 -0
- package/dist/types/license.d.ts +70 -0
- package/dist/types/license.d.ts.map +1 -0
- package/dist/types/license.js +5 -0
- package/dist/types/license.js.map +1 -0
- package/dist/types/router-config.d.ts +13 -0
- package/dist/types/router-config.d.ts.map +1 -0
- package/dist/types/router-config.js +2 -0
- package/dist/types/router-config.js.map +1 -0
- package/dist/utils/constants.d.ts +26 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +28 -0
- package/dist/utils/constants.js.map +1 -0
- package/dist/utils/machine-id.d.ts +7 -0
- package/dist/utils/machine-id.d.ts.map +1 -0
- package/dist/utils/machine-id.js +76 -0
- package/dist/utils/machine-id.js.map +1 -0
- package/dist/utils/server-startup.d.ts +13 -0
- package/dist/utils/server-startup.d.ts.map +1 -0
- package/dist/utils/server-startup.js +20 -0
- package/dist/utils/server-startup.js.map +1 -0
- package/dist/web/assets/main-DAc2rjJ2.css +1 -0
- package/dist/web/assets/main-DvlZ02mT.js +137 -0
- package/dist/web/favicon.png +0 -0
- package/dist/web/favicon.svg +22 -0
- package/dist/web/icon-192x192.png +0 -0
- package/dist/web/icon-512x512.png +0 -0
- package/dist/web/index.html +36 -0
- package/dist/web/manifest.json +61 -0
- package/package.json +174 -0
- package/scripts/postinstall.js +30 -0
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { createLogger } from './logger.js';
|
|
2
|
+
/**
|
|
3
|
+
* Service for managing conversation cache with file modification tracking
|
|
4
|
+
*/
|
|
5
|
+
export class ConversationCache {
|
|
6
|
+
cache = null;
|
|
7
|
+
logger;
|
|
8
|
+
parsingPromises = new Map();
|
|
9
|
+
constructor() {
|
|
10
|
+
this.logger = createLogger('ConversationCache');
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Clear the conversation cache to force a refresh on next read
|
|
14
|
+
*/
|
|
15
|
+
clear() {
|
|
16
|
+
this.logger.debug('Clearing conversation cache');
|
|
17
|
+
const previousStats = this.cache ? {
|
|
18
|
+
cachedFileCount: this.cache.fileCache.size,
|
|
19
|
+
totalEntries: Array.from(this.cache.fileCache.values())
|
|
20
|
+
.reduce((sum, cache) => sum + cache.entries.length, 0)
|
|
21
|
+
} : { cachedFileCount: 0, totalEntries: 0 };
|
|
22
|
+
this.cache = null;
|
|
23
|
+
this.parsingPromises.clear();
|
|
24
|
+
this.logger.info('Conversation cache cleared', {
|
|
25
|
+
previousStats,
|
|
26
|
+
timestamp: new Date().toISOString()
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Get cached file entries, combining cached and newly parsed entries
|
|
31
|
+
*/
|
|
32
|
+
async getCachedFileEntries(currentFileModTimes, parseFileFunction, getSourceProject) {
|
|
33
|
+
this.logger.debug('Getting cached file entries', {
|
|
34
|
+
hasCachedData: !!this.cache,
|
|
35
|
+
currentFileCount: currentFileModTimes.size
|
|
36
|
+
});
|
|
37
|
+
// Initialize cache if it doesn't exist
|
|
38
|
+
if (!this.cache) {
|
|
39
|
+
this.cache = {
|
|
40
|
+
fileCache: new Map(),
|
|
41
|
+
lastCacheTime: Date.now()
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const allEntries = [];
|
|
45
|
+
let filesFromCache = 0;
|
|
46
|
+
let filesReparsed = 0;
|
|
47
|
+
// Process each file: use cache OR re-parse if changed
|
|
48
|
+
for (const [filePath, currentMtime] of currentFileModTimes) {
|
|
49
|
+
const cached = this.cache.fileCache.get(filePath);
|
|
50
|
+
if (cached && cached.mtime === currentMtime) {
|
|
51
|
+
// Use cached entries (skip expensive file I/O + JSON parsing)
|
|
52
|
+
const entriesWithSource = cached.entries.map(entry => ({
|
|
53
|
+
...entry,
|
|
54
|
+
sourceProject: cached.sourceProject
|
|
55
|
+
}));
|
|
56
|
+
allEntries.push(...entriesWithSource);
|
|
57
|
+
filesFromCache++;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
// Re-parse this file (expensive operation)
|
|
61
|
+
try {
|
|
62
|
+
const entries = await parseFileFunction(filePath);
|
|
63
|
+
const sourceProject = getSourceProject(filePath);
|
|
64
|
+
// Update cache for this file
|
|
65
|
+
this.cache.fileCache.set(filePath, {
|
|
66
|
+
entries,
|
|
67
|
+
mtime: currentMtime,
|
|
68
|
+
sourceProject
|
|
69
|
+
});
|
|
70
|
+
const entriesWithSource = entries.map(entry => ({
|
|
71
|
+
...entry,
|
|
72
|
+
sourceProject
|
|
73
|
+
}));
|
|
74
|
+
allEntries.push(...entriesWithSource);
|
|
75
|
+
filesReparsed++;
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
this.logger.warn('Failed to parse file, skipping', { filePath, error });
|
|
79
|
+
// Remove from cache if it exists
|
|
80
|
+
this.cache.fileCache.delete(filePath);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Clean up cache entries for files that no longer exist
|
|
85
|
+
for (const [cachedFilePath] of this.cache.fileCache) {
|
|
86
|
+
if (!currentFileModTimes.has(cachedFilePath)) {
|
|
87
|
+
this.logger.debug('Removing cache entry for deleted file', { filePath: cachedFilePath });
|
|
88
|
+
this.cache.fileCache.delete(cachedFilePath);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
this.logger.debug('File cache processing complete', {
|
|
92
|
+
totalFiles: currentFileModTimes.size,
|
|
93
|
+
filesFromCache,
|
|
94
|
+
filesReparsed,
|
|
95
|
+
totalEntries: allEntries.length,
|
|
96
|
+
cachedFileCount: this.cache.fileCache.size
|
|
97
|
+
});
|
|
98
|
+
return allEntries;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Update a specific file's cache entry
|
|
102
|
+
*/
|
|
103
|
+
updateFileCache(filePath, entries, mtime, sourceProject) {
|
|
104
|
+
if (!this.cache) {
|
|
105
|
+
this.cache = {
|
|
106
|
+
fileCache: new Map(),
|
|
107
|
+
lastCacheTime: Date.now()
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
this.cache.fileCache.set(filePath, {
|
|
111
|
+
entries,
|
|
112
|
+
mtime,
|
|
113
|
+
sourceProject
|
|
114
|
+
});
|
|
115
|
+
this.logger.debug('File cache updated', {
|
|
116
|
+
filePath,
|
|
117
|
+
entryCount: entries.length,
|
|
118
|
+
sourceProject,
|
|
119
|
+
mtime: new Date(mtime).toISOString()
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Clear cache entry for a specific file
|
|
124
|
+
*/
|
|
125
|
+
clearFileCache(filePath) {
|
|
126
|
+
if (this.cache?.fileCache.has(filePath)) {
|
|
127
|
+
this.cache.fileCache.delete(filePath);
|
|
128
|
+
this.logger.debug('File cache cleared', { filePath });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Check if a specific file's cache entry is valid
|
|
133
|
+
*/
|
|
134
|
+
isFileCacheValid(filePath, currentMtime) {
|
|
135
|
+
if (!this.cache) {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
const cached = this.cache.fileCache.get(filePath);
|
|
139
|
+
return cached ? cached.mtime === currentMtime : false;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Get or parse conversations with file-level caching and concurrency protection
|
|
143
|
+
*/
|
|
144
|
+
async getOrParseConversations(currentFileModTimes, parseFileFunction, getSourceProject, processAllEntries) {
|
|
145
|
+
// Create cache key based on file set to avoid returning wrong results for different filters
|
|
146
|
+
const cacheKey = Array.from(currentFileModTimes.keys()).sort().join('|');
|
|
147
|
+
this.logger.debug('Request for conversations received', {
|
|
148
|
+
hasCachedData: !!this.cache,
|
|
149
|
+
activeParsings: this.parsingPromises.size,
|
|
150
|
+
currentFileCount: currentFileModTimes.size
|
|
151
|
+
});
|
|
152
|
+
// If already parsing THIS SAME file set, wait for it to complete
|
|
153
|
+
const existingPromise = this.parsingPromises.get(cacheKey);
|
|
154
|
+
if (existingPromise) {
|
|
155
|
+
this.logger.debug('Parsing already in progress for this file set, waiting for completion', {
|
|
156
|
+
fileCount: currentFileModTimes.size
|
|
157
|
+
});
|
|
158
|
+
try {
|
|
159
|
+
const result = await existingPromise;
|
|
160
|
+
this.logger.debug('Concurrent parsing completed, returning result', {
|
|
161
|
+
conversationCount: result.length
|
|
162
|
+
});
|
|
163
|
+
return result;
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
this.logger.error('Concurrent parsing failed', error);
|
|
167
|
+
// Clear the failed promise and fall through to retry
|
|
168
|
+
this.parsingPromises.delete(cacheKey);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const parsingPromise = this.executeFileBasedParsing(currentFileModTimes, parseFileFunction, getSourceProject, processAllEntries);
|
|
172
|
+
this.parsingPromises.set(cacheKey, parsingPromise);
|
|
173
|
+
try {
|
|
174
|
+
const result = await parsingPromise;
|
|
175
|
+
this.parsingPromises.delete(cacheKey);
|
|
176
|
+
return result;
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
this.parsingPromises.delete(cacheKey);
|
|
180
|
+
throw error;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Execute file-based parsing with proper logging
|
|
185
|
+
*/
|
|
186
|
+
async executeFileBasedParsing(currentFileModTimes, parseFileFunction, getSourceProject, processAllEntries) {
|
|
187
|
+
const parseStartTime = Date.now();
|
|
188
|
+
this.logger.debug('Executing file-based parsing');
|
|
189
|
+
// Get all entries using file-level caching
|
|
190
|
+
const allEntries = await this.getCachedFileEntries(currentFileModTimes, parseFileFunction, getSourceProject);
|
|
191
|
+
// Process entries into conversations (cheap in-memory operation)
|
|
192
|
+
const conversations = processAllEntries(allEntries);
|
|
193
|
+
const parseElapsed = Date.now() - parseStartTime;
|
|
194
|
+
this.logger.debug('File-based parsing completed', {
|
|
195
|
+
conversationCount: conversations.length,
|
|
196
|
+
totalEntries: allEntries.length,
|
|
197
|
+
parseElapsedMs: parseElapsed
|
|
198
|
+
});
|
|
199
|
+
return conversations;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Get cache statistics for monitoring
|
|
203
|
+
*/
|
|
204
|
+
getStats() {
|
|
205
|
+
if (!this.cache) {
|
|
206
|
+
return {
|
|
207
|
+
isLoaded: false,
|
|
208
|
+
cachedFileCount: 0,
|
|
209
|
+
totalCachedEntries: 0,
|
|
210
|
+
lastCacheTime: null,
|
|
211
|
+
cacheAge: null,
|
|
212
|
+
isCurrentlyParsing: this.parsingPromises.size > 0,
|
|
213
|
+
fileCacheDetails: []
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
const totalCachedEntries = Array.from(this.cache.fileCache.values())
|
|
217
|
+
.reduce((sum, cache) => sum + cache.entries.length, 0);
|
|
218
|
+
const fileCacheDetails = Array.from(this.cache.fileCache.entries())
|
|
219
|
+
.map(([filePath, cache]) => ({
|
|
220
|
+
filePath,
|
|
221
|
+
entryCount: cache.entries.length,
|
|
222
|
+
mtime: new Date(cache.mtime).toISOString()
|
|
223
|
+
}));
|
|
224
|
+
return {
|
|
225
|
+
isLoaded: true,
|
|
226
|
+
cachedFileCount: this.cache.fileCache.size,
|
|
227
|
+
totalCachedEntries,
|
|
228
|
+
lastCacheTime: this.cache.lastCacheTime,
|
|
229
|
+
cacheAge: Date.now() - this.cache.lastCacheTime,
|
|
230
|
+
isCurrentlyParsing: this.parsingPromises.size > 0,
|
|
231
|
+
fileCacheDetails
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=conversation-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation-cache.js","sourceRoot":"","sources":["../../src/services/conversation-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import { ConversationSummary, ConversationMessage, ConversationDetailsResponse } from '../types/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Context data stored for active conversations that have not yet been written to local directories
|
|
5
|
+
*/
|
|
6
|
+
export interface ConversationStatusContext {
|
|
7
|
+
initialPrompt: string;
|
|
8
|
+
workingDirectory: string;
|
|
9
|
+
model: string;
|
|
10
|
+
timestamp: string;
|
|
11
|
+
inheritedMessages?: ConversationMessage[];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Unified service for managing conversation status and tracking active session status.
|
|
15
|
+
* This service combines the functionality of ConversationStatusTracker and optimistic conversation handling.
|
|
16
|
+
*
|
|
17
|
+
* Responsibilities:
|
|
18
|
+
* - Track active streaming sessions and their Claude session IDs
|
|
19
|
+
* - Store conversation status contexts for active sessions
|
|
20
|
+
* - Generate optimistic conversation summaries and details for UI feedback
|
|
21
|
+
* - Emit events for session lifecycle (started/ended)
|
|
22
|
+
*/
|
|
23
|
+
export declare class ConversationStatusManager extends EventEmitter {
|
|
24
|
+
private sessionToStreaming;
|
|
25
|
+
private streamingToSession;
|
|
26
|
+
private sessionContext;
|
|
27
|
+
private logger;
|
|
28
|
+
constructor();
|
|
29
|
+
/**
|
|
30
|
+
* Register a new active streaming session with optional conversation context
|
|
31
|
+
* This is called when we extract the session_id from the first stream message
|
|
32
|
+
*/
|
|
33
|
+
registerActiveSession(streamingId: string, claudeSessionId: string, conversationContext?: {
|
|
34
|
+
initialPrompt: string;
|
|
35
|
+
workingDirectory: string;
|
|
36
|
+
model?: string;
|
|
37
|
+
inheritedMessages?: ConversationMessage[];
|
|
38
|
+
}): void;
|
|
39
|
+
/**
|
|
40
|
+
* Unregister an active streaming session when it ends
|
|
41
|
+
*/
|
|
42
|
+
unregisterActiveSession(streamingId: string): void;
|
|
43
|
+
/**
|
|
44
|
+
* Get conversation context for an active session
|
|
45
|
+
*/
|
|
46
|
+
getConversationContext(claudeSessionId: string): ConversationStatusContext | undefined;
|
|
47
|
+
/**
|
|
48
|
+
* Check if a Claude session ID is currently active (has ongoing stream)
|
|
49
|
+
*/
|
|
50
|
+
isSessionActive(claudeSessionId: string): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Get the streaming ID for an active Claude session
|
|
53
|
+
*/
|
|
54
|
+
getStreamingId(claudeSessionId: string): string | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* Get the Claude session ID for an active streaming session
|
|
57
|
+
*/
|
|
58
|
+
getSessionId(streamingId: string): string | undefined;
|
|
59
|
+
/**
|
|
60
|
+
* Get all active Claude session IDs
|
|
61
|
+
*/
|
|
62
|
+
getActiveSessionIds(): string[];
|
|
63
|
+
/**
|
|
64
|
+
* Get all active streaming IDs
|
|
65
|
+
*/
|
|
66
|
+
getActiveStreamingIds(): string[];
|
|
67
|
+
/**
|
|
68
|
+
* Get conversation status for a Claude session ID
|
|
69
|
+
*/
|
|
70
|
+
getConversationStatus(claudeSessionId: string): 'completed' | 'ongoing' | 'pending';
|
|
71
|
+
/**
|
|
72
|
+
* Get conversations that haven't appeared in history yet
|
|
73
|
+
* Used by the conversation list endpoint
|
|
74
|
+
*/
|
|
75
|
+
getConversationsNotInHistory(existingSessionIds: Set<string>): ConversationSummary[];
|
|
76
|
+
/**
|
|
77
|
+
* Get conversation details if session is active but not in history
|
|
78
|
+
* Used by the conversation details endpoint
|
|
79
|
+
*/
|
|
80
|
+
getActiveConversationDetails(sessionId: string): ConversationDetailsResponse | null;
|
|
81
|
+
/**
|
|
82
|
+
* Clear all mappings (useful for testing)
|
|
83
|
+
*/
|
|
84
|
+
clear(): void;
|
|
85
|
+
/**
|
|
86
|
+
* Get statistics about tracked sessions
|
|
87
|
+
*/
|
|
88
|
+
getStats(): {
|
|
89
|
+
activeSessionsCount: number;
|
|
90
|
+
activeStreamingIdsCount: number;
|
|
91
|
+
activeContextsCount: number;
|
|
92
|
+
activeSessions: Array<{
|
|
93
|
+
claudeSessionId: string;
|
|
94
|
+
streamingId: string;
|
|
95
|
+
}>;
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=conversation-status-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation-status-manager.d.ts","sourceRoot":"","sources":["../../src/services/conversation-status-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,MAAM,kBAAkB,CAAC;AAEzG;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC3C;AAED;;;;;;;;;GASG;AACH,qBAAa,yBAA0B,SAAQ,YAAY;IAEzD,OAAO,CAAC,kBAAkB,CAAkC;IAE5D,OAAO,CAAC,kBAAkB,CAAkC;IAE5D,OAAO,CAAC,cAAc,CAAqD;IAC3E,OAAO,CAAC,MAAM,CAAS;;IAOvB;;;OAGG;IACH,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,mBAAmB,CAAC,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,iBAAiB,CAAC,EAAE,mBAAmB,EAAE,CAAA;KAAE,GAAG,IAAI;IAyD/M;;OAEG;IACH,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAuBlD;;OAEG;IACH,sBAAsB,CAAC,eAAe,EAAE,MAAM,GAAG,yBAAyB,GAAG,SAAS;IAStF;;OAEG;IACH,eAAe,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO;IAKjD;;OAEG;IACH,cAAc,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI3D;;OAEG;IACH,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IASrD;;OAEG;IACH,mBAAmB,IAAI,MAAM,EAAE;IAS/B;;OAEG;IACH,qBAAqB,IAAI,MAAM,EAAE;IASjC;;OAEG;IACH,qBAAqB,CAAC,eAAe,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS;IAMnF;;;OAGG;IACH,4BAA4B,CAAC,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,mBAAmB,EAAE;IA0DpF;;;OAGG;IACH,4BAA4B,CAAC,SAAS,EAAE,MAAM,GAAG,2BAA2B,GAAG,IAAI;IAyDnF;;OAEG;IACH,KAAK,IAAI,IAAI;IAOb;;OAEG;IACH,QAAQ,IAAI;QACV,mBAAmB,EAAE,MAAM,CAAC;QAC5B,uBAAuB,EAAE,MAAM,CAAC;QAChC,mBAAmB,EAAE,MAAM,CAAC;QAC5B,cAAc,EAAE,KAAK,CAAC;YAAE,eAAe,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACzE;CAYF"}
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import { createLogger } from './logger.js';
|
|
3
|
+
/**
|
|
4
|
+
* Unified service for managing conversation status and tracking active session status.
|
|
5
|
+
* This service combines the functionality of ConversationStatusTracker and optimistic conversation handling.
|
|
6
|
+
*
|
|
7
|
+
* Responsibilities:
|
|
8
|
+
* - Track active streaming sessions and their Claude session IDs
|
|
9
|
+
* - Store conversation status contexts for active sessions
|
|
10
|
+
* - Generate optimistic conversation summaries and details for UI feedback
|
|
11
|
+
* - Emit events for session lifecycle (started/ended)
|
|
12
|
+
*/
|
|
13
|
+
export class ConversationStatusManager extends EventEmitter {
|
|
14
|
+
// Maps Claude session ID -> CUI streaming ID
|
|
15
|
+
sessionToStreaming = new Map();
|
|
16
|
+
// Maps CUI streaming ID -> Claude session ID (reverse lookup)
|
|
17
|
+
streamingToSession = new Map();
|
|
18
|
+
// Maps Claude session ID -> conversation context for active sessions
|
|
19
|
+
sessionContext = new Map();
|
|
20
|
+
logger;
|
|
21
|
+
constructor() {
|
|
22
|
+
super();
|
|
23
|
+
this.logger = createLogger('ConversationStatusManager');
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Register a new active streaming session with optional conversation context
|
|
27
|
+
* This is called when we extract the session_id from the first stream message
|
|
28
|
+
*/
|
|
29
|
+
registerActiveSession(streamingId, claudeSessionId, conversationContext) {
|
|
30
|
+
// Remove any existing mapping for this Claude session
|
|
31
|
+
const existingStreamingId = this.sessionToStreaming.get(claudeSessionId);
|
|
32
|
+
if (existingStreamingId && existingStreamingId !== streamingId) {
|
|
33
|
+
this.logger.debug('Removing existing mapping for Claude session', {
|
|
34
|
+
claudeSessionId,
|
|
35
|
+
oldStreamingId: existingStreamingId,
|
|
36
|
+
newStreamingId: streamingId
|
|
37
|
+
});
|
|
38
|
+
this.streamingToSession.delete(existingStreamingId);
|
|
39
|
+
}
|
|
40
|
+
// Remove any existing mapping for this streaming ID
|
|
41
|
+
const existingClaudeSessionId = this.streamingToSession.get(streamingId);
|
|
42
|
+
if (existingClaudeSessionId && existingClaudeSessionId !== claudeSessionId) {
|
|
43
|
+
this.logger.debug('Removing existing mapping for streaming ID', {
|
|
44
|
+
streamingId,
|
|
45
|
+
oldClaudeSessionId: existingClaudeSessionId,
|
|
46
|
+
newClaudeSessionId: claudeSessionId
|
|
47
|
+
});
|
|
48
|
+
this.sessionToStreaming.delete(existingClaudeSessionId);
|
|
49
|
+
this.sessionContext.delete(existingClaudeSessionId);
|
|
50
|
+
}
|
|
51
|
+
// Set the new mapping
|
|
52
|
+
this.sessionToStreaming.set(claudeSessionId, streamingId);
|
|
53
|
+
this.streamingToSession.set(streamingId, claudeSessionId);
|
|
54
|
+
// If conversation context is provided, store it immediately
|
|
55
|
+
if (conversationContext) {
|
|
56
|
+
const context = {
|
|
57
|
+
initialPrompt: conversationContext.initialPrompt,
|
|
58
|
+
workingDirectory: conversationContext.workingDirectory,
|
|
59
|
+
model: conversationContext.model || 'default',
|
|
60
|
+
timestamp: new Date().toISOString(),
|
|
61
|
+
inheritedMessages: conversationContext.inheritedMessages
|
|
62
|
+
};
|
|
63
|
+
this.sessionContext.set(claudeSessionId, context);
|
|
64
|
+
this.logger.debug('Stored conversation status context', {
|
|
65
|
+
claudeSessionId,
|
|
66
|
+
hasInitialPrompt: !!context.initialPrompt,
|
|
67
|
+
workingDirectory: context.workingDirectory,
|
|
68
|
+
model: context.model,
|
|
69
|
+
inheritedMessageCount: context.inheritedMessages?.length || 0
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
this.logger.info('[SESSION-TRACK] Session registered', {
|
|
73
|
+
streamingId: streamingId.slice(0, 8),
|
|
74
|
+
sessionId: claudeSessionId.slice(0, 8),
|
|
75
|
+
totalActive: this.sessionToStreaming.size
|
|
76
|
+
});
|
|
77
|
+
this.emit('session-started', { streamingId, claudeSessionId });
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Unregister an active streaming session when it ends
|
|
81
|
+
*/
|
|
82
|
+
unregisterActiveSession(streamingId) {
|
|
83
|
+
const claudeSessionId = this.streamingToSession.get(streamingId);
|
|
84
|
+
if (claudeSessionId) {
|
|
85
|
+
this.sessionToStreaming.delete(claudeSessionId);
|
|
86
|
+
this.streamingToSession.delete(streamingId);
|
|
87
|
+
this.sessionContext.delete(claudeSessionId);
|
|
88
|
+
this.logger.info('[SESSION-TRACK] Session unregistered', {
|
|
89
|
+
streamingId: streamingId.slice(0, 8),
|
|
90
|
+
sessionId: claudeSessionId.slice(0, 8),
|
|
91
|
+
remainingActive: this.sessionToStreaming.size
|
|
92
|
+
});
|
|
93
|
+
this.emit('session-ended', { streamingId, claudeSessionId });
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
// This is normal during startup/restart - not worth logging at warn level
|
|
97
|
+
this.logger.debug('[SESSION-TRACK] Attempted to unregister unknown streamingId', {
|
|
98
|
+
streamingId: streamingId.slice(0, 8)
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Get conversation context for an active session
|
|
104
|
+
*/
|
|
105
|
+
getConversationContext(claudeSessionId) {
|
|
106
|
+
const context = this.sessionContext.get(claudeSessionId);
|
|
107
|
+
this.logger.debug('Getting conversation context', {
|
|
108
|
+
claudeSessionId,
|
|
109
|
+
hasContext: !!context
|
|
110
|
+
});
|
|
111
|
+
return context;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Check if a Claude session ID is currently active (has ongoing stream)
|
|
115
|
+
*/
|
|
116
|
+
isSessionActive(claudeSessionId) {
|
|
117
|
+
const isActive = this.sessionToStreaming.has(claudeSessionId);
|
|
118
|
+
return isActive;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Get the streaming ID for an active Claude session
|
|
122
|
+
*/
|
|
123
|
+
getStreamingId(claudeSessionId) {
|
|
124
|
+
return this.sessionToStreaming.get(claudeSessionId);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Get the Claude session ID for an active streaming session
|
|
128
|
+
*/
|
|
129
|
+
getSessionId(streamingId) {
|
|
130
|
+
const claudeSessionId = this.streamingToSession.get(streamingId);
|
|
131
|
+
this.logger.debug('Getting Claude session ID for streaming ID', {
|
|
132
|
+
streamingId,
|
|
133
|
+
claudeSessionId: claudeSessionId || 'not found'
|
|
134
|
+
});
|
|
135
|
+
return claudeSessionId;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Get all active Claude session IDs
|
|
139
|
+
*/
|
|
140
|
+
getActiveSessionIds() {
|
|
141
|
+
const sessions = Array.from(this.sessionToStreaming.keys());
|
|
142
|
+
this.logger.debug('Getting all active session IDs', {
|
|
143
|
+
count: sessions.length,
|
|
144
|
+
sessions
|
|
145
|
+
});
|
|
146
|
+
return sessions;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Get all active streaming IDs
|
|
150
|
+
*/
|
|
151
|
+
getActiveStreamingIds() {
|
|
152
|
+
const streamingIds = Array.from(this.streamingToSession.keys());
|
|
153
|
+
this.logger.debug('Getting all active streaming IDs', {
|
|
154
|
+
count: streamingIds.length,
|
|
155
|
+
streamingIds
|
|
156
|
+
});
|
|
157
|
+
return streamingIds;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Get conversation status for a Claude session ID
|
|
161
|
+
*/
|
|
162
|
+
getConversationStatus(claudeSessionId) {
|
|
163
|
+
const isActive = this.isSessionActive(claudeSessionId);
|
|
164
|
+
const status = isActive ? 'ongoing' : 'completed';
|
|
165
|
+
return status;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Get conversations that haven't appeared in history yet
|
|
169
|
+
* Used by the conversation list endpoint
|
|
170
|
+
*/
|
|
171
|
+
getConversationsNotInHistory(existingSessionIds) {
|
|
172
|
+
const activeSessionIds = this.getActiveSessionIds();
|
|
173
|
+
const conversationsNotInHistory = activeSessionIds
|
|
174
|
+
.filter(sessionId => !existingSessionIds.has(sessionId))
|
|
175
|
+
.map(sessionId => {
|
|
176
|
+
const context = this.getConversationContext(sessionId);
|
|
177
|
+
const streamingId = this.getStreamingId(sessionId);
|
|
178
|
+
if (context && streamingId) {
|
|
179
|
+
// Create conversation entry for active session
|
|
180
|
+
const conversationSummary = {
|
|
181
|
+
sessionId,
|
|
182
|
+
projectPath: context.workingDirectory,
|
|
183
|
+
summary: '', // No summary for active conversation
|
|
184
|
+
sessionInfo: {
|
|
185
|
+
custom_name: '', // No custom name yet
|
|
186
|
+
created_at: context.timestamp,
|
|
187
|
+
updated_at: context.timestamp,
|
|
188
|
+
version: 4,
|
|
189
|
+
pinned: false,
|
|
190
|
+
archived: false,
|
|
191
|
+
continuation_session_id: '',
|
|
192
|
+
initial_commit_head: '',
|
|
193
|
+
permission_mode: 'default'
|
|
194
|
+
},
|
|
195
|
+
createdAt: context.timestamp,
|
|
196
|
+
updatedAt: context.timestamp,
|
|
197
|
+
messageCount: 1, // At least the initial user message
|
|
198
|
+
totalDuration: 0, // No duration yet
|
|
199
|
+
model: context.model || 'unknown',
|
|
200
|
+
status: 'ongoing',
|
|
201
|
+
streamingId
|
|
202
|
+
};
|
|
203
|
+
this.logger.debug('Created conversation summary for active session', {
|
|
204
|
+
sessionId,
|
|
205
|
+
streamingId,
|
|
206
|
+
workingDirectory: context.workingDirectory,
|
|
207
|
+
model: context.model
|
|
208
|
+
});
|
|
209
|
+
return conversationSummary;
|
|
210
|
+
}
|
|
211
|
+
return null;
|
|
212
|
+
})
|
|
213
|
+
.filter((conversation) => conversation !== null);
|
|
214
|
+
this.logger.debug('Generated conversations not in history', {
|
|
215
|
+
activeSessionCount: activeSessionIds.length,
|
|
216
|
+
existingSessionCount: existingSessionIds.size,
|
|
217
|
+
conversationsNotInHistoryCount: conversationsNotInHistory.length
|
|
218
|
+
});
|
|
219
|
+
return conversationsNotInHistory;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Get conversation details if session is active but not in history
|
|
223
|
+
* Used by the conversation details endpoint
|
|
224
|
+
*/
|
|
225
|
+
getActiveConversationDetails(sessionId) {
|
|
226
|
+
const isActive = this.isSessionActive(sessionId);
|
|
227
|
+
const context = this.getConversationContext(sessionId);
|
|
228
|
+
this.logger.debug('Checking for active conversation details', {
|
|
229
|
+
sessionId,
|
|
230
|
+
isActive,
|
|
231
|
+
hasContext: !!context
|
|
232
|
+
});
|
|
233
|
+
if (!isActive || !context) {
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
// Create messages array
|
|
237
|
+
const messages = [];
|
|
238
|
+
// Add inherited messages first (if any)
|
|
239
|
+
if (context.inheritedMessages) {
|
|
240
|
+
messages.push(...context.inheritedMessages);
|
|
241
|
+
}
|
|
242
|
+
// Add the current initial prompt message
|
|
243
|
+
const activeMessage = {
|
|
244
|
+
uuid: `active-${sessionId}-user`,
|
|
245
|
+
type: 'user',
|
|
246
|
+
message: {
|
|
247
|
+
role: 'user',
|
|
248
|
+
content: context.initialPrompt
|
|
249
|
+
},
|
|
250
|
+
timestamp: context.timestamp,
|
|
251
|
+
sessionId: sessionId,
|
|
252
|
+
cwd: context.workingDirectory
|
|
253
|
+
};
|
|
254
|
+
messages.push(activeMessage);
|
|
255
|
+
const response = {
|
|
256
|
+
messages,
|
|
257
|
+
summary: '', // No summary for active conversation
|
|
258
|
+
projectPath: context.workingDirectory,
|
|
259
|
+
metadata: {
|
|
260
|
+
totalDuration: 0,
|
|
261
|
+
model: context.model || 'unknown'
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
this.logger.debug('Created active conversation details', {
|
|
265
|
+
sessionId,
|
|
266
|
+
workingDirectory: context.workingDirectory,
|
|
267
|
+
model: context.model,
|
|
268
|
+
totalMessageCount: messages.length,
|
|
269
|
+
inheritedMessageCount: context.inheritedMessages?.length || 0
|
|
270
|
+
});
|
|
271
|
+
return response;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Clear all mappings (useful for testing)
|
|
275
|
+
*/
|
|
276
|
+
clear() {
|
|
277
|
+
this.logger.debug('Clearing all session mappings');
|
|
278
|
+
this.sessionToStreaming.clear();
|
|
279
|
+
this.streamingToSession.clear();
|
|
280
|
+
this.sessionContext.clear();
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Get statistics about tracked sessions
|
|
284
|
+
*/
|
|
285
|
+
getStats() {
|
|
286
|
+
const activeSessions = Array.from(this.sessionToStreaming.entries()).map(([claudeSessionId, streamingId]) => ({ claudeSessionId, streamingId }));
|
|
287
|
+
return {
|
|
288
|
+
activeSessionsCount: this.sessionToStreaming.size,
|
|
289
|
+
activeStreamingIdsCount: this.streamingToSession.size,
|
|
290
|
+
activeContextsCount: this.sessionContext.size,
|
|
291
|
+
activeSessions
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
//# sourceMappingURL=conversation-status-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation-status-manager.js","sourceRoot":"","sources":["../../src/services/conversation-status-manager.ts"],"names":[],"mappings":"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"}
|