Metadata-Version: 2.4
Name: hugpy-tools
Version: 0.2.7
Summary: Hugpy tools: a slim, stdlib-only capability suite for autonomous agents (safe file/path ops, text chunking and diffing, hashing, structured-data read/write, and urllib+html.parser webpage assessment)
Author-email: putkoff <support@hugpy.ai>
License-Expression: LicenseRef-Proprietary
Project-URL: Homepage, https://hugpy.ai
Project-URL: Documentation, https://github.com/hugpy/hugpy/blob/main/py/foundation/hugpy_tools/README.md
Project-URL: Repository, https://github.com/hugpy/hugpy
Project-URL: Source, https://github.com/hugpy/hugpy/tree/main/py/foundation/hugpy_tools
Project-URL: Issues, https://github.com/hugpy/hugpy/issues
Project-URL: Changelog, https://github.com/hugpy/hugpy/releases
Project-URL: Architecture, https://github.com/hugpy/hugpy/blob/main/PARTITION.md
Keywords: hugpy,agent,tools,filesystem,webpage,assessment
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: toml
Requires-Dist: tomli; python_version < "3.11" and extra == "toml"
Provides-Extra: yaml
Requires-Dist: PyYAML; extra == "yaml"
Provides-Extra: render
Requires-Dist: playwright; extra == "render"
Provides-Extra: images
Requires-Dist: Pillow; extra == "images"
Provides-Extra: vision
Requires-Dist: Pillow; extra == "vision"
Requires-Dist: pytesseract; extra == "vision"
Requires-Dist: numpy; extra == "vision"
Requires-Dist: opencv-python-headless; extra == "vision"
Provides-Extra: text
Requires-Dist: abstract_utilities; extra == "text"
Provides-Extra: files
Requires-Dist: abstract_utilities; extra == "files"
Requires-Dist: abstract_search; extra == "files"
Requires-Dist: abstract_paths; extra == "files"
Provides-Extra: web
Requires-Dist: abstract_webtools; extra == "web"
Provides-Extra: legacy
Requires-Dist: abstract_utilities; extra == "legacy"
Requires-Dist: abstract_search; extra == "legacy"
Requires-Dist: abstract_paths; extra == "legacy"
Requires-Dist: abstract_webtools; extra == "legacy"
Provides-Extra: media
Requires-Dist: abstract_ocr; extra == "media"
Requires-Dist: abstract_pandas; extra == "media"
Requires-Dist: media_intelligence; extra == "media"
Provides-Extra: desktop
Requires-Dist: abstract_clicks; extra == "desktop"
Requires-Dist: abstract_windows; extra == "desktop"
Requires-Dist: Pillow; extra == "desktop"
Requires-Dist: pytesseract; extra == "desktop"
Provides-Extra: test
Requires-Dist: pytest>=8; extra == "test"
Requires-Dist: pytest-timeout; extra == "test"
Dynamic: license-file

# hugpy-tools

`hugpy_tools` is a standalone capability suite for autonomous agents. Its core
uses only the standard library; optional backends provide document extraction,
model-specific token counting, rendering, media, images, desktop, and VM tools.
It does not import Toolserver or require a running service, database, or fleet.

## Standalone use

```bash
pip install hugpy-tools
hugpy-tools list
hugpy-tools call text_estimate_tokens --arguments '{"text":"hello world"}'
# The same CLI is available as python -m hugpy_tools.
```

```python
from hugpy_tools import call_tool, get_toolset, list_tools

result = call_tool("fs_read_lines", {"path": "/tmp/example.txt", "start": 1, "end": 20})
schemas = list_tools()  # name, description, inputSchema
tools = get_toolset()  # category -> route -> callable; fresh mappings per call
```

Direct module functions remain available. `include_optional=True` adds backend
tools to each registry API, or use `--optional` with the CLI. Discovery imports
no optional backend; an unavailable dependency fails when that tool is called.
Install only the extras needed: `files`, `text`, `web`, `legacy` (all three),
`render`, `images`, `vision`, `media`, or `desktop`. Rendering also needs a
Playwright browser installation; VM operations require host libvirt/LXD tools.

## Toolserver integration

The dependency runs one way: `abstract_toolserver` imports `hugpy_tools`.

