Metadata-Version: 2.4
Name: soothe-nano
Version: 1.0.12
Summary: Soothe Nano — batteries-included SootheNanoAgent on deepagents
Project-URL: Homepage, https://github.com/mirasoth/soothe-nano
Project-URL: Documentation, https://soothe.readthedocs.io
Project-URL: Repository, https://github.com/mirasoth/soothe-nano
License: MIT
Keywords: agents,ai,coreagent,deepagents,langgraph,llm,nano,soothe
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: <3.15,>=3.11
Requires-Dist: aiofiles>=24.1.0
Requires-Dist: aiohttp<4.0.0,>=3.9.0
Requires-Dist: browser-use<0.13.0,>=0.11.0
Requires-Dist: dashscope>=1.20.0
Requires-Dist: deepxiv-sdk>=0.2.5
Requires-Dist: docx2txt>=0.8.0
Requires-Dist: httpx<1.0.0,>=0.27.0
Requires-Dist: jsonschema<5.0.0,>=4.0.0
Requires-Dist: langchain-community<1.0.0,>=0.3.0
Requires-Dist: langchain-core<2.0.0,>=1.2.18
Requires-Dist: langchain-mcp-adapters<1.0.0,>=0.2.0
Requires-Dist: langchain-openai<1.0.0,>=0.3.0
Requires-Dist: langchain-quickjs>=0.1.0
Requires-Dist: langchain-tavily>=0.2.17
Requires-Dist: langchain<2.0.0,>=1.2.11
Requires-Dist: langgraph-checkpoint-postgres<4.0.0,>=3.1.0
Requires-Dist: langgraph-checkpoint-sqlite>=3.0.3
Requires-Dist: langgraph-checkpoint<5.0.0,>=4.0.0
Requires-Dist: langgraph<2.0.0,>=1.1.1
Requires-Dist: openpyxl>=3.1.0
Requires-Dist: packaging>=23.0
Requires-Dist: pandas>=2.0.0
Requires-Dist: pathspec<2.0.0,>=0.12.0
Requires-Dist: psycopg[binary,pool]<4.0.0,>=3.2.0
Requires-Dist: pydantic-settings<3.0.0,>=2.0.0
Requires-Dist: pydantic<3.0.0,>=2.0.0
Requires-Dist: pymupdf>=1.24.0
Requires-Dist: python-dotenv<2.0.0,>=1.0.0
Requires-Dist: pyyaml<7.0.0,>=6.0.0
Requires-Dist: requests<3.0.0,>=2.32.3
Requires-Dist: soothe-deepagents<1.0.0,>=0.8.4
Requires-Dist: soothe-sdk<2.0.0,>=1.0.7
Requires-Dist: sqlite-vec>=0.1.0
Requires-Dist: wcmatch>=10.1
Requires-Dist: wizsearch<2.0.0,>=1.1.9
Provides-Extra: dev
Requires-Dist: mypy>=1.0.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=1.3.0; extra == 'dev'
Requires-Dist: pytest-cov; extra == 'dev'
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Requires-Dist: ruff>=0.12.0; extra == 'dev'
Requires-Dist: twine>=5.0.0; extra == 'dev'
Description-Content-Type: text/markdown

# soothe-nano

