fix: #166 — flush-transcript now accepts --directory / --output-format / --session-id; session-creation command parity with #160/#165 lifecycle triplet

This commit is contained in:
YeonGyu-Kim
2026-04-22 18:04:25 +09:00
parent 178c8fac28
commit 85de7f9814
4 changed files with 338 additions and 6 deletions

View File

@@ -81,8 +81,24 @@ def build_parser() -> argparse.ArgumentParser:
),
)
flush_parser = subparsers.add_parser('flush-transcript', help='persist and flush a temporary session transcript')
flush_parser = subparsers.add_parser(
'flush-transcript',
help='persist and flush a temporary session transcript (#160/#166: claw-native session API)',
)
flush_parser.add_argument('prompt')
flush_parser.add_argument(
'--directory', help='session storage directory (default: .port_sessions)'
)
flush_parser.add_argument(
'--output-format',
choices=['text', 'json'],
default='text',
help='output format',
)
flush_parser.add_argument(
'--session-id',
help='deterministic session ID (default: auto-generated UUID)',
)
load_session_parser = subparsers.add_parser(
'load-session',
@@ -232,11 +248,29 @@ def main(argv: list[str] | None = None) -> int:
return 2
return 0
if args.command == 'flush-transcript':
from pathlib import Path as _Path
engine = QueryEnginePort.from_workspace()
# #166: allow deterministic session IDs for claw checkpointing/replay.
# When unset, the engine's auto-generated UUID is used (backward compat).
if args.session_id:
engine.session_id = args.session_id
engine.submit_message(args.prompt)
path = engine.persist_session()
print(path)
print(f'flushed={engine.transcript_store.flushed}')
directory = _Path(args.directory) if args.directory else None
path = engine.persist_session(directory)
if args.output_format == 'json':
import json as _json
print(_json.dumps({
'session_id': engine.session_id,
'path': path,
'flushed': engine.transcript_store.flushed,
'messages_count': len(engine.mutable_messages),
'input_tokens': engine.total_usage.input_tokens,
'output_tokens': engine.total_usage.output_tokens,
}))
else:
# #166: legacy text output preserved byte-for-byte for backward compat.
print(path)
print(f'flushed={engine.transcript_store.flushed}')
return 0
if args.command == 'load-session':
from pathlib import Path as _Path

View File

@@ -153,7 +153,19 @@ class QueryEnginePort:
def flush_transcript(self) -> None:
self.transcript_store.flush()
def persist_session(self) -> str:
def persist_session(self, directory: 'Path | None' = None) -> str:
"""Flush the transcript and save the session to disk.
Args:
directory: Optional override for the storage directory. When None
(default, for backward compat), uses the default location
(``.port_sessions`` in CWD). When set, passes through to
``save_session`` which already supports directory overrides.
#166: added directory parameter to match the session-lifecycle CLI
surface established by #160/#165. Claws running out-of-tree can now
redirect session creation to a workspace-specific dir without chdir.
"""
self.flush_transcript()
path = save_session(
StoredSession(
@@ -161,7 +173,8 @@ class QueryEnginePort:
messages=tuple(self.mutable_messages),
input_tokens=self.total_usage.input_tokens,
output_tokens=self.total_usage.output_tokens,
)
),
directory,
)
return str(path)