Skip to content

Sessions

Persistent Sessions and Resume

In this PRD, we will outline the expected behavior of persistent sessions and resume feature.

Persistent Sessions

  1. Currently, Keen Code doesn't support persistent sessions. This is a major limitation for the tool. The conversation history is lost when the tool is closed. We want to support persistent sessions so that the conversation history is saved and can be resumed later. How can we achieve this? Share some ideas and then we will discuss the best approach.
  2. We actually want to show the full REPL state when users resume a session, including tool calls, interrupted messages but skipping permission prompts. Then when user sends a new message to that session, we create the AppState from the user's and assistant's messages only, and send them to the LLMs. What do you think?
  3. The problem with compaction is that Keen doesn't render the compacted content in the UI.
  4. Okay based on our discussion, we have the following requirements for persistent sessions:
    • Every session is saved in ~/.keen/sessions/working-dir/timestamp-session-id/ folder
    • working-dir will be the full path of the working directory separated by - instead of /
    • A small hash of the working directory will be appended to the working-dir to make it unique
    • session-id is a UUID generated by the system
    • timestamp is the timestamp of the session creation
    • A session is only created when there is at least one message in the conversation history
    • Users can use the command /sessions to list all sessions and let users choose one to resume
      • It will only list sessions that were created for the current working directory
      • Users can select a session to resume by navigating with arrow keys and pressing enter
      • The list of the sessions will be displayed based on the last updated timestamp, so the most recent session will be at the top
      • Each item in the list will have the following information:
        • Created at timestamp
        • Updated at timestamp
        • Partially the first message of the session
    • When a session is resumed, the full REPL state will be shown. It will include:
      • All the user and assistant messages
      • All the tool interactions
      • Thinking tokens if the model has it
      • Diffs
      • Bash commands and outputs
      • Compaction status (if any)
    • The resumed session will NOT save the following information:
      • Provider and model: These will be the current ones
      • Context status: It will be calculated based on the current messages and model
      • Permission prompts: These will be skipped
    • Each session will have one file saved in the session folder:
      • transcript_events.jsonl: A JSONL file that contains all the events in the session
        • The events in the file should be strictly chronologically ordered
        • This file will be used to resume the session and render the full REPL state
        • This file will also be used to build the context that gets sent to the LLM when the user sends a new message to the session
        • If there was a compaction, the file will contain the compaction event and the compacted content
  5. Ok great. Let's create an RFC for the design. In the RFC, outline the solution first. Then add a concrete implementation plan along with a todo list with granular items of work. For unclear parts, use your best judgement. Save the RFC as @.ai-interactions/outputs/phase-5/output-2_sessions-rfc.md.
  6. Based on the implementation plan and the todo list, let's implement the feature step by step. Make sure to create the necessary files and packages along the way. Do not make an existing file too long or too complex. Keep idiomatic Go code in mind.
  7. There are both assistant_segment and assistant_message. This is redundant. How can we simplify this?
  8. In which case currently assistant_segment and assistant_message are different? In the log, it seems they are the same. Check the log in ~/.keen/sessions/
  9. Since we don't need separate assistant_segment and assistant_message, how can we simplify the approach and avoid the redundancy? Explain.
  10. Okay now let's implement the new assistant_turn event replacing assistant_segment and assistant_message, as you suggested. Refactor the existing implementation accordingly.
  11. The function replayLoadedSession is too big. Let's refactor it.
  12. We still have AssistantSegment in internal/session/event.go. We don't need it anymore. Let's remove it even though it will break past conversations.
  13. Review the code you have written and make sure we have unit tests for important parts of the code.
  14. We don't need to have timestamp in the directory name for sessions. Only UUID is enough. Refactor the code accordingly.