@@ -240,6 +240,140 @@ def get_buddy_config(config: Optional[Dict[str, Any]] = None) -> Dict[str, str]:
240240}
241241
242242
243+ # One-line session summary templates by language (#1036)
244+ ONE_LINE_TEMPLATES : Dict [str , Dict [str , str ]] = {
245+ "en" : {
246+ "files_and_commands" : "{files} {file_word} modified · {commands} commands run" ,
247+ "files_only" : "{files} {file_word} modified" ,
248+ "commands_only" : "{commands} commands run" ,
249+ "exploration" : "Codebase exploration ({reads} files read)" ,
250+ "minimal" : "{tools} tool calls" ,
251+ "agent_prefix" : "{agent}: " ,
252+ },
253+ "ko" : {
254+ "files_and_commands" : "파일 {files}개 수정 · 명령어 {commands}개 실행" ,
255+ "files_only" : "파일 {files}개 수정" ,
256+ "commands_only" : "명령어 {commands}개 실행" ,
257+ "exploration" : "코드베이스 탐색 (파일 {reads}개 읽음)" ,
258+ "minimal" : "도구 {tools}회 호출" ,
259+ "agent_prefix" : "{agent}: " ,
260+ },
261+ "ja" : {
262+ "files_and_commands" : "ファイル{files}件変更 · コマンド{commands}件実行" ,
263+ "files_only" : "ファイル{files}件変更" ,
264+ "commands_only" : "コマンド{commands}件実行" ,
265+ "exploration" : "コードベース探索 (ファイル{reads}件読取)" ,
266+ "minimal" : "ツール{tools}回呼出" ,
267+ "agent_prefix" : "{agent}: " ,
268+ },
269+ "zh" : {
270+ "files_and_commands" : "修改了{files}个文件 · 执行了{commands}个命令" ,
271+ "files_only" : "修改了{files}个文件" ,
272+ "commands_only" : "执行了{commands}个命令" ,
273+ "exploration" : "代码库探索 (读取了{reads}个文件)" ,
274+ "minimal" : "调用了{tools}次工具" ,
275+ "agent_prefix" : "{agent}: " ,
276+ },
277+ "es" : {
278+ "files_and_commands" : "{files} {file_word} modificados · {commands} comandos ejecutados" ,
279+ "files_only" : "{files} {file_word} modificados" ,
280+ "commands_only" : "{commands} comandos ejecutados" ,
281+ "exploration" : "Exploración del código ({reads} archivos leídos)" ,
282+ "minimal" : "{tools} llamadas de herramientas" ,
283+ "agent_prefix" : "{agent}: " ,
284+ },
285+ "pt" : {
286+ "files_and_commands" : "{files} {file_word} modificados · {commands} comandos executados" ,
287+ "files_only" : "{files} {file_word} modificados" ,
288+ "commands_only" : "{commands} comandos executados" ,
289+ "exploration" : "Exploração do código ({reads} arquivos lidos)" ,
290+ "minimal" : "{tools} chamadas de ferramentas" ,
291+ "agent_prefix" : "{agent}: " ,
292+ },
293+ "de" : {
294+ "files_and_commands" : "{files} {file_word} geändert · {commands} Befehle ausgeführt" ,
295+ "files_only" : "{files} {file_word} geändert" ,
296+ "commands_only" : "{commands} Befehle ausgeführt" ,
297+ "exploration" : "Codebase-Erkundung ({reads} Dateien gelesen)" ,
298+ "minimal" : "{tools} Toolaufrufe" ,
299+ "agent_prefix" : "{agent}: " ,
300+ },
301+ "fr" : {
302+ "files_and_commands" : "{files} {file_word} modifiés · {commands} commandes exécutées" ,
303+ "files_only" : "{files} {file_word} modifiés" ,
304+ "commands_only" : "{commands} commandes exécutées" ,
305+ "exploration" : "Exploration du code ({reads} fichiers lus)" ,
306+ "minimal" : "{tools} appels d'outils" ,
307+ "agent_prefix" : "{agent}: " ,
308+ },
309+ }
310+
311+ # Singular/plural file word by language
312+ _FILE_WORDS : Dict [str , Dict [str , str ]] = {
313+ "en" : {"one" : "file" , "many" : "files" },
314+ "es" : {"one" : "archivo" , "many" : "archivos" },
315+ "pt" : {"one" : "arquivo" , "many" : "arquivos" },
316+ "de" : {"one" : "Datei" , "many" : "Dateien" },
317+ "fr" : {"one" : "fichier" , "many" : "fichiers" },
318+ }
319+
320+
321+ def generate_one_line_summary (
322+ tool_names : Dict [str , int ],
323+ agent_name : str ,
324+ language : str ,
325+ ) -> str :
326+ """Generate a one-line session summary from tool usage data.
327+
328+ Analyzes tool_names to determine activity type and generates a
329+ human-readable one-line summary with multi-language support.
330+
331+ Args:
332+ tool_names: Dict mapping tool name to usage count
333+ (e.g. {"Edit": 5, "Bash": 10, "Read": 20}).
334+ agent_name: Active agent name, empty string if none.
335+ language: Language code (en, ko, ja, zh, es, pt, de, fr).
336+
337+ Returns:
338+ One-line summary string.
339+ """
340+ templates = ONE_LINE_TEMPLATES .get (language , ONE_LINE_TEMPLATES ["en" ])
341+
342+ files_changed = tool_names .get ("Edit" , 0 ) + tool_names .get ("Write" , 0 )
343+ commands_run = tool_names .get ("Bash" , 0 )
344+ reads = tool_names .get ("Read" , 0 ) + tool_names .get ("Grep" , 0 ) + tool_names .get ("Glob" , 0 )
345+ total_tools = sum (tool_names .values ())
346+
347+ # Determine file word (singular/plural) for languages that need it
348+ file_words = _FILE_WORDS .get (language , _FILE_WORDS .get ("en" , {"one" : "file" , "many" : "files" }))
349+ file_word = file_words ["one" ] if files_changed == 1 else file_words ["many" ]
350+
351+ # Select appropriate template
352+ if files_changed > 0 and commands_run > 0 :
353+ summary = templates ["files_and_commands" ].format (
354+ files = files_changed , file_word = file_word , commands = commands_run ,
355+ )
356+ elif files_changed > 0 :
357+ summary = templates ["files_only" ].format (
358+ files = files_changed , file_word = file_word ,
359+ )
360+ elif commands_run > 0 :
361+ summary = templates ["commands_only" ].format (commands = commands_run )
362+ elif reads > 0 :
363+ summary = templates ["exploration" ].format (reads = reads )
364+ elif total_tools > 0 :
365+ summary = templates ["minimal" ].format (tools = total_tools )
366+ else :
367+ summary = templates ["minimal" ].format (tools = 0 )
368+
369+ # Prepend agent name if available
370+ if agent_name :
371+ prefix = templates ["agent_prefix" ].format (agent = agent_name )
372+ summary = prefix + summary
373+
374+ return summary
375+
376+
243377def _get_greeting (tone : str , language : str ) -> str :
244378 """Get greeting message for given tone and language."""
245379 tone_greetings = GREETINGS .get (tone , GREETINGS ["casual" ])
@@ -369,6 +503,7 @@ def render_session_summary(
369503 tone : str ,
370504 language : str ,
371505 buddy_config : Optional [Dict [str , str ]] = None ,
506+ tool_names : Optional [Dict [str , int ]] = None ,
372507) -> str :
373508 """Render session summary with buddy character for stop hook.
374509
@@ -382,6 +517,8 @@ def render_session_summary(
382517 tone: 'casual' or 'formal'
383518 language: Language code (en, ko, ja, zh, es)
384519 buddy_config: Optional buddy customization from get_buddy_config().
520+ tool_names: Optional dict of tool name to usage count for
521+ one-line summary generation (#1036).
385522
386523 Returns:
387524 Formatted session summary string.
@@ -426,6 +563,13 @@ def render_session_summary(
426563
427564 parts .append (" \u2502 " .join (stat_items ))
428565
566+ # One-line session summary (#1036)
567+ if tool_names :
568+ agent_name = agents [0 ]["name" ] if agents else ""
569+ one_line = generate_one_line_summary (tool_names , agent_name , language )
570+ if one_line :
571+ parts .append (f"\U0001f4ac { one_line } " )
572+
429573 # Active agents section
430574 if agents :
431575 header = _get_summary_header ("agents" , language )
0 commit comments