@@ -213,7 +213,7 @@ func printUsage() {
213213 kode run [flags] <task>
214214 kode run --session [flags] <task>
215215 kode continue [--id <id>] <task>
216- kode session <list|show [id]|delete <id>>
216+ kode session <list|show [id]|trim <id> <n>| delete <id>>
217217 kode init [--global | -g] [--force | -f]
218218 kode version
219219
@@ -869,8 +869,10 @@ func sessionCmd(args []string) error {
869869 return showSession (store , args [1 :])
870870 case "delete" :
871871 return deleteSession (store , args [1 :])
872+ case "trim" :
873+ return trimSession (store , args [1 :])
872874 default :
873- return fmt .Errorf ("unknown session command %q (use list, show, delete)" , args [0 ])
875+ return fmt .Errorf ("unknown session command %q (use list, show, trim, delete)" , args [0 ])
874876 }
875877}
876878
@@ -952,6 +954,64 @@ func deleteSession(store *session.Store, args []string) error {
952954 return nil
953955}
954956
957+ // trimSession keeps only the most recent n messages from a session,
958+ // always preserving the system prompt if present.
959+ // Usage: kode session trim <id> <n>
960+ func trimSession (store * session.Store , args []string ) error {
961+ if len (args ) < 2 {
962+ return fmt .Errorf ("usage: kode session trim <id> <n>" )
963+ }
964+ id := args [0 ]
965+ var n int
966+ if _ , err := fmt .Sscanf (args [1 ], "%d" , & n ); err != nil || n < 2 {
967+ return fmt .Errorf ("n must be at least 2 (system + at least 1 message), got %q" , args [1 ])
968+ }
969+
970+ sess , err := store .Load (id )
971+ if err != nil {
972+ return fmt .Errorf ("load session: %w" , err )
973+ }
974+
975+ originalLen := len (sess .Messages )
976+ if n >= originalLen {
977+ fmt .Printf ("Session %s already has %d messages (≤ %d), nothing to trim.\n " , id , originalLen , n )
978+ return nil
979+ }
980+
981+ // Always keep the system message if it's first
982+ hasSystem := len (sess .Messages ) > 0 && sess .Messages [0 ].Role == "system"
983+
984+ if hasSystem {
985+ // Keep system message + last (n-1) messages
986+ keep := n - 1
987+ if keep > len (sess .Messages )- 1 {
988+ keep = len (sess .Messages ) - 1
989+ }
990+ system := sess .Messages [:1 ]
991+ tail := sess .Messages [len (sess .Messages )- keep :]
992+ sess .Messages = append (system , tail ... )
993+ } else {
994+ // Keep last n messages
995+ sess .Messages = sess .Messages [len (sess .Messages )- n :]
996+ }
997+
998+ // Recompute turn count
999+ sess .Turns = 0
1000+ for _ , m := range sess .Messages {
1001+ if m .Role == "user" {
1002+ sess .Turns ++
1003+ }
1004+ }
1005+
1006+ if err := store .Save (sess ); err != nil {
1007+ return fmt .Errorf ("save session: %w" , err )
1008+ }
1009+
1010+ dropped := originalLen - len (sess .Messages )
1011+ fmt .Printf ("Trimmed session %s: %d → %d messages (%d dropped)\n " , id , originalLen , len (sess .Messages ), dropped )
1012+ return nil
1013+ }
1014+
9551015// countUserTurnsUpTo counts user messages up to (but not including) index n.
9561016func countUserTurnsUpTo (messages []llm.Message , n int ) int {
9571017 count := 0
0 commit comments