Skip to content
This repository was archived by the owner on Apr 28, 2026. It is now read-only.

Commit 04a816c

Browse files
committed
feat: Add support for multiple AI providers including Google, LM Studio, Mistral, Ollama, OpenAI, and xAI
- Implemented Google provider with streaming capabilities. - Added LM Studio provider for model interactions. - Integrated Mistral provider for AI model streaming. - Included Ollama provider for chat functionalities. - Enhanced OpenAI provider with new model options. - Introduced xAI provider for Grok models. - Established a unified interface for chat providers with streaming support. - Updated utility functions to handle streaming responses and content filtering. - Created types for chat providers and credentials for better type safety.
1 parent e966cfb commit 04a816c

49 files changed

Lines changed: 1250 additions & 7363 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,5 +111,6 @@
111111
],
112112
"[typescript]": {
113113
"editor.defaultFormatter": "biomejs.biome"
114-
}
114+
},
115+
"kiroAgent.configureMCP": "Disabled"
115116
}

README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,37 @@ cat server.js | rawi ask "Review this Express server for security issues"
189189
git diff | rawi ask "Write a conventional commit message for these changes"
190190
```
191191

192+
### 💬 `rawi chat` — Interactive Conversations
193+
194+
Start interactive chat sessions for back-and-forth conversations with AI.
195+
196+
```bash
197+
# Start an interactive chat session
198+
rawi chat
199+
200+
# Use specific profile for the chat session
201+
rawi chat --profile work
202+
203+
# Apply a specialized persona for the entire chat
204+
rawi chat --act ethereum-developer
205+
206+
# Start chat with verbose information
207+
rawi chat --verbose
208+
209+
# Chat commands within a session
210+
# /help - Show chat commands
211+
# /quit - Exit the chat (also /exit)
212+
# /clear - Clear conversation history
213+
```
214+
215+
**Perfect for:**
216+
217+
- Code reviews with multiple rounds of feedback
218+
- Brainstorming sessions
219+
- Technical discussions
220+
- Learning and exploration
221+
- Problem-solving conversations
222+
192223
### ⚙️ `rawi configure` — Setup & Management
193224

194225
Easy setup and profile management for all your AI providers.

man/rawi.1.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
**rawi** **ask** [*query*] [*options*]
1212

13+
**rawi** **chat** [*options*]
14+
1315
**rawi** **configure** [*options*]
1416

1517
**rawi** **history** [*options*] [*subcommand*]
@@ -248,6 +250,75 @@ Reset filtering configuration to defaults (enables all filter types).
248250

249251
**rawi ask** **--reset-filter-config**
250252

253+
### chat \- Interactive conversations with AI
254+
255+
**Synopsis:**
256+
257+
**rawi chat** [*options*]
258+
259+
**Description:**
260+
Start an interactive chat session for back-and-forth conversations with AI. Unlike the **ask** command which handles single requests, **chat** maintains conversation context throughout the session, making it ideal for collaborative problem-solving, code reviews, and extended discussions.
261+
262+
**Options:**
263+
264+
**-p, --profile** _profile_
265+
266+
Use a specific configuration profile (default: "default")
267+
268+
**--act** _template_
269+
270+
Apply an expert prompt template for the entire chat session. The AI will maintain this persona throughout the conversation. Use **rawi act --list** to see available templates.
271+
272+
**--verbose**
273+
274+
Show detailed status information, connection details, and debug output during the chat session
275+
276+
**Chat Commands:**
277+
278+
Once in a chat session, you can use special commands:
279+
280+
**/help**
281+
282+
Show available chat commands and instructions
283+
284+
**/quit** or **/exit**
285+
286+
End the chat session and return to terminal
287+
288+
**/clear**
289+
290+
Clear the conversation history while staying in the chat
291+
292+
**Examples:**
293+
294+
# Start basic interactive chat
295+
296+
**rawi chat**
297+
298+
# Use specific profile for chat
299+
300+
**rawi chat** **--profile** work
301+
302+
# Apply expert persona for entire chat
303+
304+
**rawi chat** **--act** ethereum-developer
305+
306+
# Start chat with verbose information
307+
308+
**rawi chat** **--verbose**
309+
310+
# Combined options
311+
312+
**rawi chat** **--profile** work **--act** code-reviewer **--verbose**
313+
314+
**Use Cases:**
315+
316+
- **Code Reviews**: Multi-round feedback and improvements
317+
- **Problem Solving**: Step-by-step debugging and exploration
318+
- **Learning**: Ask follow-up questions and dive deeper
319+
- **Brainstorming**: Interactive idea development
320+
- **Planning**: Collaborative project and architecture discussions
321+
251322
### configure \- Manage AI provider settings and profiles
252323

253324
**Synopsis:**

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "rawi",
33
"description": "Rawi (راوي) is the developer-friendly AI CLI that brings the power of 11 major AI providers directly to your terminal. With seamless shell integration, persistent conversations, and 200+ specialized prompt templates, Rawi transforms your command line into an intelligent development workspace.",
4-
"version": "0.0.10-beta.1",
4+
"version": "0.0.10-beta.5",
55
"type": "module",
66
"license": "MIT",
77
"bin": {

src/cli/commands/ask/actions/provider-processing.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import chalk from 'chalk';
22
import {ContentFilter} from '../../../../core/content-filter/content-filter.js';
33
import type {DatabaseManager} from '../../../../core/database/manager.js';
4-
import {processQuery} from '../../../../core/providers/utils.js';
4+
import {processQuery} from '../../../../core/providers/ask/utils.js';
55
import {spinnerManager} from '../../../../core/shared/spinner.js';
66

77
export const streamAIResponse = async (

src/cli/commands/chat.command.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import chalk from 'chalk';
2+
import {Command} from 'commander';
3+
import {DatabaseManager} from '../../core/database/manager.js';
4+
import {chatCommandOptions, startChatSession} from './chat/index.js';
5+
import type {ChatOptions} from './chat/types.js';
6+
7+
export const createChatCommand = (): Command => {
8+
const chatCommand = new Command('chat');
9+
10+
chatCommand.description(
11+
[
12+
chalk.bold('Start an interactive chat session with AI.'),
13+
'',
14+
chalk.gray('Engage in back-and-forth conversations with AI models.'),
15+
chalk.gray('Use --act <template> for expert prompt templates.'),
16+
chalk.gray('Type /quit or /exit to end the chat session.'),
17+
].join('\n'),
18+
);
19+
20+
chatCommandOptions.forEach((option) => {
21+
if ('defaultValue' in option && option.defaultValue !== undefined) {
22+
chatCommand.option(option.flags, option.description, option.defaultValue);
23+
} else {
24+
chatCommand.option(option.flags, option.description);
25+
}
26+
});
27+
28+
chatCommand.action(async (options: ChatOptions) => {
29+
let dbManager: DatabaseManager | null = null;
30+
31+
try {
32+
if (options.verbose) {
33+
console.log(chalk.dim('🚀 Starting chat session...'));
34+
}
35+
36+
dbManager = new DatabaseManager();
37+
await startChatSession(dbManager, options);
38+
} catch (error) {
39+
if (options.verbose) {
40+
console.error('Error in chat session:', error);
41+
}
42+
process.exit(1);
43+
} finally {
44+
if (dbManager) {
45+
dbManager.close();
46+
}
47+
}
48+
});
49+
50+
return chatCommand;
51+
};
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import * as readline from 'node:readline/promises';
2+
import chalk from 'chalk';
3+
import type {DatabaseManager} from '../../../../core/database/manager.js';
4+
import {DEFAULT_PROFILE} from '../../../../core/shared/constants.js';
5+
import {
6+
processActTemplate,
7+
validateCredentials,
8+
validateProfile,
9+
} from '../../ask/actions/index.js';
10+
import type {ChatOptions} from '../types.js';
11+
import {streamChatResponse} from './response-handler.js';
12+
13+
export interface ChatMessage {
14+
role: 'user' | 'assistant';
15+
content: string;
16+
}
17+
18+
export const startChatSession = async (
19+
_dbManager: DatabaseManager,
20+
options: ChatOptions,
21+
): Promise<void> => {
22+
const profile = options.profile || DEFAULT_PROFILE;
23+
validateProfile(profile, options);
24+
25+
const credentials = validateCredentials(profile, options);
26+
27+
if (options.verbose) {
28+
console.log(
29+
chalk.dim(
30+
`🔗 Connected to ${credentials.provider} (${credentials.model})`,
31+
),
32+
);
33+
console.log(chalk.dim(`📁 Profile: ${profile}`));
34+
if (options.act) {
35+
console.log(chalk.dim(`🎭 Act template: ${options.act}`));
36+
}
37+
console.log(chalk.dim('💬 Type "/quit" or "/exit" to end the chat\n'));
38+
}
39+
40+
const messages: ChatMessage[] = [];
41+
42+
if (options.act) {
43+
try {
44+
const systemPrompt = processActTemplate(options.act, '', options);
45+
if (systemPrompt?.trim()) {
46+
messages.push({
47+
role: 'assistant',
48+
content: `I'm now acting as: ${options.act}. How can I help you?`,
49+
});
50+
51+
if (options.verbose) {
52+
console.log(chalk.dim(`🎭 Applied act template: ${options.act}`));
53+
}
54+
}
55+
} catch (error) {
56+
console.error(chalk.red(`❌ Error applying act template: ${error}`));
57+
return;
58+
}
59+
}
60+
61+
console.log(chalk.bold.blue('🤖 Welcome to Rawi Chat!'));
62+
console.log(
63+
chalk.gray(
64+
'Start typing your message. Use /quit or /exit to end the chat.\n',
65+
),
66+
);
67+
68+
const terminal = readline.createInterface({
69+
input: process.stdin,
70+
output: process.stdout,
71+
});
72+
73+
try {
74+
while (true) {
75+
let userInput: string;
76+
77+
try {
78+
userInput = await terminal.question(chalk.blue('You: '));
79+
} catch (error) {
80+
if (
81+
error instanceof Error &&
82+
'code' in error &&
83+
error.code === 'ERR_USE_AFTER_CLOSE'
84+
) {
85+
console.log(chalk.yellow('\n👋 Chat session ended (stdin closed)'));
86+
break;
87+
}
88+
throw error;
89+
}
90+
91+
if (userInput.trim() === '/quit' || userInput.trim() === '/exit') {
92+
console.log(chalk.yellow('\n👋 Goodbye!'));
93+
break;
94+
}
95+
96+
if (userInput.trim() === '/help') {
97+
console.log(chalk.cyan('\n📚 Chat Commands:'));
98+
console.log(chalk.gray(' /help - Show this help message'));
99+
console.log(chalk.gray(' /quit - Exit the chat'));
100+
console.log(chalk.gray(' /exit - Exit the chat'));
101+
console.log(chalk.gray(' /clear - Clear message history'));
102+
console.log('');
103+
continue;
104+
}
105+
106+
if (userInput.trim() === '/clear') {
107+
messages.length = 0;
108+
console.log(chalk.dim('🧹 Message history cleared\n'));
109+
continue;
110+
}
111+
112+
if (userInput.trim() === '') {
113+
continue;
114+
}
115+
116+
messages.push({
117+
role: 'user',
118+
content: userInput.trim(),
119+
});
120+
121+
try {
122+
const assistantResponse = await streamChatResponse(
123+
credentials,
124+
messages,
125+
options,
126+
terminal,
127+
);
128+
129+
messages.push({
130+
role: 'assistant',
131+
content: assistantResponse,
132+
});
133+
} catch (error) {
134+
console.error(chalk.red(`❌ Error: ${error}`));
135+
}
136+
}
137+
} catch (error) {
138+
console.error(chalk.red(`❌ Error in chat session: ${error}`));
139+
} finally {
140+
terminal.close();
141+
}
142+
};
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './chat-session.js';
2+
export * from './response-handler.js';

0 commit comments

Comments
 (0)