Added a /list command to see saved conversations. Readme changes++

This commit is contained in:
2025-12-12 07:57:44 +01:00
parent 2da56b905d
commit 45877b911c
2 changed files with 95 additions and 10 deletions

View File

@@ -67,6 +67,14 @@ export PATH="$HOME/.local/bin:$PATH"
oai
```
### 5. Alternative Installation (for *nix systems)
If you have issues with the above method you can add an alias in your `.bashrc`, `.zshrc` etc.
```bash
alias oai='python3 <path to your file>'
```
On first run, you will be prompted to enter your OpenRouter API key.
## Usage
@@ -124,11 +132,16 @@ You> Analyze this image @/path/to/image.png
```
**View Session Stats:**
```
/stats
/credits
```
**Prevous commands input:**
Use the up/down arrows to see earlier `/`commands and earlier input to model and `<enter>` to execute the same command or resend the same input.
## Command Reference
Use `/help` within the application for a complete command reference organized by category:

92
oai.py
View File

@@ -123,6 +123,26 @@ def load_conversation(name: str) -> Optional[List[Dict[str, str]]]:
return json.loads(result[0])
return None
def list_conversations() -> List[Dict[str, Any]]:
"""List all saved conversations from DB with metadata."""
with sqlite3.connect(DB_FILE) as conn:
cursor = conn.execute('''
SELECT name, MAX(timestamp) as last_saved, data
FROM conversation_sessions
GROUP BY name
ORDER BY last_saved DESC
''')
conversations = []
for row in cursor.fetchall():
name, timestamp, data_json = row
data = json.loads(data_json)
conversations.append({
'name': name,
'timestamp': timestamp,
'message_count': len(data)
})
return conversations
def estimate_cost(input_tokens: int, output_tokens: int) -> float:
"""Estimate cost in USD based on token counts."""
return (input_tokens * MODEL_PRICING['input'] / 1_000_000) + (output_tokens * MODEL_PRICING['output'] / 1_000_000)
@@ -314,6 +334,7 @@ def chat():
total_cost = 0.0
message_count = 0
middle_out_enabled = False # Session-level middle-out transform flag
saved_conversations_cache = [] # Cache for /list results to use with /load by number
app_logger.info("Starting new chat session") # Log session start
@@ -431,12 +452,28 @@ def chat():
elif user_input.lower().startswith("/load"):
args = user_input[6:].strip()
if not args:
console.print("[bold red]Usage: /load <name>[/]")
console.print("[bold red]Usage: /load <name|number>[/]")
console.print("[bold yellow]Tip: Use /list to see numbered conversations[/]")
continue
loaded_data = load_conversation(args)
# Check if input is a number
conversation_name = None
if args.isdigit():
conv_number = int(args)
if saved_conversations_cache and 1 <= conv_number <= len(saved_conversations_cache):
conversation_name = saved_conversations_cache[conv_number - 1]['name']
console.print(f"[bold cyan]Loading conversation #{conv_number}: '{conversation_name}'[/]")
else:
console.print(f"[bold red]Invalid conversation number: {conv_number}[/]")
console.print(f"[bold yellow]Use /list to see available conversations (1-{len(saved_conversations_cache) if saved_conversations_cache else 0})[/]")
continue
else:
conversation_name = args
loaded_data = load_conversation(conversation_name)
if not loaded_data:
console.print(f"[bold red]Conversation '{args}' not found.[/]")
app_logger.warning(f"Load failed for '{args}' - not found")
console.print(f"[bold red]Conversation '{conversation_name}' not found.[/]")
app_logger.warning(f"Load failed for '{conversation_name}' - not found")
continue
session_history = loaded_data
current_index = len(session_history) - 1
@@ -444,8 +481,38 @@ def chat():
total_output_tokens = 0
total_cost = 0.0
message_count = 0
console.print(f"[bold green]Conversation '{args}' loaded with {len(session_history)} messages.[/]")
app_logger.info(f"Conversation '{args}' loaded with {len(session_history)} messages")
console.print(f"[bold green]Conversation '{conversation_name}' loaded with {len(session_history)} messages.[/]")
app_logger.info(f"Conversation '{conversation_name}' loaded with {len(session_history)} messages")
continue
elif user_input.lower() == "/list":
conversations = list_conversations()
if not conversations:
console.print("[bold yellow]No saved conversations found.[/]")
app_logger.info("User viewed conversation list - empty")
saved_conversations_cache = []
continue
# Update cache for /load command
saved_conversations_cache = conversations
table = Table("No.", "Name", "Messages", "Last Saved", show_header=True, header_style="bold magenta")
for idx, conv in enumerate(conversations, 1):
# Parse ISO timestamp and format it nicely
try:
dt = datetime.datetime.fromisoformat(conv['timestamp'])
formatted_time = dt.strftime('%Y-%m-%d %H:%M:%S')
except:
formatted_time = conv['timestamp']
table.add_row(
str(idx),
conv['name'],
str(conv['message_count']),
formatted_time
)
console.print(Panel(table, title=f"[bold green]Saved Conversations ({len(conversations)} total)[/]", title_align="left", subtitle="[dim]Use /load <number> or /load <name> to load a conversation[/]", subtitle_align="right"))
app_logger.info(f"User viewed conversation list - {len(conversations)} conversations")
continue
elif user_input.lower() == "/prev":
if not session_history or current_index <= 0:
@@ -775,7 +842,7 @@ def chat():
)
help_table.add_row(
"/clear",
"Clear the terminal screen for a clean interface.",
"Clear the terminal screen for a clean interface. You can also use the keycombo [bold]ctrl+l[/]",
"/clear"
)
help_table.add_row(
@@ -897,9 +964,14 @@ def chat():
"/export md notes.md\n/export html report.html"
)
help_table.add_row(
"/load <name>",
"Load a saved conversation from database. Resets session metrics.",
"/load my_chat"
"/list",
"List all saved conversations with numbers, message counts, and timestamps.",
"/list"
)
help_table.add_row(
"/load <name|number>",
"Load a saved conversation by name or number (from /list). Resets session metrics.",
"/load my_chat\n/load 3"
)
help_table.add_row(
"/save <name>",