Skip to main content

A streaming terminal REPL for any agent.

Project description

partnuh

A streaming terminal REPL for any agent.

partnuh gives an existing agent — smolagents, an OpenAI-compatible chat model, or anything you can wrap — a fast, multi-line terminal chat with token streaming. It doesn't build agents; it gives the one you have a nice place to talk.

import partnuh

agent = partnuh.AgentSpec(name="Private Caller", model="openai/gpt-5.4-nano").build()
partnuh.run(agent)

Run the example locally (from a checkout)

Install the package into a virtualenv in editable mode, then run the example — examples/basic_agent.py, a complete agent CLI in a few lines:

cd partnuh
python3 -m venv .venv
.venv/bin/pip install -e ".[openai,dotenv]"   # or ".[all]"
cp .env.template .env                          # add your OPENROUTER_API_KEY

.venv/bin/python examples/basic_agent.py            # interactive
.venv/bin/python examples/basic_agent.py "hello"    # one-shot

It auto-loads .env. See the comments in the file for how each part maps to the library.

Install (as a dependency)

pip install partnuh                 # core (bring your own agent)
pip install "partnuh[openai]"       # + OpenAI/OpenRouter chat backend
pip install "partnuh[smolagents]"   # + smolagents adapter
pip install "partnuh[all]"

Use

A chat model over OpenRouter (no framework):

import partnuh

agent = partnuh.AgentSpec(
    name="Private Caller",
    model="openai/gpt-5.4-nano",     # OpenRouter model id
    backend="openrouter",            # uses $OPENROUTER_API_KEY
).build()
partnuh.run(agent)

Wrap a smolagents agent (tool calling works):

import os, partnuh
from smolagents import OpenAIServerModel, ToolCallingAgent, tool

@tool
def add(a: int, b: int) -> int:
    "Add two integers.\n\nArgs:\n  a: first\n  b: second"
    return a + b

model = OpenAIServerModel(model_id="openai/gpt-5.4-nano",
                          api_base="https://openrouter.ai/api/v1",
                          api_key=os.environ["OPENROUTER_API_KEY"])
smol = ToolCallingAgent(tools=[add], model=model, stream_outputs=True)

agent = partnuh.from_smolagents(smol, name="Private Caller")
partnuh.run(agent)

Ready-to-run command (after pip install "partnuh[openai,dotenv]"):

export OPENROUTER_API_KEY=sk-or-...
partnuh                       # interactive
partnuh "what's 2+2?"         # one-shot

In the REPL

  • Enter submits, Shift+Enter inserts a newline (works across terminals — see below). Backspace on a blank line joins back to the previous line.
  • /tools list tools · /reset clear history · /help · /quit

Configuring behavior

from partnuh import CliConfig

partnuh.run(agent, config=CliConfig(
    stream_speed=0.0,      # 0 = as-fast-as-tokens-arrive; 1.0 = slow typewriter
    show_tool_calls=True,  # render the tool-call markers
    banner=True,
    commands={"clear": lambda d, args: __import__("os").system("clear")},
))

How it works (ports & adapters)

There is no universal in-process agent object shared across frameworks, so partnuh defines a tiny contract and ships adapters:

  • CliAgent protocol — name, model, tools, and stream(prompt, session_id) -> Iterator[Event].
  • Event union — TextDelta, ToolCallStarted, ToolResult, Error, Done. Every adapter translates its framework's native stream into these; a bare str is treated as a TextDelta.
  • Adaptersfrom_openai, from_smolagents, from_callable. Add your own by yielding Events.
  • Pacer — renders the event stream to the terminal with optional speed control.

The Shift+Enter trick

Terminals encode Shift+Enter differently, and prompt_toolkit's default collapses the common Ghostty/xterm encoding into plain Enter (so it submits instead of adding a newline). partnuh registers every known Shift+Enter escape sequence (\x1b[27;2;13~, kitty's \x1b[13;2u, …) and maps it to "insert newline" — no terminal config required.

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

partnuh-0.0.1.tar.gz (15.1 kB view details)

Uploaded Source

Built Distribution

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

partnuh-0.0.1-py3-none-any.whl (17.8 kB view details)

Uploaded Python 3

File details

Details for the file partnuh-0.0.1.tar.gz.

File metadata

  • Download URL: partnuh-0.0.1.tar.gz
  • Upload date:
  • Size: 15.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for partnuh-0.0.1.tar.gz
Algorithm Hash digest
SHA256 bb0068f3324fa73145e4b632ec2fcea2591e927f49e76a28933ef6069e16d961
MD5 7121143f0917850ff7f5740c68fbe6b7
BLAKE2b-256 a3a4d66c5270182a55dc761b24d755c6410ec0b26256ebbaa1dda458abf98d58

See more details on using hashes here.

File details

Details for the file partnuh-0.0.1-py3-none-any.whl.

File metadata

  • Download URL: partnuh-0.0.1-py3-none-any.whl
  • Upload date:
  • Size: 17.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for partnuh-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 1aac1ac223a8a9ef08c3b756ed0333fe27b2da4378e8b88ae6fa591245fcaed4
MD5 a4ae54aafd57905ac8fcf00f86913d3f
BLAKE2b-256 b0d6d39a1603b7d822469e513442d1dc117c4795450424f71b8e03dd0dca6bf7

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