Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 54 additions & 2 deletions code_puppy/cli_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -642,8 +642,60 @@ async def interactive_mode(message_renderer, initial_command: str = None) -> Non
if command_result is True:
continue
elif isinstance(command_result, str):
if command_result == "__AUTOSAVE_LOAD__":
# Handle async autosave loading
if command_result.startswith("__AUTOSAVE_LOAD_DIRECT__:"):
# Handle direct session load by name
session_name = command_result.split(":", 1)[1]
try:
from code_puppy.agents.agent_manager import get_current_agent
from code_puppy.config import (
set_current_autosave_from_session_name,
)
from code_puppy.messaging import emit_error, emit_success
from code_puppy.session_storage import load_session

base_dir = Path(AUTOSAVE_DIR).resolve()
session_path = (base_dir / f"{session_name}.pkl").resolve()

# Security: Prevent path traversal attacks
if (
base_dir not in session_path.parents
and session_path.parent != base_dir
):
emit_error(f"❌ Invalid session name: {session_name}")
emit_info("💡 Use /resume to open the session picker.")
continue

# Check if session exists
if not session_path.exists():
emit_error(f"❌ Session not found: {session_name}")
emit_info("💡 Use /resume to open the session picker.")
continue

# Load the session
history = load_session(session_name, base_dir)

agent = get_current_agent()
agent.set_message_history(history)

# Set current autosave session
set_current_autosave_from_session_name(session_name)

total_tokens = sum(
agent.estimate_tokens_for_message(msg) for msg in history
)

emit_success(
f"✅ Resumed: {session_name}\n"
f"📊 {len(history)} messages ({total_tokens:,} tokens)"
)
except Exception as e:
from code_puppy.messaging import emit_error

emit_error(f"Failed to load session: {e}")
emit_info("💡 Use /resume to open the session picker.")
continue
elif command_result == "__AUTOSAVE_LOAD__":
# Handle async autosave loading (interactive picker)
try:
# Check if we're in a real interactive terminal
# (not pexpect/tests) - interactive picker requires proper TTY
Expand Down
37 changes: 31 additions & 6 deletions code_puppy/command_line/session_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,15 +184,40 @@ def handle_truncate_command(command: str) -> bool:

@register_command(
name="autosave_load",
description="Load an autosave session interactively",
usage="/autosave_load",
description="Load an autosave session interactively, or by name",
usage="/autosave_load [session_name]",
aliases=["resume"],
category="session",
detailed_help="""
Load an autosave session.

Commands:
/resume Open interactive session picker
/resume <session_name> Load session directly by name

Examples:
/resume
/resume auto_session_20260214_175543
""",
)
def handle_autosave_load_command(command: str) -> bool:
"""Load an autosave session."""
# Return a special marker to indicate we need to run async autosave loading
return "__AUTOSAVE_LOAD__"
def handle_autosave_load_command(command: str) -> "bool | str":
"""Load an autosave session.

If no session name is provided, opens interactive picker.
If session name is provided, loads that session directly.

Returns:
"__AUTOSAVE_LOAD__" for picker, "__AUTOSAVE_LOAD_DIRECT__:<name>" for direct load.
"""
tokens = command.split()

if len(tokens) == 1:
# No argument = open picker
return "__AUTOSAVE_LOAD__"

# Session name provided = load directly
session_name = tokens[1]
return f"__AUTOSAVE_LOAD_DIRECT__:{session_name}"


@register_command(
Expand Down
Loading