[![PyPI version](https://img.shields.io/pypi/v/soothe-nano.svg?label=PyPI&color=blue)](https://pypi.org/project/soothe-nano/)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/mirasoth/soothe-nano)

A **ready-to-run coding agent** you can drop into a script, CLI, or app.

Built on [soothe-deepagents](https://github.com/mirasoth/soothe-deepagents) (filesystem, shell, subagents, skills, MCP). Nano adds the pieces you usually wire yourself: workspace safety, progressive tools/skills, research subagents, and a config-driven factory.

## Vision

Give builders a production-shaped `SootheNanoAgent` in a few lines of Python.

- **Start small** — chat, tools, or full composition
- **Stay portable** — embed in notebooks, CLIs, or your own service
- **Compose what you need** — tools, memory, subagents, skills, and MCP via config

## Architecture

```
soothe-deepagents   agent harness (FS, shell, memory, skills base)
        ↓
soothe-sdk          shared contracts (protocols, events)
        ↓
soothe-nano         SootheNanoAgent + toolkits + subagents + MCP
```

```text
create_nano_agent(config)
        │
        ├─ model + middleware stack
        ├─ tools (builtin groups + yours)
        ├─ subagents (planner, research, browser, …)
        ├─ skills (progressive discovery)
        └─ MCP (on-demand activation)
```

## Features

| Area | What nano provides |
|---|---|
| Tools | Builtin groups: shell, file ops, HTTP, search, data, … |
| Subagents | Ready: plan, deep/academic research, browser |
| Skills / tools in context | Progressive loading — activate what the turn needs |
| Workspace | Scoped workspace + security defaults |
| Config | YAML / `SootheConfig` factory |
| Memory | Optional long-term memory via protocols |
| MCP | Registry and on-demand adapters |

## vs deepagents

| | deepagents | soothe-nano |
|---|---|---|
| What you get | Opinionated harness | Harness **plus** coding product defaults |
| Tools | Bring your own | Builtin groups out of the box |
| Subagents | You define them | Ready plan / research / browser |
| Skills / tools in context | Base support | Progressive loading |
| Workspace | Pluggable backends | Scoped workspace + security defaults |
| Config | Code-first | YAML / `SootheConfig` factory |

Use **deepagents** when you want a minimal harness and full control.  
Use **nano** when you want a coding agent that already knows how to work in a repo.

## When to use nano

| Scenario | Fit |
|---|---|
| Coding assistant in a repo | ✅ Files, shell, plan out of the box |
| Research / browsing agent | ✅ Deep research, academic, browser subagents |
| Embed in your product | ✅ Library API, no daemon required |
| One-shot / headless CLI | ✅ See [fj-ai](https://github.com/caesar0301/fj-ai) |
| Plugin / toolkit author | ✅ Depends on nano only |
| Simple Q&A chat | ✅ Strip tools/subagents as needed |

## Install

```bash
uv add soothe-nano
```

## Quick start

```python
from soothe_nano import create_nano_agent
from soothe_nano.config import SootheConfig

agent = create_nano_agent(SootheConfig())
# agent.ainvoke / streaming — see examples/
```

Library examples live in `examples/`:

1. Pure model (no tools)
2. With tools
3. With memory
4. With subagents
5. Full composition

```bash
python packages/soothe-nano/examples/01_pure_nano_example.py
```

## Productive CLI (reference: fj-ai)

[fj-ai](https://github.com/caesar0301/fj-ai) is a production one-shot coding CLI built only on **soothe-nano** (no soothe daemon). Use it as the integration blueprint:

```bash
pip install fj-ai   # or: uv tool install fj-ai
fj explain this repo
fj -f what did we decide last time?
```

### Integration pattern

A headless CLI typically does four things on top of nano:

1. **Load config** — `~/.soothe/config/nano.yml`, or zero-config from `OPENAI_API_KEY` / `ANTHROPIC_API_KEY`
2. **Force SQLite** for standalone runs (threads survive across process exits)
3. **Build the agent** with `create_nano_agent`, pin workspace, attach a checkpointer
4. **Stream** `agent.astream(...)` and **close** the `aiosqlite` connection on exit

Minimal sketch (same shape as [fj_ai/agent.py](https://github.com/caesar0301/fj-ai/blob/main/src/fj_ai/agent.py)):

```python
from __future__ import annotations

import asyncio
from contextlib import asynccontextmanager
from pathlib import Path
from typing import Any, AsyncIterator

from soothe_nano import SootheNanoAgent, create_nano_agent
from soothe_nano.config import SOOTHE_HOME, SootheConfig
from soothe_nano.resolve import resolve_checkpointer


def load_config(path: Path | None = None) -> SootheConfig:
    cfg = path or (SOOTHE_HOME / "config" / "nano.yml")
    if cfg.is_file():
        return SootheConfig.from_yaml_file(str(cfg))
    return SootheConfig()  # OPENAI_API_KEY / ANTHROPIC_API_KEY


def apply_cli_defaults(config: SootheConfig) -> SootheConfig:
    durability = config.agent.protocols.durability.model_copy(
        update={"backend": "sqlite", "checkpointer": "sqlite"}
    )
    protocols = config.agent.protocols.model_copy(update={"durability": durability})
    agent = config.agent.model_copy(update={"protocols": protocols})
    persistence = config.persistence.model_copy(update={"default_backend": "sqlite"})
    return config.model_copy(update={"agent": agent, "persistence": persistence})


@asynccontextmanager
async def open_sqlite_checkpointer(config: SootheConfig) -> AsyncIterator[Any | None]:
    result = resolve_checkpointer(apply_cli_defaults(config))
    db_path = result[1] if isinstance(result, tuple) and isinstance(result[1], str) else None
    if not db_path:
        yield None
        return

    import aiosqlite
    from langgraph.checkpoint.sqlite.aio import AsyncSqliteSaver
    from soothe_sdk.utils.serde import create_soothe_serde

    Path(db_path).parent.mkdir(parents=True, exist_ok=True)
    conn = await aiosqlite.connect(db_path)
    checkpointer = AsyncSqliteSaver(conn, serde=create_soothe_serde())
    await checkpointer.setup()
    try:
        yield checkpointer
    finally:
        await conn.close()  # required — aiosqlite uses a non-daemon thread


async def build_agent(
    config: SootheConfig,
    *,
    checkpointer: Any | None = None,
) -> SootheNanoAgent:
    agent = create_nano_agent(apply_cli_defaults(config))
    if checkpointer is not None:
        agent.graph.checkpointer = checkpointer
    return agent


async def run_once(query: str, *, thread_id: str) -> None:
    config = load_config()
    async with open_sqlite_checkpointer(config) as checkpointer:
        agent = await build_agent(config, checkpointer=checkpointer)
        async for chunk in agent.astream(
            query,
            config={"configurable": {"thread_id": thread_id}},
            stream_mode=["messages", "updates", "custom"],
        ):
            # render tokens / tool progress to stdout (see fj_ai/stream.py)
            _ = chunk


if __name__ == "__main__":
    asyncio.run(run_once("summarize this repo", thread_id="cli-demo"))
```

### What fj adds on top of nano

| Concern | fj-ai approach |
|---|---|
| UX | One-shot `fj <query…>`; `-f` / `-t` resume threads; `-l` list |
| Persistence | SQLite checkpointer under `$SOOTHE_DATA_DIR` |
| Skills | Package `builtin_skills/` via `register_builtin_skill_root` |
| Workspace | `SOOTHE_WORKSPACE` / cwd for file + shell tools |
| Streaming | Quiet progress line + full final answer (`stream.py`) |
| Setup | `fj setup` writes `~/.soothe/config/nano.yml` |

For a full TUI / StrangeLoop host on the same stack, see [mirasoth/soothe](https://github.com/mirasoth/soothe). For the slim CLI product, clone [caesar0301/fj-ai](https://github.com/caesar0301/fj-ai).

## Package layout

```
soothe_nano/
  agent/       SootheNanoAgent, create_nano_agent
  config/      SootheConfig
  toolkits/    Builtin tool groups
  subagents/   plan, research, browser, …
  middleware/  Progressive tools/skills, workspace, policy
  skills/      Catalog + progressive search
  mcp/         MCP registry / adapters
  backends/    Persistence helpers
```

## Development

From `packages/soothe-nano/`:

```bash
make help              # list targets
make sync-dev          # sync deps
make format lint       # format + lint
make test-unit         # unit tests
make test-integration  # integration tests (--run-integration)
make examples          # run examples
make build             # build dist/
```
