Skip to main content

A prompt_toolkit extension that adds a thinking box above the prompt

Project description

thinking-prompt

A prompt_toolkit extension that adds a "thinking box" above the prompt for displaying AI thinking/processing content with real-time streaming updates.

Demo

Features

  • Thinking Box: A collapsible area above the prompt that shows processing/thinking content
  • Real-time Streaming: Content updates in real-time as your callback returns new content
  • Fullscreen Mode: Optional fullscreen mode with chat history (disabled by default)
  • Animated Separator: Configurable animated indicator showing thinking is in progress
  • Rich Output: Support for markdown rendering and syntax-highlighted code blocks
  • Rich/ANSI in Thinking Box: Use Rich markup for styled, in-place-updating content inside the thinking box
  • Customizable Styles: Full control over colors and styling

Installation

pip install thinking-prompt

For markdown and code highlighting support:

pip install thinking-prompt[all]

Quick Start

import asyncio
from thinking_prompt import ThinkingPromptSession, AppInfo

async def main():
    app_info = AppInfo(name="MyApp", version="1.0.0")
    session = ThinkingPromptSession(app_info=app_info, message=">>> ")

    @session.on_input
    async def handle(text: str):
        if not text.strip():
            return

        # Use context manager for clean thinking management
        async with session.thinking() as content:
            content.append("Processing...\n")
            await asyncio.sleep(0.5)
            content.append("Done!\n")

        session.add_response(f"You said: {text}")

    await session.run_async()

if __name__ == "__main__":
    asyncio.run(main())

Key Bindings

Key Action
Ctrl+T Expand/collapse thinking box (in prompt mode)
Ctrl+E Toggle fullscreen mode (when enabled)
Ctrl+C Cancel current operation or exit
Ctrl+D Exit application

API Reference

ThinkingPromptSession

The main class for creating a thinking-enabled prompt session.

session = ThinkingPromptSession(
    message=">>> ",              # Prompt message
    app_info=AppInfo(...),       # App metadata and configuration
    max_thinking_height=15,      # Max lines when collapsed
    enable_status_bar=True,      # Show status bar
    echo_input=True,             # Echo user input to console
    complete_while_typing=True,  # Show completions as you type
    completions_menu_height=6,   # Max rows in completions popup
)

Thinking API

Context Manager (recommended):

async with session.thinking() as content:
    content.append("Step 1...\n")
    await asyncio.sleep(0.5)
    content.append("Step 2...\n")
# Automatically finishes when exiting context

Manual control:

# Start with a content callback
chunks = []
session.start_thinking(lambda: ''.join(chunks))

chunks.append("Processing...\n")
await asyncio.sleep(0.5)

# Finish and optionally echo to console
session.finish_thinking(add_to_history=True, echo_to_console=True)

Rich/ANSI Content in Thinking Box

Use append_rich() and set_line_rich() for styled content with Rich markup:

async with session.thinking(title="Processing") as ctx:
    ctx.append_rich("[dim]  ○ Load data[/dim]\n")
    ctx.append_rich("[dim]  ○ Transform[/dim]\n")

    ctx.set_line_rich(0, "[bold cyan]  ⟳ Load data…[/bold cyan]")
    ctx.set_title("Loading")
    await asyncio.sleep(1)
    ctx.set_line_rich(0, "[green]  ✓ Load data[/green]")

    ctx.set_line_rich(1, "[bold cyan]  ⟳ Transform…[/bold cyan]")
    ctx.set_title("Transforming")
    await asyncio.sleep(1)
    ctx.set_line_rich(1, "[green]  ✓ Transform[/green]")

Dynamic Titles & In-Place Updates

Use set_title() to change the thinking box title and set_line() to update lines in place:

async with session.thinking(title="Downloading") as ctx:
    ctx.append("Progress: 0%\n")
    for i in range(1, 101):
        ctx.set_line(-1, f"Progress: {i}%")
        ctx.set_title(f"Downloading {i}%")
        await asyncio.sleep(0.02)

Output Methods

# Plain text response
session.add_response("Hello, world!")

# Markdown (requires rich)
session.add_response("# Title\n- Item 1\n- Item 2", markdown=True)

# Syntax-highlighted code (requires pygments)
session.add_code("def hello(): return 'world'", language="python")

# Status bar text
session.set_status("Ready")                    # Plain text
session.set_status("[bold]Processing[/bold]")  # Rich markup

# Status messages
session.add_success("Operation completed")
session.add_warning("Rate limit approaching")
session.add_error("Connection failed")
session.add_message("system", "Connecting to server...")

Dialogs

# Yes/No confirmation
result = await session.yes_no_dialog("Confirm", "Delete this item?")
if result:
    # User clicked Yes

# Message dialog
await session.message_dialog("Info", "Operation completed!")

# Choice dialog (multiple buttons)
action = await session.choice_dialog("Action", "What to do?", ["Save", "Discard", "Cancel"])

