Coverage for cli / commands / session.py: 18%

74 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-03-29 02:55 +0800

1""" 

2/session 命令处理模块 

3""" 

4from rich.console import Console 

5from rich.table import Table 

6from qrclaw.memory.session import Session, list_sessions, delete_session 

7from qrclaw.workspace import Workspace 

8from qrclaw.logger import setup_logger 

9from qrclaw.config import LOG_LEVEL, LOG_MAX_DAYS, LOG_TO_FILE, LOG_TO_CONSOLE, LOG_CONSOLE_LEVEL 

10 

11 

12def handle(args: str, current_session: Session, console: Console, workspace: Workspace) -> Session: 

13 """ 

14 处理 /session 子命令,返回(可能切换后的)Session。 

15 

16 子命令: 

17 list 列出当前 agent 的所有会话 

18 new [id] 新建并切换(不传 id 则自动生成) 

19 switch <id> 切换到已有会话 

20 delete <id> 删除指定会话 

21 """ 

22 parts = args.strip().split(maxsplit=1) 

23 

24 if not parts or not parts[0]: 

25 _print_help(console) 

26 return current_session 

27 

28 subcommand = parts[0] 

29 sub_args = parts[1].strip() if len(parts) > 1 else "" 

30 

31 if subcommand == "list": 

32 return _cmd_list(current_session, console, workspace) 

33 elif subcommand == "new": 

34 return _cmd_new(sub_args, current_session, console, workspace) 

35 elif subcommand == "switch": 

36 return _cmd_switch(sub_args, current_session, console, workspace) 

37 elif subcommand == "delete": 

38 return _cmd_delete(sub_args, current_session, console, workspace) 

39 else: 

40 console.print(f"[red]未知子命令: {subcommand}[/red]") 

41 _print_help(console) 

42 return current_session 

43 

44 

45def _cmd_list(current_session: Session, console: Console, workspace: Workspace) -> Session: 

46 sessions = list_sessions(workspace.sessions_dir) 

47 if not sessions: 

48 console.print("[yellow]没有已保存的会话[/yellow]") 

49 return current_session 

50 

51 table = Table(title=f"会话列表 (agent: {workspace.agent_id})") 

52 table.add_column("会话 ID", style="cyan") 

53 table.add_column("消息数", style="green", justify="right") 

54 table.add_column("最后更新", style="dim") 

55 table.add_column("", style="bold yellow") 

56 

57 for s in sessions: 

58 marker = "← 当前" if s["id"] == current_session.session_id else "" 

59 table.add_row(s["id"], str(s["message_count"]), s["updated_at"], marker) 

60 

61 console.print(table) 

62 return current_session 

63 

64 

65def _cmd_new(session_id: str, current_session: Session, console: Console, workspace: Workspace) -> Session: 

66 _reinit_logger(session_id or None, workspace) 

67 # 关键修复:必须传入 resume=False,否则会恢复最近的会话 

68 new_session = Session(sessions_dir=workspace.sessions_dir, session_id=session_id or None, resume=False) 

69 console.print(f"[bold cyan]已新建并切换到会话: {new_session.session_id}[/bold cyan]") 

70 return new_session 

71 

72 

73def _cmd_switch(session_id: str, current_session: Session, console: Console, workspace: Workspace) -> Session: 

74 if not session_id: 

75 console.print("[red]用法: /session switch <会话ID>[/red]") 

76 return current_session 

77 

78 _reinit_logger(session_id, workspace) 

79 target = Session(sessions_dir=workspace.sessions_dir, session_id=session_id) 

80 msg = f"已切换到会话: {session_id}" 

81 if target.messages: 

82 msg += f"{len(target.messages)} 条历史消息)" 

83 console.print(f"[bold cyan]{msg}[/bold cyan]") 

84 return target 

85 

86 

87def _cmd_delete(session_id: str, current_session: Session, console: Console, workspace: Workspace) -> Session: 

88 if not session_id: 

89 console.print("[red]用法: /session delete <会话ID>[/red]") 

90 return current_session 

91 

92 if session_id == current_session.session_id: 

93 console.print("[red]不能删除当前正在使用的会话,请先切换到其他会话[/red]") 

94 return current_session 

95 

96 if delete_session(session_id, workspace.sessions_dir): 

97 console.print(f"[dim]会话 {session_id} 已删除[/dim]") 

98 else: 

99 console.print(f"[yellow]会话 {session_id} 不存在[/yellow]") 

100 

101 return current_session 

102 

103 

104def _reinit_logger(session_id: str | None, workspace: Workspace) -> None: 

105 setup_logger( 

106 session_id=session_id or "tmp", 

107 log_level=LOG_LEVEL, 

108 log_to_file=LOG_TO_FILE, 

109 log_to_console=LOG_TO_CONSOLE, 

110 log_max_days=LOG_MAX_DAYS, 

111 console_level=LOG_CONSOLE_LEVEL, 

112 log_dir=workspace.logs_dir, 

113 ) 

114 

115 

116def _print_help(console: Console) -> None: 

117 console.print("[dim]用法: /session <list|new|switch|delete> [会话ID][/dim]") 

118 console.print("[dim] list 列出所有会话[/dim]") 

119 console.print("[dim] new [id] 新建会话(不传 id 则自动生成)[/dim]") 

120 console.print("[dim] switch <id> 切换会话[/dim]") 

121 console.print("[dim] delete <id> 删除会话[/dim]")