| This package owns | Toolserver adds |
| --- | --- |
| Portable implementations, backend adapters, registry, and input schemas | HTTP/MCP transport, authentication, and discovery |
| Local screenshot rendering, image operations, grid math, and aiming helpers | Hosted screenshot URLs, cleanup, and fleet vision routing |
| Explicit local execution | Command allowlist, node delegation, and session context |

Boards, handoffs, credentials, database records, and managed browser/VM sessions
remain Toolserver services. `process.run_command(argv)` is available directly;
Toolserver exposes it through its allowlist-gated `sys_run_cmd` adapter.

`compat.py` preserves established Toolserver arguments and backend results where
the native helpers have different contracts. For example, `text_estimate_tokens`
is approximate and dependency-free; optional `text_count_tokens` retains the
`model_name` argument and model-specific backend. `fs_read_text` returns metadata
and text; `fs_read_file` retains the text-only result. Old Toolserver visual
imports alias the portable modules, so there is one implementation to maintain.

The `imports/` package supplies shared constants, functions, classes, and
`init_imports`, following the workspace's shared-import pattern.

## Built-in tools

Every `fs` function takes an **already-confined** absolute path — call
`paths.confine(root, path)` first to enforce a workspace jail (rejects `..`,
absolute-outside, and symlink escapes in one check).

| Module | Function | What it does |
| --- | --- | --- |
| `paths` | `confine(root, path, for_write=False)` | Resolve a path under `root`; raise `PathEscape` on any escape. |
| `paths` | `file_parts(path)` | Decompose into dir/base/name/ext + two enclosing dir levels. |
| `paths` | `sanitize_filename(name)` | Reduce to one safe path component, length-bounded. |
| `fs` | `read_text(path, max_bytes=None)` | Read with encoding detection (BOM → utf-8 → cp1252). |
| `fs` | `read_lines(path, start, end, number=False)` | 1-based inclusive line-range read. |
| `fs` | `atomic_write(path, content, append=False)` | Durable write (temp file + `os.replace`); append supported. |
| `fs` | `edit_replace(path, old, new, count=None)` | Exact string replace with an occurrence-count contract; atomic. |
| `fs` | `file_info(path, hash_files=False)` | Size, mtime, type, symlink flag, optional sha256. |
| `fs` | `list_dir(path, glob=None, ...)` | Immediate entries (dirs first), optional fnmatch. |
| `fs` | `tree(path, max_depth=3, max_entries=500)` | Bounded recursive tree text (never follows dir symlinks). |
| `hashkit` | `sha256_text` / `sha256_file` / `quick_hash` | Content hashing (files streamed in 1 MiB windows). |
| `text` | `count_tokens(text)` | Dependency-free approximate BPE token count. |
| `text` | `chunk_by_lines` / `chunk_by_tokens` | Chunk on line or token budgets (paragraph-aware). |
| `text` | `unified_diff(before, after)` | Unified diff between two texts. |
| `data` | `read_data(path, fmt=None)` | Parse JSON always, TOML via stdlib `tomllib`, YAML if PyYAML present. |
| `data` | `write_json(path, obj)` / `safe_json_dumps(obj)` | Atomic JSON write / non-exploding dumps. |
| `timekit` | `now_iso` / `now_epoch` / `epoch_to_iso` / `iso_to_epoch` | UTC time conversions. |
| `web` | `assess_webpage(url, ...)` | assessManager-parity structured page assessment over urllib + `html.parser`. |
| `web` | `prescreen_webpage(url, ...)` | Cheap title + description + lede relevance pre-screen. |

### Web assessment

`assess_webpage` returns the same dict shape as
`abstract_webtools.assessManager.assess_webpage`
(`{url, title, description, text, metadata, jsonld, links, truncated, render}`)
plus additive keys `final_url`, `status`, `canonical`, `lang`, `headings`, and
`error`. The fetch is http(s)-only, refuses redirects to other schemes,
disables `file://` / `ftp://`, caps the body, times out, handles gzip/deflate,
and detects charset (Content-Type → BOM → `<meta charset>` → utf-8 → cp1252).

JS rendering is opt-in and lazy: `force_render=True` (or an automatic fall-back
when the cheap fetch yields almost no text) drives a headless browser **only if
Playwright or Selenium is installed**, and raises a clear "install X" error
otherwise. The default path never needs a browser.

## Layer

Foundation. Core imports use only the standard library. Optional integrations
are loaded on use from `compat`, `backends`, and `visual`; they must not import
`abstract_toolserver`. The host owns authorization and resource lifecycle.
