From b8504fc5a4882e932ffa35f08e5d97ed8be4d3bc Mon Sep 17 00:00:00 2001 From: Chris Guidry Date: Mon, 30 Mar 2026 09:04:38 -0400 Subject: [PATCH] Clean up spacing between narrative text and tool notifications MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tool notifications had leading/trailing \n baked in, and the CLI added more on top — stacking up to 3-4 blank lines between a prompt and the DM's first output. Now the engine returns bare `[Label...]` strings and the CLI handles all spacing: one blank line between the rule and the response, one blank line separating text from tool groups, and leading newlines from Claude's stream are stripped so the gap is consistent. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/storied/cli.py | 17 +++++++++++------ src/storied/engine.py | 6 +++--- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/storied/cli.py b/src/storied/cli.py index f230888..3d00387 100644 --- a/src/storied/cli.py +++ b/src/storied/cli.py @@ -488,21 +488,26 @@ def cmd_play(args: argparse.Namespace) -> int: try: console.print(Rule(style="dim blue")) - console.print() # Blank line before DM response renderer = StreamRenderer(console) prev_type: str | None = None + got_text = False for chunk in engine.stream_action(action): - if chunk.startswith("\n[") or chunk.startswith("Rolled "): - if prev_type != "tool": + if chunk.startswith("[") and chunk.endswith("]") and "..." in chunk: + if prev_type == "text": renderer.flush() - console.file.write("\n") - console.print() - console.print(f"[dim]{chunk.strip()}[/dim]") + console.file.write("\n\n") + console.print(f"[dim]{chunk}[/dim]") prev_type = "tool" else: if prev_type == "tool": console.print() + if not got_text: + chunk = chunk.lstrip("\n") + if not chunk: + continue + chunk = "\n" + chunk + got_text = True renderer.feed(chunk) prev_type = "text" diff --git a/src/storied/engine.py b/src/storied/engine.py index 93a42dd..9e2540e 100644 --- a/src/storied/engine.py +++ b/src/storied/engine.py @@ -73,7 +73,7 @@ def _tool_notification(name: str) -> str: "end_initiative": "Ending initiative", } label = labels.get(short, short) - return f"\n[{label}...]\n" + return f"[{label}...]" class DMEngine: @@ -435,7 +435,7 @@ class DMEngine: if short == "roll" and not self.debug: deferred_notification = True elif self.debug: - yield f"\n[→ {short}(...)]\n" + yield f"[→ {short}(...)]" deferred_notification = False else: yield _tool_notification(name) @@ -448,7 +448,7 @@ class DMEngine: if deferred_notification and current_tool_name == "roll": reason = _extract_roll_reason(current_tool_json) label = f"Rolling {reason}" if reason else "Rolling" - yield f"\n[{label}...]\n" + yield f"[{label}...]" if self.debug and current_tool_json: truncated = current_tool_json[:200] -- 2.51.2