@wundr.io/cli 1.0.10 → 1.0.12
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/bin/wundr.js +8 -4
- package/package.json +23 -23
- package/src/ai/ai-service.ts +16 -17
- package/src/ai/claude-client.ts +16 -16
- package/src/ai/conversation-manager.ts +29 -29
- package/src/cli.ts +4 -4
- package/src/commands/ai.ts +246 -78
- package/src/commands/alignment.ts +74 -74
- package/src/commands/analyze-optimized.ts +111 -78
- package/src/commands/analyze.ts +14 -14
- package/src/commands/batch.ts +179 -42
- package/src/commands/chat.ts +37 -30
- package/src/commands/claude-init.ts +41 -45
- package/src/commands/claude-setup.ts +204 -119
- package/src/commands/computer-setup.ts +85 -43
- package/src/commands/create-command.ts +4 -4
- package/src/commands/create.ts +27 -27
- package/src/commands/dashboard.ts +24 -24
- package/src/commands/govern.ts +25 -25
- package/src/commands/governance.ts +34 -34
- package/src/commands/guardian.ts +56 -56
- package/src/commands/init.ts +25 -22
- package/src/commands/orchestrator.ts +68 -41
- package/src/commands/performance-optimizer.ts +34 -35
- package/src/commands/plugins.ts +27 -27
- package/src/commands/project-update.ts +175 -72
- package/src/commands/rag.ts +185 -78
- package/src/commands/session.ts +35 -35
- package/src/commands/setup.ts +40 -344
- package/src/commands/test-init.ts +3 -3
- package/src/commands/test.ts +4 -4
- package/src/commands/watch.ts +28 -29
- package/src/commands/worktree.ts +49 -49
- package/src/context/context-manager.ts +10 -10
- package/src/context/session-manager.ts +41 -41
- package/src/framework/command-interface.ts +520 -0
- package/src/framework/command-registry.ts +942 -0
- package/src/framework/completion-exporter.ts +383 -0
- package/src/framework/debug-logger.ts +519 -0
- package/src/framework/error-handler.ts +867 -0
- package/src/framework/help-generator.ts +540 -0
- package/src/framework/index.ts +169 -0
- package/src/framework/interactive-repl.ts +703 -0
- package/src/framework/output-formatter.ts +834 -0
- package/src/framework/progress-manager.ts +539 -0
- package/src/index.ts +4 -4
- package/src/interactive/interactive-mode.ts +16 -16
- package/src/lib/conflict-resolution.ts +799 -9
- package/src/lib/merge-strategy.ts +529 -7
- package/src/lib/safety-mechanisms.ts +422 -18
- package/src/lib/state-detection.ts +1015 -13
- package/src/nlp/command-mapper.ts +29 -29
- package/src/nlp/command-parser.ts +17 -17
- package/src/nlp/intent-classifier.ts +7 -7
- package/src/nlp/intent-parser.ts +54 -52
- package/src/plugins/plugin-manager.ts +61 -39
- package/src/tests/computer-setup-integration.test.ts +46 -15
- package/src/types/modules.d.ts +424 -1
- package/src/utils/backup-rollback-manager.ts +11 -8
- package/src/utils/config-manager.ts +3 -3
- package/src/utils/error-handler.ts +2 -2
- package/src/utils/logger.ts +22 -22
- package/templates/batch/ci-cd.yaml +7 -7
- package/test-suites/api/health.spec.ts +20 -23
- package/test-suites/helpers/test-config.ts +14 -13
- package/test-suites/ui/accessibility.spec.ts +27 -22
- package/test-suites/ui/smoke.spec.ts +26 -21
- package/LICENSE +0 -21
- package/dist/ai/ai-service.d.ts +0 -152
- package/dist/ai/ai-service.d.ts.map +0 -1
- package/dist/ai/ai-service.js +0 -430
- package/dist/ai/ai-service.js.map +0 -1
- package/dist/ai/claude-client.d.ts +0 -130
- package/dist/ai/claude-client.d.ts.map +0 -1
- package/dist/ai/claude-client.js +0 -340
- package/dist/ai/claude-client.js.map +0 -1
- package/dist/ai/conversation-manager.d.ts +0 -164
- package/dist/ai/conversation-manager.d.ts.map +0 -1
- package/dist/ai/conversation-manager.js +0 -614
- package/dist/ai/conversation-manager.js.map +0 -1
- package/dist/ai/index.d.ts +0 -5
- package/dist/ai/index.d.ts.map +0 -1
- package/dist/ai/index.js +0 -8
- package/dist/ai/index.js.map +0 -1
- package/dist/cli.d.ts +0 -36
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -192
- package/dist/cli.js.map +0 -1
- package/dist/commands/ai.d.ts +0 -89
- package/dist/commands/ai.d.ts.map +0 -1
- package/dist/commands/ai.js +0 -799
- package/dist/commands/ai.js.map +0 -1
- package/dist/commands/alignment.d.ts +0 -78
- package/dist/commands/alignment.d.ts.map +0 -1
- package/dist/commands/alignment.js +0 -817
- package/dist/commands/alignment.js.map +0 -1
- package/dist/commands/analyze-optimized.d.ts +0 -14
- package/dist/commands/analyze-optimized.d.ts.map +0 -1
- package/dist/commands/analyze-optimized.js +0 -600
- package/dist/commands/analyze-optimized.js.map +0 -1
- package/dist/commands/analyze.d.ts +0 -65
- package/dist/commands/analyze.d.ts.map +0 -1
- package/dist/commands/analyze.js +0 -435
- package/dist/commands/analyze.js.map +0 -1
- package/dist/commands/batch.d.ts +0 -71
- package/dist/commands/batch.d.ts.map +0 -1
- package/dist/commands/batch.js +0 -738
- package/dist/commands/batch.js.map +0 -1
- package/dist/commands/chat.d.ts +0 -71
- package/dist/commands/chat.d.ts.map +0 -1
- package/dist/commands/chat.js +0 -674
- package/dist/commands/chat.js.map +0 -1
- package/dist/commands/claude-init.d.ts +0 -28
- package/dist/commands/claude-init.d.ts.map +0 -1
- package/dist/commands/claude-init.js +0 -591
- package/dist/commands/claude-init.js.map +0 -1
- package/dist/commands/claude-setup.d.ts +0 -119
- package/dist/commands/claude-setup.d.ts.map +0 -1
- package/dist/commands/claude-setup.js +0 -1073
- package/dist/commands/claude-setup.js.map +0 -1
- package/dist/commands/computer-setup-commands.d.ts +0 -53
- package/dist/commands/computer-setup-commands.d.ts.map +0 -1
- package/dist/commands/computer-setup-commands.js +0 -705
- package/dist/commands/computer-setup-commands.js.map +0 -1
- package/dist/commands/computer-setup.d.ts +0 -7
- package/dist/commands/computer-setup.d.ts.map +0 -1
- package/dist/commands/computer-setup.js +0 -849
- package/dist/commands/computer-setup.js.map +0 -1
- package/dist/commands/create-command.d.ts +0 -7
- package/dist/commands/create-command.d.ts.map +0 -1
- package/dist/commands/create-command.js +0 -158
- package/dist/commands/create-command.js.map +0 -1
- package/dist/commands/create.d.ts +0 -74
- package/dist/commands/create.d.ts.map +0 -1
- package/dist/commands/create.js +0 -556
- package/dist/commands/create.js.map +0 -1
- package/dist/commands/dashboard.d.ts +0 -91
- package/dist/commands/dashboard.d.ts.map +0 -1
- package/dist/commands/dashboard.js +0 -538
- package/dist/commands/dashboard.js.map +0 -1
- package/dist/commands/govern.d.ts +0 -70
- package/dist/commands/govern.d.ts.map +0 -1
- package/dist/commands/govern.js +0 -481
- package/dist/commands/govern.js.map +0 -1
- package/dist/commands/governance.d.ts +0 -17
- package/dist/commands/governance.d.ts.map +0 -1
- package/dist/commands/governance.js +0 -703
- package/dist/commands/governance.js.map +0 -1
- package/dist/commands/guardian.d.ts +0 -20
- package/dist/commands/guardian.d.ts.map +0 -1
- package/dist/commands/guardian.js +0 -597
- package/dist/commands/guardian.js.map +0 -1
- package/dist/commands/init.d.ts +0 -59
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/init.js +0 -650
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/orchestrator.d.ts +0 -7
- package/dist/commands/orchestrator.d.ts.map +0 -1
- package/dist/commands/orchestrator.js +0 -571
- package/dist/commands/orchestrator.js.map +0 -1
- package/dist/commands/performance-optimizer.d.ts +0 -30
- package/dist/commands/performance-optimizer.d.ts.map +0 -1
- package/dist/commands/performance-optimizer.js +0 -650
- package/dist/commands/performance-optimizer.js.map +0 -1
- package/dist/commands/plugins.d.ts +0 -87
- package/dist/commands/plugins.d.ts.map +0 -1
- package/dist/commands/plugins.js +0 -685
- package/dist/commands/plugins.js.map +0 -1
- package/dist/commands/rag.d.ts +0 -7
- package/dist/commands/rag.d.ts.map +0 -1
- package/dist/commands/rag.js +0 -748
- package/dist/commands/rag.js.map +0 -1
- package/dist/commands/session.d.ts +0 -41
- package/dist/commands/session.d.ts.map +0 -1
- package/dist/commands/session.js +0 -441
- package/dist/commands/session.js.map +0 -1
- package/dist/commands/setup.d.ts +0 -29
- package/dist/commands/setup.d.ts.map +0 -1
- package/dist/commands/setup.js +0 -397
- package/dist/commands/setup.js.map +0 -1
- package/dist/commands/test-init.d.ts +0 -9
- package/dist/commands/test-init.d.ts.map +0 -1
- package/dist/commands/test-init.js +0 -222
- package/dist/commands/test-init.js.map +0 -1
- package/dist/commands/test.d.ts +0 -25
- package/dist/commands/test.d.ts.map +0 -1
- package/dist/commands/test.js +0 -217
- package/dist/commands/test.js.map +0 -1
- package/dist/commands/vp.d.ts +0 -7
- package/dist/commands/vp.d.ts.map +0 -1
- package/dist/commands/vp.js +0 -571
- package/dist/commands/vp.js.map +0 -1
- package/dist/commands/watch.d.ts +0 -76
- package/dist/commands/watch.d.ts.map +0 -1
- package/dist/commands/watch.js +0 -613
- package/dist/commands/watch.js.map +0 -1
- package/dist/commands/worktree.d.ts +0 -63
- package/dist/commands/worktree.d.ts.map +0 -1
- package/dist/commands/worktree.js +0 -774
- package/dist/commands/worktree.js.map +0 -1
- package/dist/context/context-manager.d.ts +0 -155
- package/dist/context/context-manager.d.ts.map +0 -1
- package/dist/context/context-manager.js +0 -383
- package/dist/context/context-manager.js.map +0 -1
- package/dist/context/index.d.ts +0 -3
- package/dist/context/index.d.ts.map +0 -1
- package/dist/context/index.js +0 -6
- package/dist/context/index.js.map +0 -1
- package/dist/context/session-manager.d.ts +0 -207
- package/dist/context/session-manager.d.ts.map +0 -1
- package/dist/context/session-manager.js +0 -686
- package/dist/context/session-manager.js.map +0 -1
- package/dist/index.d.ts +0 -8
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -51
- package/dist/index.js.map +0 -1
- package/dist/interactive/interactive-mode.d.ts +0 -76
- package/dist/interactive/interactive-mode.d.ts.map +0 -1
- package/dist/interactive/interactive-mode.js +0 -732
- package/dist/interactive/interactive-mode.js.map +0 -1
- package/dist/nlp/command-mapper.d.ts +0 -174
- package/dist/nlp/command-mapper.d.ts.map +0 -1
- package/dist/nlp/command-mapper.js +0 -624
- package/dist/nlp/command-mapper.js.map +0 -1
- package/dist/nlp/command-parser.d.ts +0 -106
- package/dist/nlp/command-parser.d.ts.map +0 -1
- package/dist/nlp/command-parser.js +0 -417
- package/dist/nlp/command-parser.js.map +0 -1
- package/dist/nlp/index.d.ts +0 -5
- package/dist/nlp/index.d.ts.map +0 -1
- package/dist/nlp/index.js +0 -8
- package/dist/nlp/index.js.map +0 -1
- package/dist/nlp/intent-classifier.d.ts +0 -59
- package/dist/nlp/intent-classifier.d.ts.map +0 -1
- package/dist/nlp/intent-classifier.js +0 -384
- package/dist/nlp/intent-classifier.js.map +0 -1
- package/dist/nlp/intent-parser.d.ts +0 -152
- package/dist/nlp/intent-parser.d.ts.map +0 -1
- package/dist/nlp/intent-parser.js +0 -744
- package/dist/nlp/intent-parser.js.map +0 -1
- package/dist/plugins/plugin-manager.d.ts +0 -120
- package/dist/plugins/plugin-manager.d.ts.map +0 -1
- package/dist/plugins/plugin-manager.js +0 -595
- package/dist/plugins/plugin-manager.js.map +0 -1
- package/dist/types/index.d.ts +0 -224
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -3
- package/dist/types/index.js.map +0 -1
- package/dist/utils/backup-rollback-manager.d.ts +0 -72
- package/dist/utils/backup-rollback-manager.d.ts.map +0 -1
- package/dist/utils/backup-rollback-manager.js +0 -289
- package/dist/utils/backup-rollback-manager.js.map +0 -1
- package/dist/utils/claude-config-installer.d.ts +0 -98
- package/dist/utils/claude-config-installer.d.ts.map +0 -1
- package/dist/utils/claude-config-installer.js +0 -678
- package/dist/utils/claude-config-installer.js.map +0 -1
- package/dist/utils/config-manager.d.ts +0 -73
- package/dist/utils/config-manager.d.ts.map +0 -1
- package/dist/utils/config-manager.js +0 -339
- package/dist/utils/config-manager.js.map +0 -1
- package/dist/utils/error-handler.d.ts +0 -46
- package/dist/utils/error-handler.d.ts.map +0 -1
- package/dist/utils/error-handler.js +0 -169
- package/dist/utils/error-handler.js.map +0 -1
- package/dist/utils/logger.d.ts +0 -25
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js +0 -105
- package/dist/utils/logger.js.map +0 -1
- package/src/commands/computer-setup-commands.ts +0 -872
|
@@ -1,686 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SessionManager = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
const events_1 = require("events");
|
|
6
|
-
const path_1 = tslib_1.__importDefault(require("path"));
|
|
7
|
-
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
8
|
-
const logger_1 = require("../utils/logger");
|
|
9
|
-
/**
|
|
10
|
-
* Session manager for persistent context, user preferences, and workspace management
|
|
11
|
-
*/
|
|
12
|
-
class SessionManager extends events_1.EventEmitter {
|
|
13
|
-
config;
|
|
14
|
-
conversationManager;
|
|
15
|
-
commandMapper;
|
|
16
|
-
activeSessions;
|
|
17
|
-
workspaces;
|
|
18
|
-
currentSessionId;
|
|
19
|
-
backupTimer;
|
|
20
|
-
cleanupTimer;
|
|
21
|
-
constructor(conversationManager, commandMapper, config = {}) {
|
|
22
|
-
super();
|
|
23
|
-
this.conversationManager = conversationManager;
|
|
24
|
-
this.commandMapper = commandMapper;
|
|
25
|
-
this.config = {
|
|
26
|
-
persistencePath: path_1.default.join(process.cwd(), '.wundr', 'sessions'),
|
|
27
|
-
sessionTimeout: 24 * 60, // 24 hours
|
|
28
|
-
maxSessions: 10,
|
|
29
|
-
autoDetectProjects: true,
|
|
30
|
-
enableContextLearning: true,
|
|
31
|
-
backupInterval: 15, // 15 minutes
|
|
32
|
-
...config,
|
|
33
|
-
};
|
|
34
|
-
this.activeSessions = new Map();
|
|
35
|
-
this.workspaces = new Map();
|
|
36
|
-
this.initialize();
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Create or resume a session
|
|
40
|
-
*/
|
|
41
|
-
async createSession(userId, workspacePath, sessionId) {
|
|
42
|
-
const id = sessionId ||
|
|
43
|
-
`session_${userId}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
44
|
-
// Check if session already exists
|
|
45
|
-
if (this.activeSessions.has(id)) {
|
|
46
|
-
await this.resumeSession(id);
|
|
47
|
-
return id;
|
|
48
|
-
}
|
|
49
|
-
const workspace = workspacePath || process.cwd();
|
|
50
|
-
const projectContext = await this.detectProjectContext(workspace);
|
|
51
|
-
const session = {
|
|
52
|
-
id,
|
|
53
|
-
userId,
|
|
54
|
-
currentWorkspace: workspace,
|
|
55
|
-
recentCommands: [],
|
|
56
|
-
contextStack: [],
|
|
57
|
-
userPreferences: await this.loadUserPreferences(userId),
|
|
58
|
-
projectContext,
|
|
59
|
-
temporaryData: {},
|
|
60
|
-
created: new Date(),
|
|
61
|
-
lastAccessed: new Date(),
|
|
62
|
-
};
|
|
63
|
-
// Load workspace if it exists
|
|
64
|
-
const workspaceConfig = await this.loadWorkspace(workspace);
|
|
65
|
-
if (workspaceConfig) {
|
|
66
|
-
workspaceConfig.lastAccessed = new Date();
|
|
67
|
-
this.workspaces.set(workspace, workspaceConfig);
|
|
68
|
-
}
|
|
69
|
-
this.activeSessions.set(id, session);
|
|
70
|
-
this.currentSessionId = id;
|
|
71
|
-
await this.persistSession(session);
|
|
72
|
-
this.emit('session_created', { sessionId: id, userId, workspace });
|
|
73
|
-
logger_1.logger.debug(`Created session: ${id} for user: ${userId}`);
|
|
74
|
-
return id;
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Resume an existing session
|
|
78
|
-
*/
|
|
79
|
-
async resumeSession(sessionId) {
|
|
80
|
-
let session = this.activeSessions.get(sessionId);
|
|
81
|
-
if (!session) {
|
|
82
|
-
// Try to load from persistence
|
|
83
|
-
session = (await this.loadSession(sessionId)) || undefined;
|
|
84
|
-
if (!session) {
|
|
85
|
-
throw new Error(`Session not found: ${sessionId}`);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
session.lastAccessed = new Date();
|
|
89
|
-
this.currentSessionId = sessionId;
|
|
90
|
-
this.activeSessions.set(sessionId, session);
|
|
91
|
-
// Refresh project context
|
|
92
|
-
if (session.projectContext) {
|
|
93
|
-
session.projectContext = await this.detectProjectContext(session.currentWorkspace);
|
|
94
|
-
}
|
|
95
|
-
await this.persistSession(session);
|
|
96
|
-
this.emit('session_resumed', { sessionId, session });
|
|
97
|
-
logger_1.logger.debug(`Resumed session: ${sessionId}`);
|
|
98
|
-
return session;
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Get current session
|
|
102
|
-
*/
|
|
103
|
-
getCurrentSession() {
|
|
104
|
-
if (!this.currentSessionId) {
|
|
105
|
-
return null;
|
|
106
|
-
}
|
|
107
|
-
return this.activeSessions.get(this.currentSessionId) || null;
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Get session by ID
|
|
111
|
-
*/
|
|
112
|
-
getSession(sessionId) {
|
|
113
|
-
return this.activeSessions.get(sessionId) || null;
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Update session context
|
|
117
|
-
*/
|
|
118
|
-
async updateSessionContext(sessionId, contextType, contextData) {
|
|
119
|
-
const session = this.activeSessions.get(sessionId);
|
|
120
|
-
if (!session) {
|
|
121
|
-
throw new Error(`Session not found: ${sessionId}`);
|
|
122
|
-
}
|
|
123
|
-
// Add to context stack
|
|
124
|
-
session.contextStack.push({
|
|
125
|
-
type: contextType,
|
|
126
|
-
context: contextData,
|
|
127
|
-
timestamp: new Date(),
|
|
128
|
-
});
|
|
129
|
-
// Limit context stack size
|
|
130
|
-
if (session.contextStack.length > 50) {
|
|
131
|
-
session.contextStack = session.contextStack.slice(-25);
|
|
132
|
-
}
|
|
133
|
-
// Update specific context based on type
|
|
134
|
-
switch (contextType) {
|
|
135
|
-
case 'project':
|
|
136
|
-
session.projectContext = { ...session.projectContext, ...contextData };
|
|
137
|
-
break;
|
|
138
|
-
case 'conversation':
|
|
139
|
-
session.activeConversation = contextData.conversationId;
|
|
140
|
-
break;
|
|
141
|
-
}
|
|
142
|
-
session.lastAccessed = new Date();
|
|
143
|
-
await this.persistSession(session);
|
|
144
|
-
this.emit('context_updated', { sessionId, contextType, contextData });
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Add command to session history
|
|
148
|
-
*/
|
|
149
|
-
async addCommandToHistory(sessionId, command, success, duration) {
|
|
150
|
-
const session = this.activeSessions.get(sessionId);
|
|
151
|
-
if (!session) {
|
|
152
|
-
throw new Error(`Session not found: ${sessionId}`);
|
|
153
|
-
}
|
|
154
|
-
session.recentCommands.push({
|
|
155
|
-
command,
|
|
156
|
-
timestamp: new Date(),
|
|
157
|
-
success,
|
|
158
|
-
duration,
|
|
159
|
-
});
|
|
160
|
-
// Limit history size
|
|
161
|
-
const maxHistory = session.userPreferences.maxHistoryLength || 100;
|
|
162
|
-
if (session.recentCommands.length > maxHistory) {
|
|
163
|
-
session.recentCommands = session.recentCommands.slice(-maxHistory / 2);
|
|
164
|
-
}
|
|
165
|
-
session.lastAccessed = new Date();
|
|
166
|
-
await this.persistSession(session);
|
|
167
|
-
// Learn from command patterns if enabled
|
|
168
|
-
if (this.config.enableContextLearning) {
|
|
169
|
-
await this.analyzeCommandPatterns(session);
|
|
170
|
-
}
|
|
171
|
-
this.emit('command_recorded', { sessionId, command, success, duration });
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Update user preferences
|
|
175
|
-
*/
|
|
176
|
-
async updateUserPreferences(userId, preferences) {
|
|
177
|
-
const defaultPreferences = this.getDefaultPreferences();
|
|
178
|
-
const currentPreferences = await this.loadUserPreferences(userId);
|
|
179
|
-
const updatedPreferences = { ...currentPreferences, ...preferences };
|
|
180
|
-
await this.saveUserPreferences(userId, updatedPreferences);
|
|
181
|
-
// Update all active sessions for this user
|
|
182
|
-
for (const [sessionId, session] of this.activeSessions) {
|
|
183
|
-
if (session.userId === userId) {
|
|
184
|
-
session.userPreferences = updatedPreferences;
|
|
185
|
-
await this.persistSession(session);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
this.emit('preferences_updated', {
|
|
189
|
-
userId,
|
|
190
|
-
preferences: updatedPreferences,
|
|
191
|
-
});
|
|
192
|
-
logger_1.logger.debug(`Updated preferences for user: ${userId}`);
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* Register a workspace
|
|
196
|
-
*/
|
|
197
|
-
async registerWorkspace(workspacePath, config) {
|
|
198
|
-
const workspace = {
|
|
199
|
-
name: config.name || path_1.default.basename(workspacePath),
|
|
200
|
-
path: workspacePath,
|
|
201
|
-
type: config.type || 'unknown',
|
|
202
|
-
settings: config.settings || {},
|
|
203
|
-
lastAccessed: new Date(),
|
|
204
|
-
bookmarked: config.bookmarked || false,
|
|
205
|
-
};
|
|
206
|
-
this.workspaces.set(workspacePath, workspace);
|
|
207
|
-
await this.saveWorkspace(workspace);
|
|
208
|
-
this.emit('workspace_registered', { workspace });
|
|
209
|
-
logger_1.logger.debug(`Registered workspace: ${workspacePath}`);
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* Get workspace suggestions based on recent activity
|
|
213
|
-
*/
|
|
214
|
-
getWorkspaceSuggestions(limit = 5) {
|
|
215
|
-
const workspaces = Array.from(this.workspaces.values()).sort((a, b) => b.lastAccessed.getTime() - a.lastAccessed.getTime());
|
|
216
|
-
return workspaces.slice(0, limit);
|
|
217
|
-
}
|
|
218
|
-
/**
|
|
219
|
-
* Search session history
|
|
220
|
-
*/
|
|
221
|
-
searchHistory(sessionId, query) {
|
|
222
|
-
const session = this.activeSessions.get(sessionId);
|
|
223
|
-
if (!session) {
|
|
224
|
-
return [];
|
|
225
|
-
}
|
|
226
|
-
let history = session.recentCommands;
|
|
227
|
-
if (query.command) {
|
|
228
|
-
const searchTerm = query.command.toLowerCase();
|
|
229
|
-
history = history.filter(cmd => cmd.command.toLowerCase().includes(searchTerm));
|
|
230
|
-
}
|
|
231
|
-
if (query.timeRange) {
|
|
232
|
-
history = history.filter(cmd => cmd.timestamp >= query.timeRange.from &&
|
|
233
|
-
cmd.timestamp <= query.timeRange.to);
|
|
234
|
-
}
|
|
235
|
-
if (query.successOnly) {
|
|
236
|
-
history = history.filter(cmd => cmd.success);
|
|
237
|
-
}
|
|
238
|
-
if (query.limit) {
|
|
239
|
-
history = history.slice(-query.limit);
|
|
240
|
-
}
|
|
241
|
-
return history;
|
|
242
|
-
}
|
|
243
|
-
/**
|
|
244
|
-
* Get contextual suggestions based on current session
|
|
245
|
-
*/
|
|
246
|
-
async getContextualSuggestions(sessionId, limit = 5) {
|
|
247
|
-
const session = this.activeSessions.get(sessionId);
|
|
248
|
-
if (!session) {
|
|
249
|
-
return [];
|
|
250
|
-
}
|
|
251
|
-
const suggestions = [];
|
|
252
|
-
// Command suggestions based on recent history
|
|
253
|
-
const recentCommands = session.recentCommands
|
|
254
|
-
.filter(cmd => cmd.success)
|
|
255
|
-
.slice(-10);
|
|
256
|
-
const commandFrequency = new Map();
|
|
257
|
-
for (const cmd of recentCommands) {
|
|
258
|
-
const baseCommand = cmd.command.split(' ')[0];
|
|
259
|
-
if (baseCommand) {
|
|
260
|
-
commandFrequency.set(baseCommand, (commandFrequency.get(baseCommand) || 0) + 1);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
for (const [command, frequency] of commandFrequency) {
|
|
264
|
-
suggestions.push({
|
|
265
|
-
type: 'command',
|
|
266
|
-
suggestion: command,
|
|
267
|
-
description: `Recently used command (${frequency} times)`,
|
|
268
|
-
confidence: Math.min(0.9, frequency * 0.2),
|
|
269
|
-
});
|
|
270
|
-
}
|
|
271
|
-
// Workspace suggestions
|
|
272
|
-
const workspaceSuggestions = this.getWorkspaceSuggestions(3);
|
|
273
|
-
for (const workspace of workspaceSuggestions) {
|
|
274
|
-
if (workspace.path !== session.currentWorkspace) {
|
|
275
|
-
suggestions.push({
|
|
276
|
-
type: 'workspace',
|
|
277
|
-
suggestion: workspace.path,
|
|
278
|
-
description: `Switch to ${workspace.name}`,
|
|
279
|
-
confidence: 0.6,
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
// Sort by confidence and limit
|
|
284
|
-
suggestions.sort((a, b) => b.confidence - a.confidence);
|
|
285
|
-
return suggestions.slice(0, limit);
|
|
286
|
-
}
|
|
287
|
-
/**
|
|
288
|
-
* Export session data
|
|
289
|
-
*/
|
|
290
|
-
async exportSession(sessionId, format) {
|
|
291
|
-
const session = this.activeSessions.get(sessionId);
|
|
292
|
-
if (!session) {
|
|
293
|
-
throw new Error(`Session not found: ${sessionId}`);
|
|
294
|
-
}
|
|
295
|
-
switch (format) {
|
|
296
|
-
case 'json':
|
|
297
|
-
return JSON.stringify(session, null, 2);
|
|
298
|
-
case 'csv':
|
|
299
|
-
return this.sessionToCsv(session);
|
|
300
|
-
default:
|
|
301
|
-
throw new Error(`Unsupported export format: ${format}`);
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
/**
|
|
305
|
-
* Clean up expired sessions
|
|
306
|
-
*/
|
|
307
|
-
async cleanupSessions() {
|
|
308
|
-
const now = new Date();
|
|
309
|
-
const timeoutMs = this.config.sessionTimeout * 60 * 1000;
|
|
310
|
-
const expiredSessions = [];
|
|
311
|
-
for (const [sessionId, session] of this.activeSessions) {
|
|
312
|
-
const timeSinceAccess = now.getTime() - session.lastAccessed.getTime();
|
|
313
|
-
if (timeSinceAccess > timeoutMs) {
|
|
314
|
-
expiredSessions.push(sessionId);
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
for (const sessionId of expiredSessions) {
|
|
318
|
-
const session = this.activeSessions.get(sessionId);
|
|
319
|
-
// Final persist before cleanup
|
|
320
|
-
await this.persistSession(session);
|
|
321
|
-
this.activeSessions.delete(sessionId);
|
|
322
|
-
this.emit('session_expired', { sessionId });
|
|
323
|
-
}
|
|
324
|
-
// Limit active sessions
|
|
325
|
-
if (this.activeSessions.size > this.config.maxSessions) {
|
|
326
|
-
const sessionsByAccess = Array.from(this.activeSessions.entries()).sort(([, a], [, b]) => a.lastAccessed.getTime() - b.lastAccessed.getTime());
|
|
327
|
-
const excessCount = this.activeSessions.size - this.config.maxSessions;
|
|
328
|
-
const toRemove = sessionsByAccess.slice(0, excessCount);
|
|
329
|
-
for (const [sessionId, session] of toRemove) {
|
|
330
|
-
await this.persistSession(session);
|
|
331
|
-
this.activeSessions.delete(sessionId);
|
|
332
|
-
this.emit('session_archived', { sessionId });
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
if (expiredSessions.length > 0) {
|
|
336
|
-
logger_1.logger.debug(`Cleaned up ${expiredSessions.length} expired sessions`);
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
/**
|
|
340
|
-
* Get session statistics
|
|
341
|
-
*/
|
|
342
|
-
getSessionStats() {
|
|
343
|
-
const activeSessions = this.activeSessions.size;
|
|
344
|
-
const totalCommands = Array.from(this.activeSessions.values()).reduce((sum, session) => sum + session.recentCommands.length, 0);
|
|
345
|
-
const sessionDurations = Array.from(this.activeSessions.values()).map(session => session.lastAccessed.getTime() - session.created.getTime());
|
|
346
|
-
const averageSessionDuration = sessionDurations.length > 0
|
|
347
|
-
? sessionDurations.reduce((sum, duration) => sum + duration, 0) /
|
|
348
|
-
sessionDurations.length
|
|
349
|
-
: 0;
|
|
350
|
-
// Command frequency analysis
|
|
351
|
-
const commandCounts = new Map();
|
|
352
|
-
for (const session of this.activeSessions.values()) {
|
|
353
|
-
for (const cmd of session.recentCommands) {
|
|
354
|
-
const baseCommand = cmd.command.split(' ')[0];
|
|
355
|
-
if (baseCommand) {
|
|
356
|
-
commandCounts.set(baseCommand, (commandCounts.get(baseCommand) || 0) + 1);
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
const mostUsedCommands = Array.from(commandCounts.entries())
|
|
361
|
-
.map(([command, count]) => ({ command, count }))
|
|
362
|
-
.sort((a, b) => b.count - a.count)
|
|
363
|
-
.slice(0, 10);
|
|
364
|
-
return {
|
|
365
|
-
activeSessions,
|
|
366
|
-
totalCommands,
|
|
367
|
-
averageSessionDuration,
|
|
368
|
-
mostUsedCommands,
|
|
369
|
-
workspaceCount: this.workspaces.size,
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
|
-
// Private methods
|
|
373
|
-
async initialize() {
|
|
374
|
-
// Ensure directories exist
|
|
375
|
-
await fs_extra_1.default.ensureDir(this.config.persistencePath);
|
|
376
|
-
await fs_extra_1.default.ensureDir(path_1.default.join(this.config.persistencePath, 'users'));
|
|
377
|
-
await fs_extra_1.default.ensureDir(path_1.default.join(this.config.persistencePath, 'workspaces'));
|
|
378
|
-
// Load existing workspaces
|
|
379
|
-
await this.loadAllWorkspaces();
|
|
380
|
-
// Start background tasks
|
|
381
|
-
this.startBackgroundTasks();
|
|
382
|
-
logger_1.logger.debug('Session manager initialized');
|
|
383
|
-
}
|
|
384
|
-
startBackgroundTasks() {
|
|
385
|
-
// Periodic backup
|
|
386
|
-
this.backupTimer = setInterval(async () => {
|
|
387
|
-
try {
|
|
388
|
-
await this.backupActiveSessions();
|
|
389
|
-
}
|
|
390
|
-
catch (error) {
|
|
391
|
-
logger_1.logger.error('Session backup failed:', error);
|
|
392
|
-
}
|
|
393
|
-
}, this.config.backupInterval * 60 * 1000);
|
|
394
|
-
// Periodic cleanup
|
|
395
|
-
this.cleanupTimer = setInterval(async () => {
|
|
396
|
-
try {
|
|
397
|
-
await this.cleanupSessions();
|
|
398
|
-
}
|
|
399
|
-
catch (error) {
|
|
400
|
-
logger_1.logger.error('Session cleanup failed:', error);
|
|
401
|
-
}
|
|
402
|
-
}, 30 * 60 * 1000); // Every 30 minutes
|
|
403
|
-
}
|
|
404
|
-
async detectProjectContext(workspacePath) {
|
|
405
|
-
if (!this.config.autoDetectProjects) {
|
|
406
|
-
return undefined;
|
|
407
|
-
}
|
|
408
|
-
try {
|
|
409
|
-
const context = {
|
|
410
|
-
rootPath: workspacePath,
|
|
411
|
-
projectType: 'unknown',
|
|
412
|
-
packageManager: 'unknown',
|
|
413
|
-
dependencies: [],
|
|
414
|
-
devDependencies: [],
|
|
415
|
-
scripts: {},
|
|
416
|
-
};
|
|
417
|
-
// Detect project type and package manager
|
|
418
|
-
const packageJsonPath = path_1.default.join(workspacePath, 'package.json');
|
|
419
|
-
if (await fs_extra_1.default.pathExists(packageJsonPath)) {
|
|
420
|
-
const packageJson = await fs_extra_1.default.readJson(packageJsonPath);
|
|
421
|
-
context.dependencies = Object.keys(packageJson.dependencies || {});
|
|
422
|
-
context.devDependencies = Object.keys(packageJson.devDependencies || {});
|
|
423
|
-
context.scripts = packageJson.scripts || {};
|
|
424
|
-
// Detect project type from dependencies
|
|
425
|
-
if (context.dependencies.includes('react')) {
|
|
426
|
-
context.projectType = 'react';
|
|
427
|
-
}
|
|
428
|
-
else if (context.dependencies.includes('vue')) {
|
|
429
|
-
context.projectType = 'vue';
|
|
430
|
-
}
|
|
431
|
-
else if (context.dependencies.includes('@angular/core')) {
|
|
432
|
-
context.projectType = 'angular';
|
|
433
|
-
}
|
|
434
|
-
else {
|
|
435
|
-
context.projectType = 'nodejs';
|
|
436
|
-
}
|
|
437
|
-
// Detect package manager
|
|
438
|
-
if (await fs_extra_1.default.pathExists(path_1.default.join(workspacePath, 'pnpm-lock.yaml'))) {
|
|
439
|
-
context.packageManager = 'pnpm';
|
|
440
|
-
}
|
|
441
|
-
else if (await fs_extra_1.default.pathExists(path_1.default.join(workspacePath, 'yarn.lock'))) {
|
|
442
|
-
context.packageManager = 'yarn';
|
|
443
|
-
}
|
|
444
|
-
else if (await fs_extra_1.default.pathExists(path_1.default.join(workspacePath, 'package-lock.json'))) {
|
|
445
|
-
context.packageManager = 'npm';
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
// Detect other project types
|
|
449
|
-
if (await fs_extra_1.default.pathExists(path_1.default.join(workspacePath, 'requirements.txt'))) {
|
|
450
|
-
context.projectType = 'python';
|
|
451
|
-
context.packageManager = 'pip';
|
|
452
|
-
}
|
|
453
|
-
else if (await fs_extra_1.default.pathExists(path_1.default.join(workspacePath, 'pom.xml'))) {
|
|
454
|
-
context.projectType = 'java';
|
|
455
|
-
context.packageManager = 'maven';
|
|
456
|
-
}
|
|
457
|
-
else if (await fs_extra_1.default.pathExists(path_1.default.join(workspacePath, 'build.gradle'))) {
|
|
458
|
-
context.projectType = 'java';
|
|
459
|
-
context.packageManager = 'gradle';
|
|
460
|
-
}
|
|
461
|
-
// Git information
|
|
462
|
-
const gitPath = path_1.default.join(workspacePath, '.git');
|
|
463
|
-
if (await fs_extra_1.default.pathExists(gitPath)) {
|
|
464
|
-
context.gitRepository = await this.getGitInfo(workspacePath);
|
|
465
|
-
}
|
|
466
|
-
return context;
|
|
467
|
-
}
|
|
468
|
-
catch (error) {
|
|
469
|
-
logger_1.logger.debug('Failed to detect project context:', error);
|
|
470
|
-
return undefined;
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
async getGitInfo(workspacePath) {
|
|
474
|
-
// Simplified git info extraction
|
|
475
|
-
return {
|
|
476
|
-
remote: 'origin',
|
|
477
|
-
branch: 'main',
|
|
478
|
-
status: 'clean',
|
|
479
|
-
hasUncommittedChanges: false,
|
|
480
|
-
};
|
|
481
|
-
}
|
|
482
|
-
getDefaultPreferences() {
|
|
483
|
-
return {
|
|
484
|
-
defaultModel: 'claude-3-5-sonnet-20241022',
|
|
485
|
-
preferredOutputFormat: 'table',
|
|
486
|
-
confirmDestructiveCommands: true,
|
|
487
|
-
enableStreamingResponses: true,
|
|
488
|
-
maxHistoryLength: 100,
|
|
489
|
-
autoSave: true,
|
|
490
|
-
theme: 'auto',
|
|
491
|
-
verbosity: 'normal',
|
|
492
|
-
aliases: {},
|
|
493
|
-
favorites: [],
|
|
494
|
-
workspacePreferences: {},
|
|
495
|
-
};
|
|
496
|
-
}
|
|
497
|
-
async loadUserPreferences(userId) {
|
|
498
|
-
const prefsPath = path_1.default.join(this.config.persistencePath, 'users', `${userId}.json`);
|
|
499
|
-
if (await fs_extra_1.default.pathExists(prefsPath)) {
|
|
500
|
-
try {
|
|
501
|
-
const saved = await fs_extra_1.default.readJson(prefsPath);
|
|
502
|
-
return { ...this.getDefaultPreferences(), ...saved };
|
|
503
|
-
}
|
|
504
|
-
catch (error) {
|
|
505
|
-
logger_1.logger.warn(`Failed to load preferences for ${userId}:`, error);
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
return this.getDefaultPreferences();
|
|
509
|
-
}
|
|
510
|
-
async saveUserPreferences(userId, preferences) {
|
|
511
|
-
const prefsPath = path_1.default.join(this.config.persistencePath, 'users', `${userId}.json`);
|
|
512
|
-
await fs_extra_1.default.ensureDir(path_1.default.dirname(prefsPath));
|
|
513
|
-
await fs_extra_1.default.writeJson(prefsPath, preferences, { spaces: 2 });
|
|
514
|
-
}
|
|
515
|
-
async persistSession(session) {
|
|
516
|
-
const sessionPath = path_1.default.join(this.config.persistencePath, `${session.id}.json`);
|
|
517
|
-
const serialized = this.serializeSession(session);
|
|
518
|
-
await fs_extra_1.default.writeJson(sessionPath, serialized, { spaces: 2 });
|
|
519
|
-
}
|
|
520
|
-
async loadSession(sessionId) {
|
|
521
|
-
const sessionPath = path_1.default.join(this.config.persistencePath, `${sessionId}.json`);
|
|
522
|
-
if (await fs_extra_1.default.pathExists(sessionPath)) {
|
|
523
|
-
try {
|
|
524
|
-
const data = await fs_extra_1.default.readJson(sessionPath);
|
|
525
|
-
return this.deserializeSession(data);
|
|
526
|
-
}
|
|
527
|
-
catch (error) {
|
|
528
|
-
logger_1.logger.warn(`Failed to load session ${sessionId}:`, error);
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
return null;
|
|
532
|
-
}
|
|
533
|
-
serializeSession(session) {
|
|
534
|
-
return {
|
|
535
|
-
...session,
|
|
536
|
-
created: session.created.toISOString(),
|
|
537
|
-
lastAccessed: session.lastAccessed.toISOString(),
|
|
538
|
-
recentCommands: session.recentCommands.map(cmd => ({
|
|
539
|
-
...cmd,
|
|
540
|
-
timestamp: cmd.timestamp.toISOString(),
|
|
541
|
-
})),
|
|
542
|
-
contextStack: session.contextStack.map(ctx => ({
|
|
543
|
-
...ctx,
|
|
544
|
-
timestamp: ctx.timestamp.toISOString(),
|
|
545
|
-
})),
|
|
546
|
-
projectContext: session.projectContext
|
|
547
|
-
? {
|
|
548
|
-
...session.projectContext,
|
|
549
|
-
lastAnalysis: session.projectContext.lastAnalysis
|
|
550
|
-
? {
|
|
551
|
-
...session.projectContext.lastAnalysis,
|
|
552
|
-
timestamp: session.projectContext.lastAnalysis.timestamp.toISOString(),
|
|
553
|
-
}
|
|
554
|
-
: undefined,
|
|
555
|
-
}
|
|
556
|
-
: undefined,
|
|
557
|
-
};
|
|
558
|
-
}
|
|
559
|
-
deserializeSession(data) {
|
|
560
|
-
return {
|
|
561
|
-
...data,
|
|
562
|
-
created: new Date(data.created),
|
|
563
|
-
lastAccessed: new Date(data.lastAccessed),
|
|
564
|
-
recentCommands: data.recentCommands.map((cmd) => ({
|
|
565
|
-
...cmd,
|
|
566
|
-
timestamp: new Date(cmd.timestamp),
|
|
567
|
-
})),
|
|
568
|
-
contextStack: data.contextStack.map((ctx) => ({
|
|
569
|
-
...ctx,
|
|
570
|
-
timestamp: new Date(ctx.timestamp),
|
|
571
|
-
})),
|
|
572
|
-
projectContext: data.projectContext
|
|
573
|
-
? {
|
|
574
|
-
...data.projectContext,
|
|
575
|
-
lastAnalysis: data.projectContext.lastAnalysis
|
|
576
|
-
? {
|
|
577
|
-
...data.projectContext.lastAnalysis,
|
|
578
|
-
timestamp: new Date(data.projectContext.lastAnalysis.timestamp),
|
|
579
|
-
}
|
|
580
|
-
: undefined,
|
|
581
|
-
}
|
|
582
|
-
: undefined,
|
|
583
|
-
};
|
|
584
|
-
}
|
|
585
|
-
async loadWorkspace(workspacePath) {
|
|
586
|
-
const workspacesDir = path_1.default.join(this.config.persistencePath, 'workspaces');
|
|
587
|
-
const workspaceFile = path_1.default.join(workspacesDir, `${Buffer.from(workspacePath).toString('base64')}.json`);
|
|
588
|
-
if (await fs_extra_1.default.pathExists(workspaceFile)) {
|
|
589
|
-
try {
|
|
590
|
-
const data = await fs_extra_1.default.readJson(workspaceFile);
|
|
591
|
-
data.lastAccessed = new Date(data.lastAccessed);
|
|
592
|
-
return data;
|
|
593
|
-
}
|
|
594
|
-
catch (error) {
|
|
595
|
-
logger_1.logger.warn(`Failed to load workspace ${workspacePath}:`, error);
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
return null;
|
|
599
|
-
}
|
|
600
|
-
async saveWorkspace(workspace) {
|
|
601
|
-
const workspacesDir = path_1.default.join(this.config.persistencePath, 'workspaces');
|
|
602
|
-
const workspaceFile = path_1.default.join(workspacesDir, `${Buffer.from(workspace.path).toString('base64')}.json`);
|
|
603
|
-
await fs_extra_1.default.ensureDir(workspacesDir);
|
|
604
|
-
await fs_extra_1.default.writeJson(workspaceFile, {
|
|
605
|
-
...workspace,
|
|
606
|
-
lastAccessed: workspace.lastAccessed.toISOString(),
|
|
607
|
-
}, { spaces: 2 });
|
|
608
|
-
}
|
|
609
|
-
async loadAllWorkspaces() {
|
|
610
|
-
const workspacesDir = path_1.default.join(this.config.persistencePath, 'workspaces');
|
|
611
|
-
if (await fs_extra_1.default.pathExists(workspacesDir)) {
|
|
612
|
-
const files = await fs_extra_1.default.readdir(workspacesDir);
|
|
613
|
-
for (const file of files) {
|
|
614
|
-
if (file.endsWith('.json')) {
|
|
615
|
-
try {
|
|
616
|
-
const data = await fs_extra_1.default.readJson(path_1.default.join(workspacesDir, file));
|
|
617
|
-
data.lastAccessed = new Date(data.lastAccessed);
|
|
618
|
-
this.workspaces.set(data.path, data);
|
|
619
|
-
}
|
|
620
|
-
catch (error) {
|
|
621
|
-
logger_1.logger.debug(`Failed to load workspace file ${file}:`, error);
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
async backupActiveSessions() {
|
|
628
|
-
for (const session of this.activeSessions.values()) {
|
|
629
|
-
await this.persistSession(session);
|
|
630
|
-
}
|
|
631
|
-
logger_1.logger.debug(`Backed up ${this.activeSessions.size} active sessions`);
|
|
632
|
-
}
|
|
633
|
-
async analyzeCommandPatterns(session) {
|
|
634
|
-
// Simple pattern analysis for learning user behavior
|
|
635
|
-
const recentCommands = session.recentCommands.slice(-10);
|
|
636
|
-
if (recentCommands.length >= 3) {
|
|
637
|
-
// Look for command sequences
|
|
638
|
-
const sequences = [];
|
|
639
|
-
for (let i = 0; i < recentCommands.length - 1; i++) {
|
|
640
|
-
const current = recentCommands[i];
|
|
641
|
-
const next = recentCommands[i + 1];
|
|
642
|
-
if (current?.command && next?.command) {
|
|
643
|
-
sequences.push(`${current.command} -> ${next.command}`);
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
// Store patterns in temporary data for future suggestions
|
|
647
|
-
if (!session.temporaryData['commandPatterns']) {
|
|
648
|
-
session.temporaryData['commandPatterns'] = [];
|
|
649
|
-
}
|
|
650
|
-
session.temporaryData['commandPatterns'].push(...sequences);
|
|
651
|
-
// Keep only recent patterns
|
|
652
|
-
session.temporaryData['commandPatterns'] =
|
|
653
|
-
session.temporaryData['commandPatterns'].slice(-20);
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
sessionToCsv(session) {
|
|
657
|
-
const headers = ['Timestamp', 'Command', 'Success', 'Duration'];
|
|
658
|
-
const rows = [headers];
|
|
659
|
-
session.recentCommands.forEach(cmd => {
|
|
660
|
-
rows.push([
|
|
661
|
-
cmd.timestamp.toISOString(),
|
|
662
|
-
`"${cmd.command.replace(/"/g, '""')}"`,
|
|
663
|
-
cmd.success.toString(),
|
|
664
|
-
cmd.duration.toString(),
|
|
665
|
-
]);
|
|
666
|
-
});
|
|
667
|
-
return rows.map(row => row.join(',')).join('\n');
|
|
668
|
-
}
|
|
669
|
-
/**
|
|
670
|
-
* Cleanup resources
|
|
671
|
-
*/
|
|
672
|
-
destroy() {
|
|
673
|
-
if (this.backupTimer) {
|
|
674
|
-
clearInterval(this.backupTimer);
|
|
675
|
-
}
|
|
676
|
-
if (this.cleanupTimer) {
|
|
677
|
-
clearInterval(this.cleanupTimer);
|
|
678
|
-
}
|
|
679
|
-
this.activeSessions.clear();
|
|
680
|
-
this.workspaces.clear();
|
|
681
|
-
this.removeAllListeners();
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
exports.SessionManager = SessionManager;
|
|
685
|
-
exports.default = SessionManager;
|
|
686
|
-
//# sourceMappingURL=session-manager.js.map
|