janito 0.13.0__tar.gz → 0.14.0__tar.gz
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.
- {janito-0.13.0 → janito-0.14.0}/PKG-INFO +104 -8
- {janito-0.13.0 → janito-0.14.0}/README.md +103 -7
- janito-0.14.0/janito/__init__.py +5 -0
- janito-0.14.0/janito/cli/agent/__init__.py +7 -0
- janito-0.14.0/janito/cli/agent/conversation.py +149 -0
- janito-0.14.0/janito/cli/agent/initialization.py +172 -0
- janito-0.14.0/janito/cli/agent/query.py +108 -0
- janito-0.14.0/janito/cli/agent.py +12 -0
- janito-0.14.0/janito/cli/app.py +182 -0
- janito-0.14.0/janito/cli/commands/__init__.py +12 -0
- janito-0.13.0/janito/cli/commands.py → janito-0.14.0/janito/cli/commands/config.py +16 -103
- janito-0.14.0/janito/cli/commands/history.py +119 -0
- janito-0.14.0/janito/cli/commands/profile.py +72 -0
- janito-0.14.0/janito/cli/commands/validation.py +24 -0
- janito-0.14.0/janito/cli/commands/workspace.py +31 -0
- janito-0.14.0/janito/cli/commands.py +12 -0
- {janito-0.13.0 → janito-0.14.0}/janito/config.py +17 -0
- {janito-0.13.0 → janito-0.14.0}/janito/data/instructions_template.txt +7 -4
- {janito-0.13.0 → janito-0.14.0}/janito/tools/__init__.py +8 -2
- janito-0.14.0/janito/tools/fetch_webpage/__init__.py +23 -0
- janito-0.14.0/janito/tools/fetch_webpage/core.py +182 -0
- {janito-0.13.0 → janito-0.14.0}/janito/tools/search_text.py +225 -239
- janito-0.14.0/janito/tools/think.py +37 -0
- {janito-0.13.0 → janito-0.14.0}/janito/tools/usage_tracker.py +1 -0
- {janito-0.13.0 → janito-0.14.0}/pyproject.toml +1 -1
- janito-0.13.0/janito/__init__.py +0 -5
- janito-0.13.0/janito/cli/agent.py +0 -400
- janito-0.13.0/janito/cli/app.py +0 -94
- janito-0.13.0/janito/test_file.py +0 -4
- janito-0.13.0/janito/tools/fetch_webpage/__init__.py +0 -34
- janito-0.13.0/janito/tools/fetch_webpage/chunking.py +0 -76
- janito-0.13.0/janito/tools/fetch_webpage/core.py +0 -155
- janito-0.13.0/janito/tools/fetch_webpage/extractors.py +0 -276
- janito-0.13.0/janito/tools/fetch_webpage/news.py +0 -137
- janito-0.13.0/janito/tools/fetch_webpage/utils.py +0 -108
- {janito-0.13.0 → janito-0.14.0}/.gitignore +0 -0
- {janito-0.13.0 → janito-0.14.0}/LICENSE +0 -0
- {janito-0.13.0 → janito-0.14.0}/janito/__main__.py +0 -0
- {janito-0.13.0 → janito-0.14.0}/janito/callbacks.py +0 -0
- {janito-0.13.0 → janito-0.14.0}/janito/cli/__init__.py +0 -0
- {janito-0.13.0 → janito-0.14.0}/janito/cli/output.py +0 -0
- {janito-0.13.0 → janito-0.14.0}/janito/cli/utils.py +0 -0
- {janito-0.13.0 → janito-0.14.0}/janito/token_report.py +0 -0
- {janito-0.13.0 → janito-0.14.0}/janito/tools/bash/bash.py +0 -0
- {janito-0.13.0 → janito-0.14.0}/janito/tools/bash/unix_persistent_bash.py +0 -0
- {janito-0.13.0 → janito-0.14.0}/janito/tools/bash/win_persistent_bash.py +0 -0
- {janito-0.13.0 → janito-0.14.0}/janito/tools/decorators.py +0 -0
- {janito-0.13.0 → janito-0.14.0}/janito/tools/delete_file.py +0 -0
- {janito-0.13.0 → janito-0.14.0}/janito/tools/find_files.py +0 -0
- {janito-0.13.0 → janito-0.14.0}/janito/tools/move_file.py +0 -0
- {janito-0.13.0 → janito-0.14.0}/janito/tools/prompt_user.py +0 -0
- {janito-0.13.0 → janito-0.14.0}/janito/tools/replace_file.py +0 -0
- {janito-0.13.0 → janito-0.14.0}/janito/tools/rich_console.py +0 -0
- {janito-0.13.0 → janito-0.14.0}/janito/tools/str_replace_editor/__init__.py +0 -0
- {janito-0.13.0 → janito-0.14.0}/janito/tools/str_replace_editor/editor.py +0 -0
- {janito-0.13.0 → janito-0.14.0}/janito/tools/str_replace_editor/handlers/__init__.py +0 -0
- {janito-0.13.0 → janito-0.14.0}/janito/tools/str_replace_editor/handlers/create.py +0 -0
- {janito-0.13.0 → janito-0.14.0}/janito/tools/str_replace_editor/handlers/insert.py +0 -0
- {janito-0.13.0 → janito-0.14.0}/janito/tools/str_replace_editor/handlers/str_replace.py +0 -0
- {janito-0.13.0 → janito-0.14.0}/janito/tools/str_replace_editor/handlers/undo.py +0 -0
- {janito-0.13.0 → janito-0.14.0}/janito/tools/str_replace_editor/handlers/view.py +0 -0
- {janito-0.13.0 → janito-0.14.0}/janito/tools/str_replace_editor/utils.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: janito
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.14.0
|
4
4
|
Summary: Janito CLI tool
|
5
5
|
Project-URL: Homepage, https://github.com/joaompinto/janito
|
6
6
|
Author-email: João Pinto <lamego.pinto@gmail.com>
|
@@ -31,12 +31,13 @@ Janito is a powerful AI-assisted command-line interface (CLI) tool built with Py
|
|
31
31
|
- 🔍 Smart code search and editing
|
32
32
|
- 💻 Interactive terminal interface with rich formatting
|
33
33
|
- 📊 Detailed token usage tracking and cost reporting with cache savings analysis
|
34
|
-
- 🛑 Token and tool usage reporting even when interrupted with Ctrl+C
|
35
34
|
- 🌐 Web page fetching with content extraction capabilities
|
36
35
|
- 🔄 Parameter profiles for optimizing Claude's behavior for different tasks
|
37
36
|
- 📋 Line delta tracking to monitor net changes in files
|
38
|
-
- 💬
|
37
|
+
- 💬 Enhanced conversation history with browsing and management
|
39
38
|
- 🔇 Trust mode for concise output without tool details
|
39
|
+
- 🚫 No-tools mode for pure AI interactions without file system access
|
40
|
+
- 📝 Custom system instructions for specialized assistant behavior
|
40
41
|
|
41
42
|
## 🛠️ System Requirements
|
42
43
|
|
@@ -115,19 +116,35 @@ janito --trust "Optimize the HTML code"
|
|
115
116
|
# Or use the short alias
|
116
117
|
janito -t "Optimize the HTML code"
|
117
118
|
|
119
|
+
# Disable all tools for pure AI interaction
|
120
|
+
janito --no-tools "Explain how HTML works"
|
121
|
+
|
122
|
+
# View your conversation history
|
123
|
+
janito --history
|
124
|
+
|
125
|
+
# View a specific number of recent conversations
|
126
|
+
janito --history 10
|
127
|
+
|
118
128
|
# Continue the most recent conversation
|
119
129
|
janito --continue "Please add one more line"
|
120
130
|
|
121
131
|
# Continue a specific conversation using its message ID
|
122
132
|
# (Janito displays the message ID after each conversation)
|
123
|
-
janito --continue abc123def
|
133
|
+
janito --continue 'abc123def' 'Let's refine that code'
|
134
|
+
|
135
|
+
# Alternative way to continue a specific conversation
|
136
|
+
janito --continue-id abc123def "Let's refine that code"
|
137
|
+
|
138
|
+
# Provide custom system instructions
|
139
|
+
janito --system "You are a poetry expert who speaks in rhymes" "Write about coding"
|
140
|
+
# Or use the short alias
|
141
|
+
janito -s "You are a poetry expert who speaks in rhymes" "Write about coding"
|
124
142
|
|
125
143
|
# Show current configuration and available profiles
|
126
144
|
janito --show-config
|
127
145
|
|
128
146
|
# You can press Ctrl+C at any time to interrupt a query
|
129
|
-
#
|
130
|
-
# Even interrupted conversations can be continued with --continue
|
147
|
+
# Interrupted conversations can be continued with --continue
|
131
148
|
```
|
132
149
|
|
133
150
|
## 🔧 Available Tools
|
@@ -213,9 +230,58 @@ This feature is particularly useful for:
|
|
213
230
|
- Focusing on results rather than the process
|
214
231
|
- Creating cleaner output for documentation or sharing
|
215
232
|
|
233
|
+
## 🚫 No-Tools Mode
|
234
|
+
|
235
|
+
Janito provides a no-tools mode that disables all file system and external tools for pure AI interactions:
|
236
|
+
|
237
|
+
### How It Works
|
238
|
+
|
239
|
+
- When enabled with `--no-tools`, Janito disables all tools for the current session
|
240
|
+
- Claude will respond based purely on its knowledge without accessing or modifying files
|
241
|
+
- This mode is a per-session setting and not saved to your configuration
|
242
|
+
|
243
|
+
### Using No-Tools Mode
|
244
|
+
|
245
|
+
```bash
|
246
|
+
# Enable no-tools mode
|
247
|
+
janito --no-tools "Explain how Docker containers work"
|
248
|
+
```
|
249
|
+
|
250
|
+
This feature is particularly useful for:
|
251
|
+
- Getting general information or explanations without file system access
|
252
|
+
- Brainstorming sessions where you don't need file operations
|
253
|
+
- Safer operation in sensitive environments
|
254
|
+
- Faster responses for queries that don't require tools
|
255
|
+
|
256
|
+
## 📝 Custom System Instructions
|
257
|
+
|
258
|
+
Janito allows you to provide custom system instructions to change Claude's behavior:
|
259
|
+
|
260
|
+
### How It Works
|
261
|
+
|
262
|
+
- When provided with `--system` or `-s`, Janito uses your custom instructions instead of the default
|
263
|
+
- This allows you to create specialized assistant personalities or behaviors
|
264
|
+
- Custom instructions are a per-session setting and not saved to your configuration
|
265
|
+
|
266
|
+
### Using Custom System Instructions
|
267
|
+
|
268
|
+
```bash
|
269
|
+
# Provide custom system instructions
|
270
|
+
janito --system "You are a poetry expert who speaks in rhymes" "Write about coding"
|
271
|
+
|
272
|
+
# Or use the short alias
|
273
|
+
janito -s "You are a cybersecurity expert" "Review this authentication code"
|
274
|
+
```
|
275
|
+
|
276
|
+
This feature is particularly useful for:
|
277
|
+
- Creating specialized assistant personalities
|
278
|
+
- Focusing Claude on specific domains or expertise
|
279
|
+
- Setting up specific response formats or styles
|
280
|
+
- Educational scenarios where you need different expert perspectives
|
281
|
+
|
216
282
|
## 💬 Conversation History
|
217
283
|
|
218
|
-
Janito automatically saves your conversation history, allowing you to continue previous discussions:
|
284
|
+
Janito automatically saves your conversation history, allowing you to browse, manage, and continue previous discussions:
|
219
285
|
|
220
286
|
### How It Works
|
221
287
|
|
@@ -223,6 +289,23 @@ Janito automatically saves your conversation history, allowing you to continue p
|
|
223
289
|
- The most recent conversation is also saved as `.janito/last_message.json` for backward compatibility
|
224
290
|
- After each conversation, Janito displays the command to continue that specific conversation
|
225
291
|
|
292
|
+
### Browsing Your History
|
293
|
+
|
294
|
+
You can view your conversation history with the `--history` flag:
|
295
|
+
|
296
|
+
```bash
|
297
|
+
# Show the 20 most recent conversations (default)
|
298
|
+
janito --history
|
299
|
+
|
300
|
+
# Show a specific number of recent conversations
|
301
|
+
janito --history 10
|
302
|
+
```
|
303
|
+
|
304
|
+
This displays a table with:
|
305
|
+
- Conversation ID
|
306
|
+
- Date and time
|
307
|
+
- First query from each conversation
|
308
|
+
|
226
309
|
### Using the Continue Feature
|
227
310
|
|
228
311
|
```bash
|
@@ -231,6 +314,13 @@ janito --continue "Add more details to your previous response"
|
|
231
314
|
|
232
315
|
# Continue a specific conversation using its ID
|
233
316
|
janito --continue abc123def "Let's modify that code you suggested"
|
317
|
+
|
318
|
+
# Just use --continue without arguments to continue the most recent conversation
|
319
|
+
# and be prompted for your next query
|
320
|
+
janito --continue
|
321
|
+
|
322
|
+
# Alternative way to continue a specific conversation
|
323
|
+
janito --continue-id abc123def "Let's modify that code you suggested"
|
234
324
|
```
|
235
325
|
|
236
326
|
The `--continue` flag (or `-c` for short) allows you to:
|
@@ -266,11 +356,17 @@ Janito offers a variety of command-line options to customize its behavior:
|
|
266
356
|
--set-api-key TEXT Set the Anthropic API key globally in the user's home directory
|
267
357
|
--ask Enable ask mode which disables tools that perform changes
|
268
358
|
--trust, -t Enable trust mode which suppresses tool outputs for concise execution
|
359
|
+
--no-tools Disable all tools for this session (pure AI interaction)
|
269
360
|
--temperature FLOAT Set the temperature for model generation (0.0 to 1.0)
|
270
361
|
--profile TEXT Use a predefined parameter profile (precise, balanced, conversational, creative, technical)
|
271
362
|
--role TEXT Set the assistant's role (default: 'software engineer')
|
363
|
+
--system, -s TEXT Provide custom system instructions, bypassing the default file load method
|
272
364
|
--version Show the version and exit
|
273
|
-
--continue, -c TEXT Continue a
|
365
|
+
--continue, -c TEXT Continue a conversation. Can be used as: 1) --continue (to continue most recent),
|
366
|
+
2) --continue 123 (to continue conversation with ID 123), or
|
367
|
+
3) --continue "query" (to continue most recent with new query)
|
368
|
+
--continue-id TEXT Continue a specific conversation with the given ID
|
369
|
+
--history Show a summary of conversations. Use --history for default (20) or --history n to specify count
|
274
370
|
--help Show the help message and exit
|
275
371
|
```
|
276
372
|
|
@@ -11,12 +11,13 @@ Janito is a powerful AI-assisted command-line interface (CLI) tool built with Py
|
|
11
11
|
- 🔍 Smart code search and editing
|
12
12
|
- 💻 Interactive terminal interface with rich formatting
|
13
13
|
- 📊 Detailed token usage tracking and cost reporting with cache savings analysis
|
14
|
-
- 🛑 Token and tool usage reporting even when interrupted with Ctrl+C
|
15
14
|
- 🌐 Web page fetching with content extraction capabilities
|
16
15
|
- 🔄 Parameter profiles for optimizing Claude's behavior for different tasks
|
17
16
|
- 📋 Line delta tracking to monitor net changes in files
|
18
|
-
- 💬
|
17
|
+
- 💬 Enhanced conversation history with browsing and management
|
19
18
|
- 🔇 Trust mode for concise output without tool details
|
19
|
+
- 🚫 No-tools mode for pure AI interactions without file system access
|
20
|
+
- 📝 Custom system instructions for specialized assistant behavior
|
20
21
|
|
21
22
|
## 🛠️ System Requirements
|
22
23
|
|
@@ -95,19 +96,35 @@ janito --trust "Optimize the HTML code"
|
|
95
96
|
# Or use the short alias
|
96
97
|
janito -t "Optimize the HTML code"
|
97
98
|
|
99
|
+
# Disable all tools for pure AI interaction
|
100
|
+
janito --no-tools "Explain how HTML works"
|
101
|
+
|
102
|
+
# View your conversation history
|
103
|
+
janito --history
|
104
|
+
|
105
|
+
# View a specific number of recent conversations
|
106
|
+
janito --history 10
|
107
|
+
|
98
108
|
# Continue the most recent conversation
|
99
109
|
janito --continue "Please add one more line"
|
100
110
|
|
101
111
|
# Continue a specific conversation using its message ID
|
102
112
|
# (Janito displays the message ID after each conversation)
|
103
|
-
janito --continue abc123def
|
113
|
+
janito --continue 'abc123def' 'Let's refine that code'
|
114
|
+
|
115
|
+
# Alternative way to continue a specific conversation
|
116
|
+
janito --continue-id abc123def "Let's refine that code"
|
117
|
+
|
118
|
+
# Provide custom system instructions
|
119
|
+
janito --system "You are a poetry expert who speaks in rhymes" "Write about coding"
|
120
|
+
# Or use the short alias
|
121
|
+
janito -s "You are a poetry expert who speaks in rhymes" "Write about coding"
|
104
122
|
|
105
123
|
# Show current configuration and available profiles
|
106
124
|
janito --show-config
|
107
125
|
|
108
126
|
# You can press Ctrl+C at any time to interrupt a query
|
109
|
-
#
|
110
|
-
# Even interrupted conversations can be continued with --continue
|
127
|
+
# Interrupted conversations can be continued with --continue
|
111
128
|
```
|
112
129
|
|
113
130
|
## 🔧 Available Tools
|
@@ -193,9 +210,58 @@ This feature is particularly useful for:
|
|
193
210
|
- Focusing on results rather than the process
|
194
211
|
- Creating cleaner output for documentation or sharing
|
195
212
|
|
213
|
+
## 🚫 No-Tools Mode
|
214
|
+
|
215
|
+
Janito provides a no-tools mode that disables all file system and external tools for pure AI interactions:
|
216
|
+
|
217
|
+
### How It Works
|
218
|
+
|
219
|
+
- When enabled with `--no-tools`, Janito disables all tools for the current session
|
220
|
+
- Claude will respond based purely on its knowledge without accessing or modifying files
|
221
|
+
- This mode is a per-session setting and not saved to your configuration
|
222
|
+
|
223
|
+
### Using No-Tools Mode
|
224
|
+
|
225
|
+
```bash
|
226
|
+
# Enable no-tools mode
|
227
|
+
janito --no-tools "Explain how Docker containers work"
|
228
|
+
```
|
229
|
+
|
230
|
+
This feature is particularly useful for:
|
231
|
+
- Getting general information or explanations without file system access
|
232
|
+
- Brainstorming sessions where you don't need file operations
|
233
|
+
- Safer operation in sensitive environments
|
234
|
+
- Faster responses for queries that don't require tools
|
235
|
+
|
236
|
+
## 📝 Custom System Instructions
|
237
|
+
|
238
|
+
Janito allows you to provide custom system instructions to change Claude's behavior:
|
239
|
+
|
240
|
+
### How It Works
|
241
|
+
|
242
|
+
- When provided with `--system` or `-s`, Janito uses your custom instructions instead of the default
|
243
|
+
- This allows you to create specialized assistant personalities or behaviors
|
244
|
+
- Custom instructions are a per-session setting and not saved to your configuration
|
245
|
+
|
246
|
+
### Using Custom System Instructions
|
247
|
+
|
248
|
+
```bash
|
249
|
+
# Provide custom system instructions
|
250
|
+
janito --system "You are a poetry expert who speaks in rhymes" "Write about coding"
|
251
|
+
|
252
|
+
# Or use the short alias
|
253
|
+
janito -s "You are a cybersecurity expert" "Review this authentication code"
|
254
|
+
```
|
255
|
+
|
256
|
+
This feature is particularly useful for:
|
257
|
+
- Creating specialized assistant personalities
|
258
|
+
- Focusing Claude on specific domains or expertise
|
259
|
+
- Setting up specific response formats or styles
|
260
|
+
- Educational scenarios where you need different expert perspectives
|
261
|
+
|
196
262
|
## 💬 Conversation History
|
197
263
|
|
198
|
-
Janito automatically saves your conversation history, allowing you to continue previous discussions:
|
264
|
+
Janito automatically saves your conversation history, allowing you to browse, manage, and continue previous discussions:
|
199
265
|
|
200
266
|
### How It Works
|
201
267
|
|
@@ -203,6 +269,23 @@ Janito automatically saves your conversation history, allowing you to continue p
|
|
203
269
|
- The most recent conversation is also saved as `.janito/last_message.json` for backward compatibility
|
204
270
|
- After each conversation, Janito displays the command to continue that specific conversation
|
205
271
|
|
272
|
+
### Browsing Your History
|
273
|
+
|
274
|
+
You can view your conversation history with the `--history` flag:
|
275
|
+
|
276
|
+
```bash
|
277
|
+
# Show the 20 most recent conversations (default)
|
278
|
+
janito --history
|
279
|
+
|
280
|
+
# Show a specific number of recent conversations
|
281
|
+
janito --history 10
|
282
|
+
```
|
283
|
+
|
284
|
+
This displays a table with:
|
285
|
+
- Conversation ID
|
286
|
+
- Date and time
|
287
|
+
- First query from each conversation
|
288
|
+
|
206
289
|
### Using the Continue Feature
|
207
290
|
|
208
291
|
```bash
|
@@ -211,6 +294,13 @@ janito --continue "Add more details to your previous response"
|
|
211
294
|
|
212
295
|
# Continue a specific conversation using its ID
|
213
296
|
janito --continue abc123def "Let's modify that code you suggested"
|
297
|
+
|
298
|
+
# Just use --continue without arguments to continue the most recent conversation
|
299
|
+
# and be prompted for your next query
|
300
|
+
janito --continue
|
301
|
+
|
302
|
+
# Alternative way to continue a specific conversation
|
303
|
+
janito --continue-id abc123def "Let's modify that code you suggested"
|
214
304
|
```
|
215
305
|
|
216
306
|
The `--continue` flag (or `-c` for short) allows you to:
|
@@ -246,11 +336,17 @@ Janito offers a variety of command-line options to customize its behavior:
|
|
246
336
|
--set-api-key TEXT Set the Anthropic API key globally in the user's home directory
|
247
337
|
--ask Enable ask mode which disables tools that perform changes
|
248
338
|
--trust, -t Enable trust mode which suppresses tool outputs for concise execution
|
339
|
+
--no-tools Disable all tools for this session (pure AI interaction)
|
249
340
|
--temperature FLOAT Set the temperature for model generation (0.0 to 1.0)
|
250
341
|
--profile TEXT Use a predefined parameter profile (precise, balanced, conversational, creative, technical)
|
251
342
|
--role TEXT Set the assistant's role (default: 'software engineer')
|
343
|
+
--system, -s TEXT Provide custom system instructions, bypassing the default file load method
|
252
344
|
--version Show the version and exit
|
253
|
-
--continue, -c TEXT Continue a
|
345
|
+
--continue, -c TEXT Continue a conversation. Can be used as: 1) --continue (to continue most recent),
|
346
|
+
2) --continue 123 (to continue conversation with ID 123), or
|
347
|
+
3) --continue "query" (to continue most recent with new query)
|
348
|
+
--continue-id TEXT Continue a specific conversation with the given ID
|
349
|
+
--history Show a summary of conversations. Use --history for default (20) or --history n to specify count
|
254
350
|
--help Show the help message and exit
|
255
351
|
```
|
256
352
|
|
@@ -0,0 +1,149 @@
|
|
1
|
+
"""
|
2
|
+
Conversation management functionality for Janito CLI.
|
3
|
+
"""
|
4
|
+
import json
|
5
|
+
import datetime
|
6
|
+
import sys
|
7
|
+
from typing import Optional, List, Dict, Any
|
8
|
+
from rich.console import Console
|
9
|
+
from pathlib import Path
|
10
|
+
import claudine
|
11
|
+
|
12
|
+
from janito.config import get_config
|
13
|
+
|
14
|
+
console = Console()
|
15
|
+
|
16
|
+
def generate_message_id() -> str:
|
17
|
+
"""
|
18
|
+
Generate a message ID based on timestamp with seconds granularity
|
19
|
+
|
20
|
+
Returns:
|
21
|
+
str: A timestamp-based message ID
|
22
|
+
"""
|
23
|
+
timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
|
24
|
+
return timestamp
|
25
|
+
|
26
|
+
def save_messages(agent: claudine.Agent) -> Optional[str]:
|
27
|
+
"""
|
28
|
+
Save agent messages to .janito/last_messages/{message_id}.json
|
29
|
+
|
30
|
+
Args:
|
31
|
+
agent: The claudine agent instance
|
32
|
+
|
33
|
+
Returns:
|
34
|
+
str: The message ID used for saving, or None if saving failed
|
35
|
+
"""
|
36
|
+
try:
|
37
|
+
# Get the workspace directory
|
38
|
+
workspace_dir = Path(get_config().workspace_dir)
|
39
|
+
|
40
|
+
# Create .janito directory if it doesn't exist
|
41
|
+
janito_dir = workspace_dir / ".janito"
|
42
|
+
janito_dir.mkdir(exist_ok=True)
|
43
|
+
|
44
|
+
# Create last_messages directory if it doesn't exist
|
45
|
+
messages_dir = janito_dir / "last_messages"
|
46
|
+
messages_dir.mkdir(exist_ok=True)
|
47
|
+
|
48
|
+
# Generate a unique message ID
|
49
|
+
message_id = generate_message_id()
|
50
|
+
|
51
|
+
# Get messages from the agent
|
52
|
+
messages = agent.get_messages()
|
53
|
+
|
54
|
+
# Create a message object with metadata
|
55
|
+
message_object = {
|
56
|
+
"id": message_id,
|
57
|
+
"timestamp": datetime.datetime.now().isoformat(),
|
58
|
+
"messages": messages
|
59
|
+
}
|
60
|
+
|
61
|
+
# Save messages to file
|
62
|
+
message_file = messages_dir / f"{message_id}.json"
|
63
|
+
with open(message_file, "w", encoding="utf-8") as f:
|
64
|
+
json.dump(message_object, f, ensure_ascii=False, indent=2)
|
65
|
+
|
66
|
+
if get_config().verbose:
|
67
|
+
console.print(f"[bold green]✅ Conversation saved to {message_file}[/bold green]")
|
68
|
+
|
69
|
+
return message_id
|
70
|
+
except Exception as e:
|
71
|
+
console.print(f"[bold red]❌ Error saving conversation:[/bold red] {str(e)}")
|
72
|
+
return None
|
73
|
+
|
74
|
+
def load_messages(message_id: Optional[str] = None) -> Optional[List[Dict[str, Any]]]:
|
75
|
+
"""
|
76
|
+
Load messages from .janito/last_messages/{message_id}.json or the latest message file
|
77
|
+
|
78
|
+
Args:
|
79
|
+
message_id: Optional message ID to load specific conversation
|
80
|
+
|
81
|
+
Returns:
|
82
|
+
List of message dictionaries or None if file doesn't exist
|
83
|
+
"""
|
84
|
+
try:
|
85
|
+
# Get the workspace directory
|
86
|
+
workspace_dir = Path(get_config().workspace_dir)
|
87
|
+
janito_dir = workspace_dir / ".janito"
|
88
|
+
messages_dir = janito_dir / "last_messages"
|
89
|
+
|
90
|
+
# If message_id is provided, try to load that specific conversation
|
91
|
+
if message_id:
|
92
|
+
# Check if the message ID is a file name or just the ID
|
93
|
+
if message_id.endswith('.json'):
|
94
|
+
message_file = messages_dir / message_id
|
95
|
+
else:
|
96
|
+
message_file = messages_dir / f"{message_id}.json"
|
97
|
+
|
98
|
+
if not message_file.exists():
|
99
|
+
console.print(f"[bold yellow]⚠️ No conversation found with ID {message_id}[/bold yellow]")
|
100
|
+
return None
|
101
|
+
|
102
|
+
# Load messages from file
|
103
|
+
with open(message_file, "r", encoding="utf-8") as f:
|
104
|
+
message_object = json.load(f)
|
105
|
+
|
106
|
+
# Extract messages from the message object
|
107
|
+
if isinstance(message_object, dict) and "messages" in message_object:
|
108
|
+
messages = message_object["messages"]
|
109
|
+
else:
|
110
|
+
# Handle legacy format
|
111
|
+
messages = message_object
|
112
|
+
|
113
|
+
if get_config().verbose:
|
114
|
+
console.print(f"[bold green]✅ Loaded conversation from {message_file}[/bold green]")
|
115
|
+
console.print(f"[dim]📝 Conversation has {len(messages)} messages[/dim]")
|
116
|
+
|
117
|
+
return messages
|
118
|
+
|
119
|
+
# If no message_id is provided, try to load the latest message from last_messages directory
|
120
|
+
if not messages_dir.exists() or not any(messages_dir.iterdir()):
|
121
|
+
console.print("[bold yellow]⚠️ No previous conversation found[/bold yellow]")
|
122
|
+
return None
|
123
|
+
|
124
|
+
# Find the latest message file (based on filename which is a timestamp)
|
125
|
+
latest_file = max(
|
126
|
+
[f for f in messages_dir.iterdir() if f.is_file() and f.suffix == '.json'],
|
127
|
+
key=lambda x: x.stem
|
128
|
+
)
|
129
|
+
|
130
|
+
# Load messages from the latest file
|
131
|
+
with open(latest_file, "r", encoding="utf-8") as f:
|
132
|
+
message_object = json.load(f)
|
133
|
+
|
134
|
+
# Extract messages from the message object
|
135
|
+
if isinstance(message_object, dict) and "messages" in message_object:
|
136
|
+
messages = message_object["messages"]
|
137
|
+
else:
|
138
|
+
# Handle legacy format
|
139
|
+
messages = message_object
|
140
|
+
|
141
|
+
if get_config().verbose:
|
142
|
+
console.print(f"[bold green]✅ Loaded latest conversation from {latest_file}[/bold green]")
|
143
|
+
console.print(f"[dim]📝 Conversation has {len(messages)} messages[/dim]")
|
144
|
+
|
145
|
+
return messages
|
146
|
+
except Exception as e:
|
147
|
+
console.print(f"[bold red]❌ Error loading conversation:[/bold red] {str(e)}")
|
148
|
+
return None
|
149
|
+
|
@@ -0,0 +1,172 @@
|
|
1
|
+
"""
|
2
|
+
Agent initialization functionality for Janito CLI.
|
3
|
+
"""
|
4
|
+
import os
|
5
|
+
import platform
|
6
|
+
import typer
|
7
|
+
from typing import Optional, Dict, Any
|
8
|
+
from rich.console import Console
|
9
|
+
from jinja2 import Template
|
10
|
+
import importlib.resources as pkg_resources
|
11
|
+
import claudine
|
12
|
+
|
13
|
+
from janito.config import get_config, Config
|
14
|
+
from janito.callbacks import text_callback
|
15
|
+
from janito.tools import str_replace_editor, get_tools, reset_tracker
|
16
|
+
from janito.tools.bash.bash import bash_tool
|
17
|
+
from janito.cli.output import display_generation_params
|
18
|
+
|
19
|
+
console = Console()
|
20
|
+
|
21
|
+
def get_api_key() -> str:
|
22
|
+
"""
|
23
|
+
Get the API key from global config, environment variable, or user input.
|
24
|
+
|
25
|
+
Returns:
|
26
|
+
str: The API key
|
27
|
+
"""
|
28
|
+
# Get API key from global config, environment variable, or ask the user
|
29
|
+
api_key = Config.get_api_key()
|
30
|
+
|
31
|
+
# If not found in global config, try environment variable
|
32
|
+
if not api_key:
|
33
|
+
api_key = os.environ.get("ANTHROPIC_API_KEY")
|
34
|
+
|
35
|
+
# If still not found, prompt the user
|
36
|
+
if not api_key:
|
37
|
+
console.print("[bold yellow]⚠️ Warning:[/bold yellow] API key not found in global config or ANTHROPIC_API_KEY environment variable.")
|
38
|
+
console.print("🔑 Please set it using --set-api-key or provide your API key now:")
|
39
|
+
api_key = typer.prompt("Anthropic API Key", hide_input=True)
|
40
|
+
|
41
|
+
return api_key
|
42
|
+
|
43
|
+
def load_instructions() -> str:
|
44
|
+
"""
|
45
|
+
Load instructions template and render it with variables.
|
46
|
+
|
47
|
+
Returns:
|
48
|
+
str: The rendered instructions
|
49
|
+
"""
|
50
|
+
try:
|
51
|
+
# For Python 3.9+
|
52
|
+
try:
|
53
|
+
from importlib.resources import files
|
54
|
+
template_content = files('janito.data').joinpath('instructions_template.txt').read_text(encoding='utf-8')
|
55
|
+
# Fallback for older Python versions
|
56
|
+
except (ImportError, AttributeError):
|
57
|
+
template_content = pkg_resources.read_text('janito.data', 'instructions_template.txt', encoding='utf-8')
|
58
|
+
|
59
|
+
# Create template variables
|
60
|
+
template_variables = {
|
61
|
+
'platform': platform.system(),
|
62
|
+
'role': get_config().role,
|
63
|
+
# Add any other variables you want to pass to the template here
|
64
|
+
}
|
65
|
+
|
66
|
+
# Create template and render
|
67
|
+
template = Template(template_content)
|
68
|
+
instructions = template.render(**template_variables)
|
69
|
+
|
70
|
+
except Exception as e:
|
71
|
+
console.print(f"[bold red]❌ Error loading instructions template:[/bold red] {str(e)}")
|
72
|
+
# Try to fall back to regular instructions.txt
|
73
|
+
try:
|
74
|
+
# For Python 3.9+
|
75
|
+
try:
|
76
|
+
from importlib.resources import files
|
77
|
+
instructions = files('janito.data').joinpath('instructions.txt').read_text(encoding='utf-8')
|
78
|
+
# Fallback for older Python versions
|
79
|
+
except (ImportError, AttributeError):
|
80
|
+
instructions = pkg_resources.read_text('janito.data', 'instructions.txt', encoding='utf-8')
|
81
|
+
except Exception as e2:
|
82
|
+
console.print(f"[bold red]❌ Error loading fallback instructions:[/bold red] {str(e2)}")
|
83
|
+
instructions = "You are Janito, an AI assistant."
|
84
|
+
|
85
|
+
return instructions
|
86
|
+
|
87
|
+
def initialize_agent(temperature: float, verbose: bool, system_instructions: Optional[str] = None) -> claudine.Agent:
|
88
|
+
"""
|
89
|
+
Initialize the Claude agent with tools and configuration.
|
90
|
+
|
91
|
+
Args:
|
92
|
+
temperature: Temperature value for model generation
|
93
|
+
verbose: Whether to enable verbose mode
|
94
|
+
system_instructions: Optional custom system instructions to use instead of loading from file
|
95
|
+
|
96
|
+
Returns:
|
97
|
+
claudine.Agent: The initialized agent
|
98
|
+
"""
|
99
|
+
# Get API key
|
100
|
+
api_key = get_api_key()
|
101
|
+
|
102
|
+
# Load instructions or use provided system instructions
|
103
|
+
if system_instructions:
|
104
|
+
instructions = system_instructions
|
105
|
+
if verbose:
|
106
|
+
console.print("[bold blue]🔄 Using custom system instructions provided via --system parameter[/bold blue]")
|
107
|
+
# Print the first 50 characters of the instructions for verification
|
108
|
+
preview = system_instructions[:50] + "..." if len(system_instructions) > 50 else system_instructions
|
109
|
+
console.print(f"[dim]System instructions preview: {preview}[/dim]")
|
110
|
+
else:
|
111
|
+
instructions = load_instructions()
|
112
|
+
|
113
|
+
# Get tools
|
114
|
+
tools_list = get_tools()
|
115
|
+
|
116
|
+
# Reset usage tracker before each query
|
117
|
+
reset_tracker()
|
118
|
+
|
119
|
+
# Use command line parameters if provided (not default values), otherwise use config
|
120
|
+
temp_to_use = temperature if temperature != 0.0 else get_config().temperature
|
121
|
+
|
122
|
+
# Get profile parameters if a profile is set
|
123
|
+
config = get_config()
|
124
|
+
profile_data = None
|
125
|
+
if config.profile:
|
126
|
+
profile_data = config.get_available_profiles()[config.profile]
|
127
|
+
|
128
|
+
# Display generation parameters if verbose mode is enabled
|
129
|
+
if verbose:
|
130
|
+
display_generation_params(temp_to_use, profile_data, temperature)
|
131
|
+
|
132
|
+
# Create config_params dictionary with generation parameters
|
133
|
+
config_params = {
|
134
|
+
"temperature": temp_to_use
|
135
|
+
}
|
136
|
+
|
137
|
+
# Add top_k and top_p from profile if available
|
138
|
+
if profile_data:
|
139
|
+
if "top_k" in profile_data and profile_data["top_k"] != 0:
|
140
|
+
config_params["top_k"] = profile_data["top_k"]
|
141
|
+
if "top_p" in profile_data and profile_data["top_p"] != 0.0:
|
142
|
+
config_params["top_p"] = profile_data["top_p"]
|
143
|
+
|
144
|
+
# Initialize the agent
|
145
|
+
if get_config().no_tools:
|
146
|
+
# If no_tools mode is enabled, don't pass any tools to the agent
|
147
|
+
agent = claudine.Agent(
|
148
|
+
api_key=api_key,
|
149
|
+
system_prompt=instructions,
|
150
|
+
callbacks={"text": text_callback},
|
151
|
+
verbose=verbose,
|
152
|
+
max_tokens=8126,
|
153
|
+
max_tool_rounds=100,
|
154
|
+
config_params=config_params,
|
155
|
+
# Don't pass any tools, including text_editor_tool and bash_tool
|
156
|
+
)
|
157
|
+
else:
|
158
|
+
# Normal mode with tools
|
159
|
+
agent = claudine.Agent(
|
160
|
+
api_key=api_key,
|
161
|
+
system_prompt=instructions,
|
162
|
+
callbacks={"text": text_callback},
|
163
|
+
text_editor_tool=str_replace_editor,
|
164
|
+
bash_tool=bash_tool,
|
165
|
+
tools=tools_list,
|
166
|
+
verbose=verbose,
|
167
|
+
max_tokens=8126,
|
168
|
+
max_tool_rounds=100,
|
169
|
+
config_params=config_params,
|
170
|
+
)
|
171
|
+
|
172
|
+
return agent
|