Skip to main content

Thin Python client for the wigolo local-first web intelligence REST API

Project description

wigolo — Python client

Pre-publish. This package is not on PyPI yet. Install it from the locally built wheel:

pip install dist/wigolo-0.1.0-py3-none-any.whl

A thin, dependency-free Python client for the wigolo local-first web intelligence server. It speaks the wigolo REST API and nothing more — no retries, no re-ranking, no interpretation, no caching. The server does all of that; this client just gets requests there and responses back with typed method signatures.

  • Zero runtime dependencies — stdlib only.
  • Sync and async clients with an identical surface.
  • Embedded local modelocal_client() probes or spawns a local server for you, no manual setup.
  • Fully typed (py.typed, PEP 561).

Tools

One method per tool: search, fetch, crawl, cache, extract, find_similar, research, agent, diff, watch, plus health(), list_tools(), and openapi().

Sync quickstart

from wigolo import Client

with Client(base_url="http://127.0.0.1:3333") as client:
    res = client.search(query="local first web search", max_results=5)
    for r in res.get("results", []):
        print(r.get("title"), r.get("url"))

    page = client.fetch(url="https://example.com")
    print(page.get("markdown", "")[:500])

    tables = client.extract(
        html="<table><tr><th>a</th></tr><tr><td>1</td></tr></table>",
        mode="tables",
    )
    print(tables["data"])

Async quickstart

import asyncio
from wigolo import AsyncClient

async def main():
    async with AsyncClient(base_url="http://127.0.0.1:3333") as client:
        res = await client.search(query="local first web search", max_results=5)
        print([r.get("url") for r in res.get("results", [])])

asyncio.run(main())

The async client runs each request on a bounded thread pool (max_workers, default 16). Cancelling an awaited call returns promptly but abandons the in-flight request — the worker thread runs to completion in the background (a blocking socket read cannot be portably aborted).

Embedded local mode (zero setup)

from wigolo import local_client

# Reuses a healthy local daemon if one is already listening; otherwise spawns
# one for you and waits for it to become healthy.
with local_client() as client:
    print(client.health())
    print(client.search(query="wigolo"))

local_client() (equivalently Client(local=True), or setting WIGOLO_LOCAL=1) resolves a port (WIGOLO_LOCAL_PORT, default 3333), probes /health, and either reuses an existing REST-capable daemon or spawns a new one via the wigolo CLI on your PATH (override with WIGOLO_CLI). A daemon this client spawns is stopped on close(); a daemon it merely reused is left running. In local mode base_url / WIGOLO_BASE_URL are ignored.

AsyncClient(local=True) accepts the same port / command overrides, but note the daemon probe-or-spawn runs synchronously in the constructor (it may block the calling thread up to ~20s while the daemon becomes healthy).

Security notes for embedded mode

  • WIGOLO_CLI is an exec-from-env vector. In embedded mode the SDK spawns the process named by WIGOLO_CLI (a JSON argv list, or a single executable path). Anything that can set this env var chooses what binary runs. When you hand the SDK untrusted environments, strip WIGOLO_CLI (and WIGOLO_LOCAL_PORT) before construction and pass the trusted argv through the explicit command= argument — the argument always overrides the env.
  • Point command at the server binary itself, not a wrapper. On POSIX, forced-kill escalation signals only the direct child. A wrapper such as ["npx", "wigolo"] makes the launcher the direct child, so a hung close() can kill the launcher while the real daemon it spawned is orphaned and keeps holding the port. Resolve to the actual wigolo executable so close() reaches the process that owns the socket.

Configuration

Resolution order for each option is explicit argument > environment variable > default. When an argument is passed explicitly, the corresponding env var is not consulted.

Option Argument Env var Default
Base URL base_url WIGOLO_BASE_URL http://127.0.0.1:3333
Bearer token token WIGOLO_API_TOKEN none
Local mode local WIGOLO_LOCAL=1 off
Local port port WIGOLO_LOCAL_PORT 3333
Spawn command command WIGOLO_CLI wigolo on PATH

The bearer token is only sent when set — the server requires it only when it runs with a token configured.

Timeouts

The timeout option (per client, or per call) is a per-socket-operation timeout — the maximum idle time on connect or read inactivity — not a total wall-clock deadline. When unset, each method uses its per-tool default, which mirrors the server's unscaled per-route deadline. If your server runs with WIGOLO_SERVE_TIMEOUT_SCALE set, its effective deadline scales but the client defaults do not — pass an explicit timeout to match.

Notes

  • stream on research / agent is accepted by the schema but has no effect over this transport — responses are returned whole.
  • A degraded call stays HTTP 200 with in-body warning / error fields; those are returned verbatim and never raise.
  • crawl(strategy="map") returns urls (no pages); the other strategies return pages.
  • The searxng field in health() is the search-aggregator sidecar status.

Errors

  • WigoloError — base class.
  • WigoloAPIError — a non-2xx HTTP response, carrying status, error, error_reason, stage, and retry_after (parsed from Retry-After on 429).
  • WigoloConnectionError — a transport-level failure (e.g. connection refused) with no HTTP response. Its message points at local_client() as the zero-setup path.

License

AGPL-3.0-or-later. See LICENSE.

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

wigolo-0.2.0.tar.gz (29.4 kB view details)

Uploaded Source

Built Distribution

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

wigolo-0.2.0-py3-none-any.whl (33.4 kB view details)

Uploaded Python 3

File details

Details for the file wigolo-0.2.0.tar.gz.

File metadata

  • Download URL: wigolo-0.2.0.tar.gz
  • Upload date:
  • Size: 29.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for wigolo-0.2.0.tar.gz
Algorithm Hash digest
SHA256 71f83dfd4805e5460e84594cd1353c40990f94be6d6a185c19f8a61a9b2ee81a
MD5 0e93e1d8fb659b959b97015fd1c5fd5b
BLAKE2b-256 8a4c21f045216618a87b69f610a578acb0463d3ede47024a9b6aa4adced19780

See more details on using hashes here.

File details

Details for the file wigolo-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: wigolo-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 33.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for wigolo-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e0cdf1ec59e9556a216ccd94ae128ed06488b9c4f7e49f745d1b767a7af14be0
MD5 d88aea1fb4144db02d8275ba73370d88
BLAKE2b-256 12ce14c29ad3cbbb849aefcf3c4d518805a8524780a157a782aeff9e8b009b26

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