Skip to content

Commit fef0731

Browse files
feat: add --resume flag to restore session from .pkl file
- Add `_resume_session_from_path` function that loads message history from any .pkl session file on disk - Add `--resume`/`-r` CLI argument accepting a path to a saved session file - Rotate autosave ID after resuming to prevent overwriting the original session file - Validate file existence and .pkl extension before attempting to load, with clear error messages
1 parent b55899a commit fef0731

1 file changed

Lines changed: 61 additions & 0 deletions

File tree

code_puppy/cli_runner.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,57 @@
4747
plugins.load_plugin_callbacks()
4848

4949

50+
def _resume_session_from_path(raw_path: str) -> None:
51+
"""Restore agent message history from a saved .pkl session file.
52+
53+
Accepts any path (autosaves, contexts, somewhere weird on disk). We don't
54+
care where it lives — we just decompose into (parent_dir, stem) and reuse
55+
``session_storage.load_session`` so we stay DRY.
56+
"""
57+
from code_puppy.agents.agent_manager import get_current_agent
58+
from code_puppy.messaging import emit_error, emit_success
59+
from code_puppy.session_storage import load_session
60+
61+
session_path = Path(raw_path).expanduser().resolve()
62+
63+
if not session_path.exists():
64+
emit_error(f"--resume: session file not found: {session_path}")
65+
sys.exit(1)
66+
67+
if session_path.suffix != ".pkl":
68+
emit_error(
69+
f"--resume: expected a .pkl session file, got '{session_path.suffix}': {session_path}"
70+
)
71+
sys.exit(1)
72+
73+
try:
74+
history = load_session(session_path.stem, session_path.parent)
75+
except Exception as exc:
76+
emit_error(f"--resume: failed to load session: {exc}")
77+
sys.exit(1)
78+
79+
try:
80+
agent = get_current_agent()
81+
agent.set_message_history(history)
82+
except Exception as exc:
83+
emit_error(f"--resume: failed to attach history to agent: {exc}")
84+
sys.exit(1)
85+
86+
# Rotate autosave id so we don't clobber the original file we just resumed.
87+
try:
88+
from code_puppy.config import rotate_autosave_id
89+
90+
rotate_autosave_id()
91+
except Exception:
92+
pass # autosave rotation is best-effort
93+
94+
total_tokens = sum(agent.estimate_tokens_for_message(m) for m in history)
95+
emit_success(
96+
f"✅ Resumed session: {len(history)} messages ({total_tokens} tokens)\n"
97+
f"📁 From: {session_path}"
98+
)
99+
100+
50101
async def main():
51102
"""Main async entry point for Code Puppy CLI."""
52103
parser = argparse.ArgumentParser(description="Code Puppy - A code generation agent")
@@ -81,6 +132,13 @@ async def main():
81132
type=str,
82133
help="Specify which model to use (e.g., --model gpt-5)",
83134
)
135+
parser.add_argument(
136+
"--resume",
137+
"-r",
138+
type=str,
139+
metavar="PATH",
140+
help="Resume a saved session from a .pkl file (e.g. ~/.code_puppy/contexts/foo.pkl)",
141+
)
84142
parser.add_argument(
85143
"command", nargs="*", help="Run a single command (deprecated, use -p instead)"
86144
)
@@ -282,6 +340,9 @@ def _uvx_protective_sigint_handler(_sig, _frame):
282340

283341
await callbacks.on_startup()
284342

343+
if args.resume:
344+
_resume_session_from_path(args.resume)
345+
285346
global shutdown_flag
286347
shutdown_flag = False
287348
try:

0 commit comments

Comments
 (0)