# Dropdown selection
theme = await session.dropdown_dialog("Theme", "Choose:", ["Light", "Dark", "System"])

# Custom dialog
from thinking_prompt import DialogConfig, ButtonConfig
config = DialogConfig(
    title="Custom",
    body="Choose an option:",
    buttons=[
        ButtonConfig(text="Option A", result="a"),
        ButtonConfig(text="Option B", result="b"),
    ],
)
result = await session.show_dialog(config)

Settings Dialog

A form-based dialog for configuring multiple settings at once:

from thinking_prompt.settings_dialog import (
    SettingsDialog,
    DropdownItem,
    InlineSelectItem,
    TextItem,
    CheckboxItem,
)

items = [
    DropdownItem(
        key="theme",
        label="Theme",
        description="Application color scheme",
        options=["Light", "Dark", "System"],
        default="System",
    ),
    InlineSelectItem(
        key="font_size",
        label="Font Size",
        options=["Small", "Medium", "Large"],
        default="Medium",
    ),
    TextItem(
        key="username",
        label="Username",
        default="Guest",
    ),
    TextItem(
        key="api_key",
        label="API Key",
        password=True,
    ),
    CheckboxItem(
        key="notifications",
        label="Enable Notifications",
        description="Show desktop notifications",
        default=True,
    ),
]

dialog = SettingsDialog(title="Settings", items=items)
result = await session.show_dialog(dialog)

if result:
    # result is a dict of changed values only
    for key, value in result.items():
        print(f"{key}: {value}")

Control Types:

Control Description Navigation
DropdownItem Expandable dropdown list with indicator Enter to open, Up/Down to select, Enter to confirm
InlineSelectItem Inline cycling with / indicators Left/Right to cycle through options
TextItem Text input (optional password masking) Enter to edit, Enter/Escape to confirm/cancel
CheckboxItem Boolean toggle (true/false) Space/Enter/Left/Right to toggle

Navigation: Up/Down moves between controls, Tab cycles through controls and buttons, Ctrl+S saves.

AppInfo Configuration

app_info = AppInfo(
    name="MyApp",
    version="1.0.0",
    welcome_message="Welcome to MyApp!",  # Optional custom welcome

    # Key bindings
    fullscreen_key="c-e",        # Ctrl+E for fullscreen
    expand_key="c-t",            # Ctrl+T for expand/collapse

    # Feature flags
    fullscreen_enabled=False,    # Enable fullscreen mode
    echo_thinking=True,          # Echo thinking to console after completion

    # Thinking animation
    thinking_text="Thinking",    # Text in separator
    thinking_animation=("⠋", "⠙", "⠹", ...),  # Animation frames
    thinking_animation_position="before",      # "before" or "after" text
)

Examples

See the examples/ directory for complete demos:

  • basic.py - Simple thinking box usage
  • demo.py - Interactive demo with simulated AI thinking
  • streaming.py - Character-by-character streaming
  • progress_demo.py - Progress bar with callback
  • demo_progress_line.py - In-place progress updates
  • demo_messages_during_thinking.py - Output messages during thinking
  • demo_animated_separator.py - Different animation configurations
  • dialog_test.py - Dialog system demo (yes/no, message, choice, dropdown)
  • settings_dialog_demo.py - Settings dialog with all control types
  • demo_showcase.py - Feature showcase for demos and screenshots
  • demo_task_progress.py - Rich-styled task progress with in-place status updates
  • completer_demo.py - Slash-command autocompletion (like Claude Code)

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

thinking_prompt-0.2.5.tar.gz (978.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

thinking_prompt-0.2.5-py3-none-any.whl (47.7 kB view details)

Uploaded Python 3

File details

Details for the file thinking_prompt-0.2.5.tar.gz.

File metadata

  • Download URL: thinking_prompt-0.2.5.tar.gz
  • Upload date:
  • Size: 978.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for thinking_prompt-0.2.5.tar.gz
Algorithm Hash digest
SHA256 e8c1e1d09533d822582d065f2bc92435d372dd7277d385bd7a2d248ba68c063d
MD5 e9b610fa8b05fbefcfedad63fa21cc0c
BLAKE2b-256 efb5e09c7064b657940a478ec4a41fd86ea66073bcdfa94c9c928350a392d077

See more details on using hashes here.

File details

Details for the file thinking_prompt-0.2.5-py3-none-any.whl.

File metadata

File hashes

Hashes for thinking_prompt-0.2.5-py3-none-any.whl
Algorithm Hash digest
SHA256 1e26ed781c222fbb7b5779becaad5ee44f8bc6f3c2007d51fce4c4d260f87091
MD5 1a66741ebece5fff440b5dbe2a17ddab
BLAKE2b-256 80cb40b0d7c5fb931fd453da31e001e87cfccaf48364373e3c300696159b407c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page