Metadata-Version: 2.4
Name: node-mantis
Version: 0.1.0a13
Summary: NodeMantis Python configuration, browser setup, and installation validation tools
Author: NodeMantis
License-Expression: LicenseRef-NodeMantis-Proprietary
Project-URL: Homepage, https://github.com/Node-Mantis/CleanSlate#readme
Project-URL: Repository, https://github.com/Node-Mantis/CleanSlate
Project-URL: Issues, https://github.com/Node-Mantis/CleanSlate/issues
Keywords: browser,automation,playwright,node-mantis,nodemantis
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE.txt
Provides-Extra: browser
Requires-Dist: playwright<2,>=1.59.1; extra == "browser"
Dynamic: license-file

# NodeMantis Python

The NodeMantis Python SDK: browser-driving agent sessions at parity with the
npm `node-mantis` package, plus configuration, browser setup, and installation
validation tools.

Platform wheels bundle the same compiled native runtime the npm SDK uses; the
Python layer is a thin client that spawns it and forwards requests. Browser
sessions additionally need Playwright for Python (the `[browser]` extra) — the
runtime launches and drives a real Google Chrome through it.

Customer install:

```bash
pip install "node-mantis[browser]"
python -m nodemantis configure --api-key "$NODEMANTIS_API_KEY"
python -m nodemantis install-browser --browser chrome
python -m nodemantis smoke
```

Run a browser goal:

```python
from nodemantis import NodeMantis

with NodeMantis.start(start_url="https://example.com", headless=True) as mantis:
    result = mantis.run("Open the More information link.", max_iterations=5)
    print(result.ok, result.reason)
```

The session surface mirrors the TypeScript SDK: `NodeMantis.start()` /
`NodeMantis.preflight()`, and per-session `go`, `run`, `step`, `retrieve`,
`extract`, `check`, `close` (sessions are context managers). Options are
snake_case (`max_iterations`, `screenshot_enabled`, `result_schema`,
`allow_navigation`, …); `model` selects a size tier (`"small"`, `"standard"`,
`"large"`). `run`/`step` accept an `on_progress` callback for per-iteration
narration; callbacks arrive on a background thread and must not call session
methods. `retrieve` returns a discriminated result with `status` of `success`
or `unavailable`. Success carries non-null `data`; unavailable carries
`data=None`, a client-readable `message`, and a `retryable` boolean. Both
outcomes include token usage, metered cost, the final URL, and an optional
trace ID. Schemas are plain JSON Schema dicts (pydantic v2 model classes are
also accepted). `attach()` remains TypeScript-only.

If NodeMantis cannot complete a retrieval request, it raises
`RetrievalRequestError` rather than returning `unavailable`. The exception
contains only customer-actionable fields: `code`, `retryable`, `trace_id`, and
`cost_usd`, along with its message. Codes are `INVALID_REQUEST`,
`AUTHENTICATION_FAILED`, `USAGE_LIMIT`, `REQUEST_BLOCKED`,
`SERVICE_UNAVAILABLE`, `CANCELLED`, or `OPERATION_FAILED`.

```python
from nodemantis import RetrievalRequestError

try:
    result = mantis.retrieve("Retrieve the current price.")
    if result.is_unavailable and result.retryable:
        print("No result was available; trying again may help.")
except RetrievalRequestError as error:
    if error.retryable:
        # Retry using your application's normal backoff policy.
        pass
    raise
```

Managed sessions accept Playwright browser-context settings through
`context_options`, using the same camel-case option names as TypeScript
`contextOptions`. NodeMantis owns the user agent and device-class identity, so
`userAgent`, `isMobile`, and `hasTouch` are reserved and must not be supplied
there.

```python
with NodeMantis.start(
    headless=True,
    viewport={"width": 1280, "height": 720},
    context_options={
        "locale": "en-CA",
        "timezoneId": "America/Toronto",
        "screen": {"width": 1440, "height": 900},
        "deviceScaleFactor": 2,
    },
) as localized:
    localized.go("https://example.com")
```

### How Phase 1 chooses a browser identity

