@wundr.io/cli 1.0.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/README.md +551 -0
- package/bin/wundr.js +39 -0
- package/dist/ai/ai-service.d.ts +152 -0
- package/dist/ai/ai-service.d.ts.map +1 -0
- package/dist/ai/ai-service.js +430 -0
- package/dist/ai/ai-service.js.map +1 -0
- package/dist/ai/claude-client.d.ts +130 -0
- package/dist/ai/claude-client.d.ts.map +1 -0
- package/dist/ai/claude-client.js +339 -0
- package/dist/ai/claude-client.js.map +1 -0
- package/dist/ai/conversation-manager.d.ts +164 -0
- package/dist/ai/conversation-manager.d.ts.map +1 -0
- package/dist/ai/conversation-manager.js +612 -0
- package/dist/ai/conversation-manager.js.map +1 -0
- package/dist/ai/index.d.ts +5 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +8 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/cli.d.ts +36 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +173 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/ai.d.ts +89 -0
- package/dist/commands/ai.d.ts.map +1 -0
- package/dist/commands/ai.js +735 -0
- package/dist/commands/ai.js.map +1 -0
- package/dist/commands/analyze-optimized.d.ts +14 -0
- package/dist/commands/analyze-optimized.d.ts.map +1 -0
- package/dist/commands/analyze-optimized.js +437 -0
- package/dist/commands/analyze-optimized.js.map +1 -0
- package/dist/commands/analyze.d.ts +65 -0
- package/dist/commands/analyze.d.ts.map +1 -0
- package/dist/commands/analyze.js +435 -0
- package/dist/commands/analyze.js.map +1 -0
- package/dist/commands/batch.d.ts +71 -0
- package/dist/commands/batch.d.ts.map +1 -0
- package/dist/commands/batch.js +738 -0
- package/dist/commands/batch.js.map +1 -0
- package/dist/commands/chat.d.ts +71 -0
- package/dist/commands/chat.d.ts.map +1 -0
- package/dist/commands/chat.js +674 -0
- package/dist/commands/chat.js.map +1 -0
- package/dist/commands/claude-init.d.ts +28 -0
- package/dist/commands/claude-init.d.ts.map +1 -0
- package/dist/commands/claude-init.js +587 -0
- package/dist/commands/claude-init.js.map +1 -0
- package/dist/commands/claude-setup.d.ts +32 -0
- package/dist/commands/claude-setup.d.ts.map +1 -0
- package/dist/commands/claude-setup.js +570 -0
- package/dist/commands/claude-setup.js.map +1 -0
- package/dist/commands/computer-setup-commands.d.ts +39 -0
- package/dist/commands/computer-setup-commands.d.ts.map +1 -0
- package/dist/commands/computer-setup-commands.js +563 -0
- package/dist/commands/computer-setup-commands.js.map +1 -0
- package/dist/commands/computer-setup.d.ts +7 -0
- package/dist/commands/computer-setup.d.ts.map +1 -0
- package/dist/commands/computer-setup.js +481 -0
- package/dist/commands/computer-setup.js.map +1 -0
- package/dist/commands/create-command.d.ts +7 -0
- package/dist/commands/create-command.d.ts.map +1 -0
- package/dist/commands/create-command.js +158 -0
- package/dist/commands/create-command.js.map +1 -0
- package/dist/commands/create.d.ts +74 -0
- package/dist/commands/create.d.ts.map +1 -0
- package/dist/commands/create.js +556 -0
- package/dist/commands/create.js.map +1 -0
- package/dist/commands/dashboard.d.ts +91 -0
- package/dist/commands/dashboard.d.ts.map +1 -0
- package/dist/commands/dashboard.js +537 -0
- package/dist/commands/dashboard.js.map +1 -0
- package/dist/commands/govern.d.ts +70 -0
- package/dist/commands/govern.d.ts.map +1 -0
- package/dist/commands/govern.js +480 -0
- package/dist/commands/govern.js.map +1 -0
- package/dist/commands/init.d.ts +55 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +584 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/performance-optimizer.d.ts +30 -0
- package/dist/commands/performance-optimizer.d.ts.map +1 -0
- package/dist/commands/performance-optimizer.js +649 -0
- package/dist/commands/performance-optimizer.js.map +1 -0
- package/dist/commands/plugins.d.ts +87 -0
- package/dist/commands/plugins.d.ts.map +1 -0
- package/dist/commands/plugins.js +685 -0
- package/dist/commands/plugins.js.map +1 -0
- package/dist/commands/setup.d.ts +29 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +399 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/test-init.d.ts +9 -0
- package/dist/commands/test-init.d.ts.map +1 -0
- package/dist/commands/test-init.js +222 -0
- package/dist/commands/test-init.js.map +1 -0
- package/dist/commands/test.d.ts +25 -0
- package/dist/commands/test.d.ts.map +1 -0
- package/dist/commands/test.js +217 -0
- package/dist/commands/test.js.map +1 -0
- package/dist/commands/watch.d.ts +76 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +610 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/context/context-manager.d.ts +155 -0
- package/dist/context/context-manager.d.ts.map +1 -0
- package/dist/context/context-manager.js +383 -0
- package/dist/context/context-manager.js.map +1 -0
- package/dist/context/index.d.ts +3 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +6 -0
- package/dist/context/index.js.map +1 -0
- package/dist/context/session-manager.d.ts +207 -0
- package/dist/context/session-manager.d.ts.map +1 -0
- package/dist/context/session-manager.js +682 -0
- package/dist/context/session-manager.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/interactive/interactive-mode.d.ts +76 -0
- package/dist/interactive/interactive-mode.d.ts.map +1 -0
- package/dist/interactive/interactive-mode.js +730 -0
- package/dist/interactive/interactive-mode.js.map +1 -0
- package/dist/nlp/command-mapper.d.ts +174 -0
- package/dist/nlp/command-mapper.d.ts.map +1 -0
- package/dist/nlp/command-mapper.js +623 -0
- package/dist/nlp/command-mapper.js.map +1 -0
- package/dist/nlp/command-parser.d.ts +106 -0
- package/dist/nlp/command-parser.d.ts.map +1 -0
- package/dist/nlp/command-parser.js +416 -0
- package/dist/nlp/command-parser.js.map +1 -0
- package/dist/nlp/index.d.ts +5 -0
- package/dist/nlp/index.d.ts.map +1 -0
- package/dist/nlp/index.js +8 -0
- package/dist/nlp/index.js.map +1 -0
- package/dist/nlp/intent-classifier.d.ts +59 -0
- package/dist/nlp/intent-classifier.d.ts.map +1 -0
- package/dist/nlp/intent-classifier.js +384 -0
- package/dist/nlp/intent-classifier.js.map +1 -0
- package/dist/nlp/intent-parser.d.ts +152 -0
- package/dist/nlp/intent-parser.d.ts.map +1 -0
- package/dist/nlp/intent-parser.js +739 -0
- package/dist/nlp/intent-parser.js.map +1 -0
- package/dist/plugins/plugin-manager.d.ts +120 -0
- package/dist/plugins/plugin-manager.d.ts.map +1 -0
- package/dist/plugins/plugin-manager.js +595 -0
- package/dist/plugins/plugin-manager.js.map +1 -0
- package/dist/types/index.d.ts +224 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/config-manager.d.ts +73 -0
- package/dist/utils/config-manager.d.ts.map +1 -0
- package/dist/utils/config-manager.js +339 -0
- package/dist/utils/config-manager.js.map +1 -0
- package/dist/utils/error-handler.d.ts +46 -0
- package/dist/utils/error-handler.d.ts.map +1 -0
- package/dist/utils/error-handler.js +169 -0
- package/dist/utils/error-handler.js.map +1 -0
- package/dist/utils/logger.d.ts +25 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +94 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +119 -0
- package/src/ai/ai-service.ts +595 -0
- package/src/ai/claude-client.ts +490 -0
- package/src/ai/conversation-manager.ts +907 -0
- package/src/ai/index.ts +8 -0
- package/src/cli.ts +202 -0
- package/src/commands/ai.ts +995 -0
- package/src/commands/analyze-optimized.ts +641 -0
- package/src/commands/analyze.ts +576 -0
- package/src/commands/batch.ts +935 -0
- package/src/commands/chat.ts +876 -0
- package/src/commands/claude-init.ts +715 -0
- package/src/commands/claude-setup.ts +697 -0
- package/src/commands/computer-setup-commands.ts +709 -0
- package/src/commands/computer-setup.ts +565 -0
- package/src/commands/create-command.ts +175 -0
- package/src/commands/create.ts +727 -0
- package/src/commands/dashboard.ts +691 -0
- package/src/commands/govern.ts +635 -0
- package/src/commands/init.ts +677 -0
- package/src/commands/performance-optimizer.ts +864 -0
- package/src/commands/plugins.ts +848 -0
- package/src/commands/setup.ts +508 -0
- package/src/commands/test-init.ts +242 -0
- package/src/commands/test.ts +264 -0
- package/src/commands/watch.ts +755 -0
- package/src/context/context-manager.ts +546 -0
- package/src/context/index.ts +9 -0
- package/src/context/session-manager.ts +1019 -0
- package/src/index.ts +64 -0
- package/src/interactive/interactive-mode.ts +830 -0
- package/src/nlp/command-mapper.ts +885 -0
- package/src/nlp/command-parser.ts +564 -0
- package/src/nlp/index.ts +4 -0
- package/src/nlp/intent-classifier.ts +458 -0
- package/src/nlp/intent-parser.ts +1101 -0
- package/src/plugins/plugin-manager.ts +744 -0
- package/src/types/index.ts +252 -0
- package/src/types/modules.d.ts +56 -0
- package/src/utils/config-manager.ts +391 -0
- package/src/utils/error-handler.ts +192 -0
- package/src/utils/logger.ts +104 -0
- package/templates/batch/ci-cd.yaml +62 -0
- package/templates/component/{{fileName}}.test.tsx +17 -0
- package/templates/component/{{fileName}}.tsx +21 -0
- package/templates/service/{{fileName}}.ts +98 -0
- package/templates/wundr-test.config.js +0 -0
- package/test-suites/api/health.spec.ts +134 -0
- package/test-suites/helpers/test-config.ts +84 -0
- package/test-suites/ui/accessibility.spec.ts +102 -0
- package/test-suites/ui/smoke.spec.ts +92 -0
|
@@ -0,0 +1,876 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import fs from 'fs-extra';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import { ConfigManager } from '../utils/config-manager';
|
|
7
|
+
import { PluginManager } from '../plugins/plugin-manager';
|
|
8
|
+
import { logger } from '../utils/logger';
|
|
9
|
+
import { errorHandler } from '../utils/error-handler';
|
|
10
|
+
import { ChatSession, ChatMessage } from '../types';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Chat commands for natural language interface
|
|
14
|
+
*/
|
|
15
|
+
export class ChatCommands {
|
|
16
|
+
private activeSessions: Map<string, ChatSession> = new Map();
|
|
17
|
+
|
|
18
|
+
constructor(
|
|
19
|
+
private program: Command,
|
|
20
|
+
private configManager: ConfigManager,
|
|
21
|
+
private pluginManager: PluginManager
|
|
22
|
+
) {
|
|
23
|
+
this.registerCommands();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private registerCommands(): void {
|
|
27
|
+
const chatCmd = this.program
|
|
28
|
+
.command('chat')
|
|
29
|
+
.alias('c')
|
|
30
|
+
.description('natural language chat interface');
|
|
31
|
+
|
|
32
|
+
// Start chat session
|
|
33
|
+
chatCmd
|
|
34
|
+
.command('start')
|
|
35
|
+
.description('start a new chat session')
|
|
36
|
+
.option('--model <model>', 'AI model to use', 'claude-3')
|
|
37
|
+
.option('--context <path>', 'include project context from path')
|
|
38
|
+
.option(
|
|
39
|
+
'--persona <persona>',
|
|
40
|
+
'AI persona (developer, architect, reviewer)',
|
|
41
|
+
'developer'
|
|
42
|
+
)
|
|
43
|
+
.option('--session-name <name>', 'custom session name')
|
|
44
|
+
.action(async options => {
|
|
45
|
+
await this.startChatSession(options);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// Resume chat session
|
|
49
|
+
chatCmd
|
|
50
|
+
.command('resume <sessionId>')
|
|
51
|
+
.description('resume existing chat session')
|
|
52
|
+
.action(async sessionId => {
|
|
53
|
+
await this.resumeChatSession(sessionId);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// List chat sessions
|
|
57
|
+
chatCmd
|
|
58
|
+
.command('list')
|
|
59
|
+
.alias('ls')
|
|
60
|
+
.description('list chat sessions')
|
|
61
|
+
.option('--active-only', 'show only active sessions')
|
|
62
|
+
.action(async options => {
|
|
63
|
+
await this.listChatSessions(options);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Send single message
|
|
67
|
+
chatCmd
|
|
68
|
+
.command('ask <message>')
|
|
69
|
+
.description('send a single message and get response')
|
|
70
|
+
.option('--session <sessionId>', 'use specific session')
|
|
71
|
+
.option('--model <model>', 'AI model to use')
|
|
72
|
+
.option('--context <path>', 'include context from path')
|
|
73
|
+
.action(async (message, options) => {
|
|
74
|
+
await this.askSingleQuestion(message, options);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// Export chat session
|
|
78
|
+
chatCmd
|
|
79
|
+
.command('export <sessionId>')
|
|
80
|
+
.description('export chat session')
|
|
81
|
+
.option(
|
|
82
|
+
'--format <format>',
|
|
83
|
+
'export format (json, markdown, txt)',
|
|
84
|
+
'markdown'
|
|
85
|
+
)
|
|
86
|
+
.option('--output <path>', 'output file path')
|
|
87
|
+
.action(async (sessionId, options) => {
|
|
88
|
+
await this.exportChatSession(sessionId, options);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// Import chat session
|
|
92
|
+
chatCmd
|
|
93
|
+
.command('import <file>')
|
|
94
|
+
.description('import chat session')
|
|
95
|
+
.option('--format <format>', 'import format (json, markdown)')
|
|
96
|
+
.action(async (file, options) => {
|
|
97
|
+
await this.importChatSession(file, options);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// Delete chat session
|
|
101
|
+
chatCmd
|
|
102
|
+
.command('delete <sessionId>')
|
|
103
|
+
.description('delete chat session')
|
|
104
|
+
.option('--force', 'skip confirmation')
|
|
105
|
+
.action(async (sessionId, options) => {
|
|
106
|
+
await this.deleteChatSession(sessionId, options);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Configure chat
|
|
110
|
+
chatCmd.command('config').description('configure chat settings');
|
|
111
|
+
|
|
112
|
+
chatCmd
|
|
113
|
+
.command('config set <key> <value>')
|
|
114
|
+
.description('set chat configuration')
|
|
115
|
+
.action(async (key, value) => {
|
|
116
|
+
await this.setChatConfig(key, value);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
chatCmd
|
|
120
|
+
.command('config get [key]')
|
|
121
|
+
.description('get chat configuration')
|
|
122
|
+
.action(async key => {
|
|
123
|
+
await this.getChatConfig(key);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// Chat with files
|
|
127
|
+
chatCmd
|
|
128
|
+
.command('file <file>')
|
|
129
|
+
.description('chat about specific file')
|
|
130
|
+
.option(
|
|
131
|
+
'--action <action>',
|
|
132
|
+
'action to perform (explain, review, improve)',
|
|
133
|
+
'explain'
|
|
134
|
+
)
|
|
135
|
+
.option('--model <model>', 'AI model to use')
|
|
136
|
+
.action(async (file, options) => {
|
|
137
|
+
await this.chatWithFile(file, options);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// Chat with code
|
|
141
|
+
chatCmd
|
|
142
|
+
.command('code')
|
|
143
|
+
.description('chat about code from clipboard or input')
|
|
144
|
+
.option('--clipboard', 'read code from clipboard')
|
|
145
|
+
.option(
|
|
146
|
+
'--action <action>',
|
|
147
|
+
'action to perform (explain, review, improve)',
|
|
148
|
+
'explain'
|
|
149
|
+
)
|
|
150
|
+
.action(async options => {
|
|
151
|
+
await this.chatWithCode(options);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// Chat templates
|
|
155
|
+
chatCmd.command('template').description('manage chat templates');
|
|
156
|
+
|
|
157
|
+
chatCmd
|
|
158
|
+
.command('template list')
|
|
159
|
+
.description('list available chat templates')
|
|
160
|
+
.action(async () => {
|
|
161
|
+
await this.listChatTemplates();
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
chatCmd
|
|
165
|
+
.command('template use <name>')
|
|
166
|
+
.description('start chat with template')
|
|
167
|
+
.option('--vars <vars>', 'template variables (JSON or key=value)')
|
|
168
|
+
.action(async (name, options) => {
|
|
169
|
+
await this.useChatTemplate(name, options);
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Start a new chat session
|
|
175
|
+
*/
|
|
176
|
+
private async startChatSession(options: any): Promise<void> {
|
|
177
|
+
try {
|
|
178
|
+
logger.info('Starting new chat session...');
|
|
179
|
+
|
|
180
|
+
const session = await this.createNewSession(options);
|
|
181
|
+
this.activeSessions.set(session.id, session);
|
|
182
|
+
|
|
183
|
+
console.log(chalk.green(`\n🤖 Chat Session Started (${session.model})`));
|
|
184
|
+
console.log(chalk.gray(`Session ID: ${session.id}`));
|
|
185
|
+
if (session.context) {
|
|
186
|
+
console.log(chalk.gray(`Context: ${session.context}`));
|
|
187
|
+
}
|
|
188
|
+
console.log(
|
|
189
|
+
chalk.gray('Type "exit" to end the session, "help" for commands\n')
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
await this.runChatLoop(session);
|
|
193
|
+
} catch (error) {
|
|
194
|
+
throw errorHandler.createError(
|
|
195
|
+
'WUNDR_CHAT_START_FAILED',
|
|
196
|
+
'Failed to start chat session',
|
|
197
|
+
{ options },
|
|
198
|
+
true
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Resume existing chat session
|
|
205
|
+
*/
|
|
206
|
+
private async resumeChatSession(sessionId: string): Promise<void> {
|
|
207
|
+
try {
|
|
208
|
+
logger.info(`Resuming chat session: ${sessionId}`);
|
|
209
|
+
|
|
210
|
+
const session = await this.loadChatSession(sessionId);
|
|
211
|
+
if (!session) {
|
|
212
|
+
throw new Error(`Chat session not found: ${sessionId}`);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
this.activeSessions.set(sessionId, session);
|
|
216
|
+
|
|
217
|
+
console.log(chalk.green(`\n🤖 Chat Session Resumed (${session.model})`));
|
|
218
|
+
console.log(chalk.gray(`Session ID: ${session.id}`));
|
|
219
|
+
console.log(chalk.gray(`Messages: ${session.history.length}`));
|
|
220
|
+
console.log(
|
|
221
|
+
chalk.gray(`Last updated: ${session.updated.toLocaleString()}\n`)
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
// Show recent messages
|
|
225
|
+
if (session.history.length > 0) {
|
|
226
|
+
console.log(chalk.blue('Recent messages:'));
|
|
227
|
+
session.history.slice(-3).forEach(msg => {
|
|
228
|
+
const role = msg.role === 'user' ? 'You' : 'AI';
|
|
229
|
+
const content =
|
|
230
|
+
msg.content.length > 100
|
|
231
|
+
? msg.content.substring(0, 100) + '...'
|
|
232
|
+
: msg.content;
|
|
233
|
+
console.log(` ${chalk.cyan(role)}: ${content}`);
|
|
234
|
+
});
|
|
235
|
+
console.log();
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
await this.runChatLoop(session);
|
|
239
|
+
} catch (error) {
|
|
240
|
+
throw errorHandler.createError(
|
|
241
|
+
'WUNDR_CHAT_RESUME_FAILED',
|
|
242
|
+
'Failed to resume chat session',
|
|
243
|
+
{ sessionId },
|
|
244
|
+
true
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* List chat sessions
|
|
251
|
+
*/
|
|
252
|
+
private async listChatSessions(options: any): Promise<void> {
|
|
253
|
+
try {
|
|
254
|
+
const sessions = await this.getAllChatSessions();
|
|
255
|
+
const filteredSessions = options.activeOnly
|
|
256
|
+
? sessions.filter(s => this.activeSessions.has(s.id))
|
|
257
|
+
: sessions;
|
|
258
|
+
|
|
259
|
+
if (filteredSessions.length === 0) {
|
|
260
|
+
logger.info('No chat sessions found');
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
logger.info(`Chat sessions (${filteredSessions.length}):`);
|
|
265
|
+
|
|
266
|
+
const sessionData = filteredSessions.map(session => ({
|
|
267
|
+
ID: session.id,
|
|
268
|
+
Model: session.model,
|
|
269
|
+
Messages: session.history.length,
|
|
270
|
+
Created: session.created.toLocaleDateString(),
|
|
271
|
+
Updated: session.updated.toLocaleDateString(),
|
|
272
|
+
Active: this.activeSessions.has(session.id) ? '✓' : '✗',
|
|
273
|
+
}));
|
|
274
|
+
|
|
275
|
+
console.table(sessionData);
|
|
276
|
+
} catch (error) {
|
|
277
|
+
throw errorHandler.createError(
|
|
278
|
+
'WUNDR_CHAT_LIST_FAILED',
|
|
279
|
+
'Failed to list chat sessions',
|
|
280
|
+
{ options },
|
|
281
|
+
true
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Ask a single question
|
|
288
|
+
*/
|
|
289
|
+
private async askSingleQuestion(
|
|
290
|
+
message: string,
|
|
291
|
+
options: any
|
|
292
|
+
): Promise<void> {
|
|
293
|
+
try {
|
|
294
|
+
logger.debug('Processing single question...');
|
|
295
|
+
|
|
296
|
+
let session: ChatSession | null;
|
|
297
|
+
|
|
298
|
+
if (options.session) {
|
|
299
|
+
session = await this.loadChatSession(options.session);
|
|
300
|
+
if (!session) {
|
|
301
|
+
throw new Error(`Chat session not found: ${options.session}`);
|
|
302
|
+
}
|
|
303
|
+
} else {
|
|
304
|
+
session = await this.createNewSession({
|
|
305
|
+
model: options.model,
|
|
306
|
+
context: options.context,
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const response = await this.sendMessage(session, message);
|
|
311
|
+
|
|
312
|
+
console.log(chalk.cyan('\nAI Response:'));
|
|
313
|
+
console.log(response);
|
|
314
|
+
console.log();
|
|
315
|
+
|
|
316
|
+
// Save session if it was created for this question
|
|
317
|
+
if (!options.session) {
|
|
318
|
+
await this.saveChatSession(session);
|
|
319
|
+
logger.debug(`Session saved: ${session.id}`);
|
|
320
|
+
}
|
|
321
|
+
} catch (error) {
|
|
322
|
+
throw errorHandler.createError(
|
|
323
|
+
'WUNDR_CHAT_ASK_FAILED',
|
|
324
|
+
'Failed to process question',
|
|
325
|
+
{ message, options },
|
|
326
|
+
true
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Export chat session
|
|
333
|
+
*/
|
|
334
|
+
private async exportChatSession(
|
|
335
|
+
sessionId: string,
|
|
336
|
+
options: any
|
|
337
|
+
): Promise<void> {
|
|
338
|
+
try {
|
|
339
|
+
logger.info(`Exporting chat session: ${sessionId}`);
|
|
340
|
+
|
|
341
|
+
const session = await this.loadChatSession(sessionId);
|
|
342
|
+
if (!session) {
|
|
343
|
+
throw new Error(`Chat session not found: ${sessionId}`);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
let exportedContent: string;
|
|
347
|
+
|
|
348
|
+
switch (options.format) {
|
|
349
|
+
case 'json':
|
|
350
|
+
exportedContent = JSON.stringify(session, null, 2);
|
|
351
|
+
break;
|
|
352
|
+
case 'markdown':
|
|
353
|
+
exportedContent = this.convertToMarkdown(session);
|
|
354
|
+
break;
|
|
355
|
+
case 'txt':
|
|
356
|
+
exportedContent = this.convertToText(session);
|
|
357
|
+
break;
|
|
358
|
+
default:
|
|
359
|
+
throw new Error(`Unsupported export format: ${options.format}`);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
const outputPath =
|
|
363
|
+
options.output || `chat-${sessionId}.${options.format}`;
|
|
364
|
+
await fs.writeFile(outputPath, exportedContent);
|
|
365
|
+
|
|
366
|
+
logger.success(`Chat session exported: ${outputPath}`);
|
|
367
|
+
} catch (error) {
|
|
368
|
+
throw errorHandler.createError(
|
|
369
|
+
'WUNDR_CHAT_EXPORT_FAILED',
|
|
370
|
+
'Failed to export chat session',
|
|
371
|
+
{ sessionId, options },
|
|
372
|
+
true
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Import chat session
|
|
379
|
+
*/
|
|
380
|
+
private async importChatSession(file: string, options: any): Promise<void> {
|
|
381
|
+
try {
|
|
382
|
+
logger.info(`Importing chat session: ${file}`);
|
|
383
|
+
|
|
384
|
+
if (!(await fs.pathExists(file))) {
|
|
385
|
+
throw new Error(`File not found: ${file}`);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
let session: ChatSession;
|
|
389
|
+
|
|
390
|
+
switch (options.format) {
|
|
391
|
+
case 'json':
|
|
392
|
+
session = await fs.readJson(file);
|
|
393
|
+
break;
|
|
394
|
+
case 'markdown':
|
|
395
|
+
session = await this.parseMarkdown(file);
|
|
396
|
+
break;
|
|
397
|
+
default:
|
|
398
|
+
throw new Error(`Unsupported import format: ${options.format}`);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// Generate new ID for imported session
|
|
402
|
+
session.id = `imported-${Date.now()}`;
|
|
403
|
+
session.created = new Date();
|
|
404
|
+
session.updated = new Date();
|
|
405
|
+
|
|
406
|
+
await this.saveChatSession(session);
|
|
407
|
+
logger.success(`Chat session imported: ${session.id}`);
|
|
408
|
+
} catch (error) {
|
|
409
|
+
throw errorHandler.createError(
|
|
410
|
+
'WUNDR_CHAT_IMPORT_FAILED',
|
|
411
|
+
'Failed to import chat session',
|
|
412
|
+
{ file, options },
|
|
413
|
+
true
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Delete chat session
|
|
420
|
+
*/
|
|
421
|
+
private async deleteChatSession(
|
|
422
|
+
sessionId: string,
|
|
423
|
+
options: any
|
|
424
|
+
): Promise<void> {
|
|
425
|
+
try {
|
|
426
|
+
const session = await this.loadChatSession(sessionId);
|
|
427
|
+
if (!session) {
|
|
428
|
+
throw new Error(`Chat session not found: ${sessionId}`);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
if (!options.force) {
|
|
432
|
+
const { confirm } = await inquirer.prompt([
|
|
433
|
+
{
|
|
434
|
+
type: 'confirm',
|
|
435
|
+
name: 'confirm',
|
|
436
|
+
message: `Delete chat session ${sessionId}? (${session.history.length} messages)`,
|
|
437
|
+
default: false,
|
|
438
|
+
},
|
|
439
|
+
]);
|
|
440
|
+
|
|
441
|
+
if (!confirm) {
|
|
442
|
+
logger.info('Deletion cancelled');
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
await this.deleteChatSessionFile(sessionId);
|
|
448
|
+
this.activeSessions.delete(sessionId);
|
|
449
|
+
|
|
450
|
+
logger.success(`Chat session deleted: ${sessionId}`);
|
|
451
|
+
} catch (error) {
|
|
452
|
+
throw errorHandler.createError(
|
|
453
|
+
'WUNDR_CHAT_DELETE_FAILED',
|
|
454
|
+
'Failed to delete chat session',
|
|
455
|
+
{ sessionId, options },
|
|
456
|
+
true
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Chat with specific file
|
|
463
|
+
*/
|
|
464
|
+
private async chatWithFile(file: string, options: any): Promise<void> {
|
|
465
|
+
try {
|
|
466
|
+
if (!(await fs.pathExists(file))) {
|
|
467
|
+
throw new Error(`File not found: ${file}`);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
const fileContent = await fs.readFile(file, 'utf8');
|
|
471
|
+
const fileName = path.basename(file);
|
|
472
|
+
|
|
473
|
+
const actionPrompts = {
|
|
474
|
+
explain: `Please explain this code from ${fileName}:`,
|
|
475
|
+
review: `Please review this code from ${fileName} for potential issues:`,
|
|
476
|
+
improve: `Please suggest improvements for this code from ${fileName}:`,
|
|
477
|
+
};
|
|
478
|
+
|
|
479
|
+
const prompt =
|
|
480
|
+
actionPrompts[options.action as keyof typeof actionPrompts] ||
|
|
481
|
+
actionPrompts.explain;
|
|
482
|
+
const message = `${prompt}\n\n\`\`\`\n${fileContent}\n\`\`\``;
|
|
483
|
+
|
|
484
|
+
await this.askSingleQuestion(message, { model: options.model });
|
|
485
|
+
} catch (error) {
|
|
486
|
+
throw errorHandler.createError(
|
|
487
|
+
'WUNDR_CHAT_FILE_FAILED',
|
|
488
|
+
'Failed to chat with file',
|
|
489
|
+
{ file, options },
|
|
490
|
+
true
|
|
491
|
+
);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* Chat with code
|
|
497
|
+
*/
|
|
498
|
+
private async chatWithCode(options: any): Promise<void> {
|
|
499
|
+
try {
|
|
500
|
+
let code: string;
|
|
501
|
+
|
|
502
|
+
if (options.clipboard) {
|
|
503
|
+
// Read from clipboard (would need clipboard library)
|
|
504
|
+
code = 'Code from clipboard'; // Placeholder
|
|
505
|
+
} else {
|
|
506
|
+
const { codeInput } = await inquirer.prompt([
|
|
507
|
+
{
|
|
508
|
+
type: 'editor',
|
|
509
|
+
name: 'codeInput',
|
|
510
|
+
message: 'Enter your code:',
|
|
511
|
+
},
|
|
512
|
+
]);
|
|
513
|
+
code = codeInput;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
const actionPrompts = {
|
|
517
|
+
explain: 'Please explain this code:',
|
|
518
|
+
review: 'Please review this code for potential issues:',
|
|
519
|
+
improve: 'Please suggest improvements for this code:',
|
|
520
|
+
};
|
|
521
|
+
|
|
522
|
+
const prompt =
|
|
523
|
+
actionPrompts[options.action as keyof typeof actionPrompts] ||
|
|
524
|
+
actionPrompts.explain;
|
|
525
|
+
const message = `${prompt}\n\n\`\`\`\n${code}\n\`\`\``;
|
|
526
|
+
|
|
527
|
+
await this.askSingleQuestion(message, {});
|
|
528
|
+
} catch (error) {
|
|
529
|
+
throw errorHandler.createError(
|
|
530
|
+
'WUNDR_CHAT_CODE_FAILED',
|
|
531
|
+
'Failed to chat with code',
|
|
532
|
+
{ options },
|
|
533
|
+
true
|
|
534
|
+
);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Helper methods for chat operations
|
|
540
|
+
*/
|
|
541
|
+
private async createNewSession(options: any): Promise<ChatSession> {
|
|
542
|
+
const config = this.configManager.getConfig();
|
|
543
|
+
|
|
544
|
+
return {
|
|
545
|
+
id: options.sessionName || `session-${Date.now()}`,
|
|
546
|
+
model: options.model || config.ai.model,
|
|
547
|
+
context: options.context,
|
|
548
|
+
history: [],
|
|
549
|
+
created: new Date(),
|
|
550
|
+
updated: new Date(),
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
private async runChatLoop(session: ChatSession): Promise<void> {
|
|
555
|
+
while (true) {
|
|
556
|
+
try {
|
|
557
|
+
const { message } = await inquirer.prompt([
|
|
558
|
+
{
|
|
559
|
+
type: 'input',
|
|
560
|
+
name: 'message',
|
|
561
|
+
message: chalk.green('You:'),
|
|
562
|
+
validate: input => input.length > 0 || 'Message cannot be empty',
|
|
563
|
+
},
|
|
564
|
+
]);
|
|
565
|
+
|
|
566
|
+
if (message.toLowerCase() === 'exit') {
|
|
567
|
+
break;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
if (message.toLowerCase() === 'help') {
|
|
571
|
+
this.showChatHelp();
|
|
572
|
+
continue;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
if (message.startsWith('/')) {
|
|
576
|
+
await this.handleChatCommand(session, message);
|
|
577
|
+
continue;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
const response = await this.sendMessage(session, message);
|
|
581
|
+
console.log(chalk.cyan(`\nAI: ${response}\n`));
|
|
582
|
+
} catch (error) {
|
|
583
|
+
logger.error('Chat error:', error);
|
|
584
|
+
console.log(
|
|
585
|
+
chalk.red('Sorry, there was an error processing your message.\n')
|
|
586
|
+
);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
// Save session when exiting
|
|
591
|
+
await this.saveChatSession(session);
|
|
592
|
+
this.activeSessions.delete(session.id);
|
|
593
|
+
logger.success('Chat session ended and saved');
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
private async sendMessage(
|
|
597
|
+
session: ChatSession,
|
|
598
|
+
message: string
|
|
599
|
+
): Promise<string> {
|
|
600
|
+
// Add user message to history
|
|
601
|
+
const userMessage: ChatMessage = {
|
|
602
|
+
role: 'user',
|
|
603
|
+
content: message,
|
|
604
|
+
timestamp: new Date(),
|
|
605
|
+
};
|
|
606
|
+
session.history.push(userMessage);
|
|
607
|
+
|
|
608
|
+
// Call AI service (mock implementation)
|
|
609
|
+
const response = await this.callAI(session, message);
|
|
610
|
+
|
|
611
|
+
// Add AI response to history
|
|
612
|
+
const aiMessage: ChatMessage = {
|
|
613
|
+
role: 'assistant',
|
|
614
|
+
content: response,
|
|
615
|
+
timestamp: new Date(),
|
|
616
|
+
};
|
|
617
|
+
session.history.push(aiMessage);
|
|
618
|
+
|
|
619
|
+
session.updated = new Date();
|
|
620
|
+
|
|
621
|
+
return response;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
private async callAI(session: ChatSession, message: string): Promise<string> {
|
|
625
|
+
// Mock AI service call
|
|
626
|
+
// In a real implementation, this would call Claude, GPT, etc.
|
|
627
|
+
return `This is a mock response to: "${message}". The AI would provide a helpful response here based on the context and conversation history.`;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
private showChatHelp(): void {
|
|
631
|
+
console.log(chalk.blue('\nChat Commands:'));
|
|
632
|
+
console.log(' exit - End the chat session');
|
|
633
|
+
console.log(' help - Show this help message');
|
|
634
|
+
console.log(' /clear - Clear chat history');
|
|
635
|
+
console.log(' /save - Save chat session');
|
|
636
|
+
console.log(' /export - Export chat session');
|
|
637
|
+
console.log(' /context - Show current context');
|
|
638
|
+
console.log(' /model - Change AI model');
|
|
639
|
+
console.log();
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
private async handleChatCommand(
|
|
643
|
+
session: ChatSession,
|
|
644
|
+
command: string
|
|
645
|
+
): Promise<void> {
|
|
646
|
+
const [cmd, ...args] = command.slice(1).split(' ');
|
|
647
|
+
|
|
648
|
+
switch (cmd) {
|
|
649
|
+
case 'clear':
|
|
650
|
+
session.history = [];
|
|
651
|
+
console.log(chalk.green('Chat history cleared\n'));
|
|
652
|
+
break;
|
|
653
|
+
|
|
654
|
+
case 'save':
|
|
655
|
+
await this.saveChatSession(session);
|
|
656
|
+
console.log(chalk.green(`Session saved: ${session.id}\n`));
|
|
657
|
+
break;
|
|
658
|
+
|
|
659
|
+
case 'export':
|
|
660
|
+
const format = args[0] || 'markdown';
|
|
661
|
+
await this.exportChatSession(session.id, {
|
|
662
|
+
format,
|
|
663
|
+
output: `${session.id}.${format}`,
|
|
664
|
+
});
|
|
665
|
+
break;
|
|
666
|
+
|
|
667
|
+
case 'context':
|
|
668
|
+
console.log(chalk.blue('Current Context:'));
|
|
669
|
+
console.log(` Model: ${session.model}`);
|
|
670
|
+
console.log(` Messages: ${session.history.length}`);
|
|
671
|
+
console.log(` Context: ${session.context || 'None'}\n`);
|
|
672
|
+
break;
|
|
673
|
+
|
|
674
|
+
case 'model':
|
|
675
|
+
if (args[0]) {
|
|
676
|
+
session.model = args[0];
|
|
677
|
+
console.log(chalk.green(`Model changed to: ${args[0]}\n`));
|
|
678
|
+
} else {
|
|
679
|
+
console.log(chalk.yellow('Current model: ' + session.model + '\n'));
|
|
680
|
+
}
|
|
681
|
+
break;
|
|
682
|
+
|
|
683
|
+
default:
|
|
684
|
+
console.log(chalk.red(`Unknown command: /${cmd}\n`));
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
private async saveChatSession(session: ChatSession): Promise<void> {
|
|
689
|
+
const sessionPath = path.join(
|
|
690
|
+
process.cwd(),
|
|
691
|
+
'.wundr',
|
|
692
|
+
'chat',
|
|
693
|
+
`${session.id}.json`
|
|
694
|
+
);
|
|
695
|
+
await fs.ensureDir(path.dirname(sessionPath));
|
|
696
|
+
await fs.writeJson(sessionPath, session, { spaces: 2 });
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
private async loadChatSession(
|
|
700
|
+
sessionId: string
|
|
701
|
+
): Promise<ChatSession | null> {
|
|
702
|
+
const sessionPath = path.join(
|
|
703
|
+
process.cwd(),
|
|
704
|
+
'.wundr',
|
|
705
|
+
'chat',
|
|
706
|
+
`${sessionId}.json`
|
|
707
|
+
);
|
|
708
|
+
if (await fs.pathExists(sessionPath)) {
|
|
709
|
+
const data = await fs.readJson(sessionPath);
|
|
710
|
+
data.created = new Date(data.created);
|
|
711
|
+
data.updated = new Date(data.updated);
|
|
712
|
+
data.history = data.history.map((msg: any) => ({
|
|
713
|
+
...msg,
|
|
714
|
+
timestamp: new Date(msg.timestamp),
|
|
715
|
+
}));
|
|
716
|
+
return data;
|
|
717
|
+
}
|
|
718
|
+
return null;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
private async getAllChatSessions(): Promise<ChatSession[]> {
|
|
722
|
+
const chatDir = path.join(process.cwd(), '.wundr', 'chat');
|
|
723
|
+
if (!(await fs.pathExists(chatDir))) {
|
|
724
|
+
return [];
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
const files = await fs.readdir(chatDir);
|
|
728
|
+
const jsonFiles = files.filter(f => f.endsWith('.json'));
|
|
729
|
+
|
|
730
|
+
const sessions: ChatSession[] = [];
|
|
731
|
+
for (const file of jsonFiles) {
|
|
732
|
+
try {
|
|
733
|
+
const sessionId = path.basename(file, '.json');
|
|
734
|
+
const session = await this.loadChatSession(sessionId);
|
|
735
|
+
if (session) {
|
|
736
|
+
sessions.push(session);
|
|
737
|
+
}
|
|
738
|
+
} catch (error) {
|
|
739
|
+
logger.debug(`Failed to load session ${file}:`, error);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
return sessions;
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
private async deleteChatSessionFile(sessionId: string): Promise<void> {
|
|
747
|
+
const sessionPath = path.join(
|
|
748
|
+
process.cwd(),
|
|
749
|
+
'.wundr',
|
|
750
|
+
'chat',
|
|
751
|
+
`${sessionId}.json`
|
|
752
|
+
);
|
|
753
|
+
if (await fs.pathExists(sessionPath)) {
|
|
754
|
+
await fs.remove(sessionPath);
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
private convertToMarkdown(session: ChatSession): string {
|
|
759
|
+
let markdown = `# Chat Session: ${session.id}\n\n`;
|
|
760
|
+
markdown += `**Model:** ${session.model}\n`;
|
|
761
|
+
markdown += `**Created:** ${session.created.toLocaleString()}\n`;
|
|
762
|
+
markdown += `**Updated:** ${session.updated.toLocaleString()}\n`;
|
|
763
|
+
if (session.context) {
|
|
764
|
+
markdown += `**Context:** ${session.context}\n`;
|
|
765
|
+
}
|
|
766
|
+
markdown += `**Messages:** ${session.history.length}\n\n`;
|
|
767
|
+
markdown += '---\n\n';
|
|
768
|
+
|
|
769
|
+
session.history.forEach(msg => {
|
|
770
|
+
const role = msg.role === 'user' ? '**You**' : '**AI**';
|
|
771
|
+
markdown += `${role} (${msg.timestamp.toLocaleTimeString()}):\n\n`;
|
|
772
|
+
markdown += `${msg.content}\n\n`;
|
|
773
|
+
markdown += '---\n\n';
|
|
774
|
+
});
|
|
775
|
+
|
|
776
|
+
return markdown;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
private convertToText(session: ChatSession): string {
|
|
780
|
+
let text = `Chat Session: ${session.id}\n`;
|
|
781
|
+
text += `Model: ${session.model}\n`;
|
|
782
|
+
text += `Created: ${session.created.toLocaleString()}\n`;
|
|
783
|
+
text += `Updated: ${session.updated.toLocaleString()}\n`;
|
|
784
|
+
text += `Messages: ${session.history.length}\n\n`;
|
|
785
|
+
text += '='.repeat(50) + '\n\n';
|
|
786
|
+
|
|
787
|
+
session.history.forEach(msg => {
|
|
788
|
+
const role = msg.role === 'user' ? 'You' : 'AI';
|
|
789
|
+
text += `[${msg.timestamp.toLocaleTimeString()}] ${role}:\n`;
|
|
790
|
+
text += `${msg.content}\n\n`;
|
|
791
|
+
text += '-'.repeat(30) + '\n\n';
|
|
792
|
+
});
|
|
793
|
+
|
|
794
|
+
return text;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
private async parseMarkdown(file: string): Promise<ChatSession> {
|
|
798
|
+
// Implementation to parse markdown format back to session
|
|
799
|
+
const content = await fs.readFile(file, 'utf8');
|
|
800
|
+
|
|
801
|
+
// This is a simplified parser - a real implementation would be more robust
|
|
802
|
+
return {
|
|
803
|
+
id: `parsed-${Date.now()}`,
|
|
804
|
+
model: 'claude-3',
|
|
805
|
+
history: [],
|
|
806
|
+
created: new Date(),
|
|
807
|
+
updated: new Date(),
|
|
808
|
+
};
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
// Configuration methods
|
|
812
|
+
private async setChatConfig(key: string, value: string): Promise<void> {
|
|
813
|
+
this.configManager.set(`chat.${key}`, value);
|
|
814
|
+
await this.configManager.saveConfig();
|
|
815
|
+
logger.success(`Chat configuration updated: ${key} = ${value}`);
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
private async getChatConfig(key?: string): Promise<void> {
|
|
819
|
+
if (key) {
|
|
820
|
+
const value = this.configManager.get(`chat.${key}`);
|
|
821
|
+
console.log(`${key}: ${value}`);
|
|
822
|
+
} else {
|
|
823
|
+
const chatConfig = this.configManager.get('chat') || {};
|
|
824
|
+
console.log(JSON.stringify(chatConfig, null, 2));
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
// Template methods
|
|
829
|
+
private async listChatTemplates(): Promise<void> {
|
|
830
|
+
const templates = [
|
|
831
|
+
'code-review',
|
|
832
|
+
'explain-code',
|
|
833
|
+
'debug-help',
|
|
834
|
+
'architecture-review',
|
|
835
|
+
'performance-optimization',
|
|
836
|
+
];
|
|
837
|
+
|
|
838
|
+
console.log('Available chat templates:');
|
|
839
|
+
templates.forEach(template => {
|
|
840
|
+
console.log(` - ${template}`);
|
|
841
|
+
});
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
private async useChatTemplate(name: string, options: any): Promise<void> {
|
|
845
|
+
const templates: Record<string, string> = {
|
|
846
|
+
'code-review':
|
|
847
|
+
'Please review the following code for best practices, potential bugs, and improvements:',
|
|
848
|
+
'explain-code': 'Please explain what this code does and how it works:',
|
|
849
|
+
'debug-help':
|
|
850
|
+
"I'm having trouble with this code. Can you help me debug it?",
|
|
851
|
+
'architecture-review':
|
|
852
|
+
'Please review this architectural design and suggest improvements:',
|
|
853
|
+
'performance-optimization':
|
|
854
|
+
'Please suggest performance optimizations for this code:',
|
|
855
|
+
};
|
|
856
|
+
|
|
857
|
+
const template = templates[name];
|
|
858
|
+
if (!template) {
|
|
859
|
+
throw new Error(`Template not found: ${name}`);
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
// Process template variables if provided
|
|
863
|
+
let processedTemplate = template;
|
|
864
|
+
if (options.vars) {
|
|
865
|
+
const variables = JSON.parse(options.vars);
|
|
866
|
+
Object.entries(variables).forEach(([key, value]) => {
|
|
867
|
+
processedTemplate = processedTemplate.replace(
|
|
868
|
+
`{{${key}}}`,
|
|
869
|
+
String(value)
|
|
870
|
+
);
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
await this.askSingleQuestion(processedTemplate, {});
|
|
875
|
+
}
|
|
876
|
+
}
|