Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ GitHub Releases page; `0.8.0` is the new starting line.

## Unreleased

- Reduce the shell prompt session to a compatibility façade over deep `prompting/` modules (config, keybindings, completion menus, narrow shell-facing methods), with Unicode cell-width coverage and documented module ownership in the architecture guide.
- Render image/audio/video and unknown content parts as payload-free labels in the live view, roll nested subagent activity (up to 16 levels) under the correct root tool card, and stop provider-remapped tool results from starting replay user turns.
- **Behavior change:** `!` shell commands now run through the detected configured shell (`<shell> -c`, PowerShell `-command` on Windows) instead of the implicit `/bin/sh`/`cmd.exe`, with separate 1 MiB stdout/stderr caps and cancellation cleanup; existing `cmd.exe`-syntax commands on Windows may need updating.
- Distinguish background auto-trigger grace expiry from user input activity with typed prompt events, and bound streamed tool-argument label scans to 1 KiB growth boundaries.
Expand Down
27 changes: 27 additions & 0 deletions docs/en/customization/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,33 @@ events include `StepBegin`, `StepRetry`, `StepInterrupted`, `ToolExecutionStarte
The shell can run with a working directory inside its subtree, so `src/pythinker_code/ui/`
is a candidate for a focused nested guide on prompt, visualization, and component layout.

### Shell prompt deep modules

`src/pythinker_code/ui/shell/prompt.py` is a compatibility façade: it keeps the public
`CustomPromptSession` surface and re-exports legacy underscore helper names, while the
implementation lives in the `src/pythinker_code/ui/shell/prompting/` deep modules.

| Path | Owns |
| --- | --- |
| `prompting/frame.py` | One-frame snapshot flow: `PromptFrameCollector` samples every render delegate exactly once per frame into an immutable `PromptFrame`. |
| `prompting/state.py` | Reducer-style prompt state: UI events flow through the reducer; render code reads state, never mutates it. |
| `prompting/lifecycle.py` | Async task ownership and closers: startup/shutdown symmetry for session-owned background tasks. |
| `prompting/renderer.py` | Scene row allocation and rendering within the terminal height/width budget (cell-width measured). |
| `prompting/footer.py` | `FooterViewModel` plus content precedence and cell-width truncation, consumed by both toolbar adapters (pythinker and card styles). |
| `prompting/toasts.py`, `git_status.py`, `history.py`, `clipboard.py` | Session-owned resources: toast queue, Git status snapshots, prompt history persistence, clipboard integration. |
| `prompting/config.py` | `PromptConfig` / `PromptProviders`: constructor-time wiring of callbacks and providers. |
| `prompting/keybindings.py` | `build_prompt_key_bindings` over the `PromptController` protocol. |
| `prompting/completion/` | Canonical `CompletionContext`, slash-command completion, workspace-indexed `@` file mentions, and completion menus. |

Workspace and Git snapshots publish asynchronously under a generation counter: each refresh
owns its generation, and results from a superseded generation are discarded rather than
rendered stale.

Compatibility policy: legacy underscore helper names re-exported from `prompt.py` delegate to
the session modules and remain import-compatible, but private implementation helpers are not
supported extension interfaces and may change without notice; extend via the documented
public surfaces (`CustomPromptSession`, `PromptConfig`/`PromptProviders`, tool renderers).

## ACP server

| Path | Purpose | Key entry points and interfaces |
Expand Down
5 changes: 2 additions & 3 deletions src/pythinker_code/ui/shell/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2081,8 +2081,7 @@ def _maybe_present_pending_approvals(self) -> None:
def _get_default_buffer_text_and_cursor(self) -> tuple[str, int]:
if self._prompt_session is None:
return "", 0
buf = self._prompt_session._session.default_buffer # pyright: ignore[reportPrivateUsage]
return buf.text, buf.cursor_position
return self._prompt_session.input_state()

def _activate_prompt_approval_modal(self) -> None:
if self._prompt_session is None:
Expand All @@ -2101,7 +2100,7 @@ def _activate_prompt_approval_modal(self) -> None:
current_request,
on_response=self._handle_prompt_approval_response,
buffer_state_provider=self._get_default_buffer_text_and_cursor,
text_expander=self._prompt_session._get_placeholder_manager().serialize_for_history, # pyright: ignore[reportPrivateUsage]
text_expander=self._prompt_session.serialize_for_history,
)
self._prompt_session.attach_modal(self._approval_modal)
else:
Expand Down
Loading
Loading