NodeMantis chooses one coherent identity when a managed session starts and
keeps it for the life of that session. Supported values supplied by the caller
come first, followed by facts read from the installed Chrome and the host. If
those facts cannot be read, NodeMantis uses a platform-specific fallback whose
screen, viewport, language, and device scale still agree. For any value Chrome
cannot represent honestly, NodeMantis keeps Chrome's native value instead of
inventing one or replacing a JavaScript getter.

If no viewport is supplied, the managed-session default remains 1280×720.
Screen size and DPR are detected separately or taken from the coherent
platform fallback; they are not inferred by pretending the viewport is the
whole display.

The resulting profile is applied through browser controls, without page-level
JavaScript identity wrappers. Managed sessions work in both headless and headed
mode, and each session keeps its chosen profile fixed across pages, frames,
popups, and dedicated, shared, and service workers. HTTP requests retain the
resolved full `Accept-Language` preference, while browser JavaScript
consistently sees the selected primary locale. If an unrecognized Chrome
version cannot provide a coherent live Client Hints fingerprint, NodeMantis
leaves those values native rather than fabricating a brand list.

Before a managed page or worker starts running site code, NodeMantis asks
Chrome to hold it briefly, applies the native parts of the session profile,
and then lets it continue. The hold applies only to the browser context owned
by that NodeMantis session, so unrelated Playwright browsers and contexts keep
working normally. Popups and workers created later go through the same check,
including workers created by another worker.

Cross-origin frames use a safe exception to that hold because pausing both the
frame and its parent can block Chrome from attaching either one. They receive
the same launch, context, network, and top-page settings before their first
instruction, then NodeMantis reinforces the values Chrome allows on the frame
itself. If Chrome cannot apply a value there, the frame keeps its honest native
value; NodeMantis never installs a JavaScript getter to disguise the mismatch.

Pages and workers can disappear while Chrome is still setting them up. When
that happens, NodeMantis asks Chrome whether the target really ended. If it did,
the rest of the session continues; if it is still alive with only part of the
profile applied, NodeMantis closes it. If Chrome cannot give a definite answer,
that browser instance is retired and a later session starts a fresh one. This
keeps headless startup from returning a half-configured page or reusing a
browser whose shutdown was uncertain.

Chrome version, User-Agent, and Client Hints must describe the browser that is
actually running. Consequently, `userAgent`, `isMobile`, and `hasTouch` remain
reserved context options. `User-Agent` and every `Sec-CH-UA*` name are also
reserved inside `context_options["extraHTTPHeaders"]`; attempts to override
them are rejected instead of creating a mismatch between JavaScript and
network requests.

Phase 1 makes Chrome's own identity internally consistent; it does not claim
that headless Chrome defeats every detector. Graphics, the observable effects
of automation and CDP, networking, and the agent's functional page scripts are
separate hardening areas.

API keys resolve from the `api_key` argument, then `NODEMANTIS_API_KEY`,
`NODEMANTIS_AUTH_TOKEN`, and finally the `nodemantis configure` config file.
The package always connects to the hosted Node Mantis API; the service
endpoint is not customer-configurable.

`node-mantis[browser]` installs Playwright for browser sessions, checks, and
smoke tests. Browser binaries are installed separately; run
`python -m nodemantis install-browser --browser chrome` for Google Chrome or
use `--browser chromium` for Playwright Chromium.

Installing the wheel also puts a `nodemantis` command on `PATH` (equivalent to
`python -m nodemantis`); `pipx install node-mantis` gives the same command in
an isolated environment. This CLI covers setup verbs only — `configure`,
`doctor`, `install-browser`, `smoke`. Command-line task execution
(`nodemantis run`, `nodemantis retrieve`) ships with the npm package:
`npm install -g node-mantis`. If both are installed, whichever is first on
`PATH` wins; the setup verbs behave identically.

Validate API access, credentials, and the selected browser from Python:

```python
from nodemantis import preflight

report = preflight(check_browser_launch=True, timeout_seconds=5)
if not report.ok:
    raise RuntimeError(report.checks)
```

Supported alpha platforms: Linux x64, Windows x64, macOS x64, and macOS arm64.
Wheels without a bundled runtime (source-free builds) raise
`RUNTIME_NOT_INSTALLED` when starting a session; advanced setups can point
`NODEMANTIS_RUNTIME_PATH` at a runtime executable.

This package is proprietary alpha software. Use is governed by `LICENSE.txt`
and applicable NodeMantis terms.
