Skip to main content

WaveAssist Python SDK for storing and retrieving structured data, LLM integration, and credit management

Project description

WaveAssist SDK & CLI ๐ŸŒŠ

WaveAssist SDK makes it simple to store and retrieve data in your automation workflows. Access your projects through our Python SDK or CLI.


โœจ Features

  • ๐Ÿ” One-line init() to connect with your WaveAssist project
  • โš™๏ธ Automatically works on local and WaveAssist Cloud (worker) environments
  • ๐Ÿ“ฆ Store and retrieve data (DataFrames, JSON, strings)
  • ๐Ÿง  LLM-friendly function names (init, store_data, fetch_data)
  • ๐Ÿ“ Auto-serialization for common Python objects
  • ๐Ÿ“Š Publish HTML dashboards with shareable public URLs
  • ๐Ÿค– LLM integration with structured outputs via Instructor and OpenRouter
  • ๐Ÿ’ณ Credit management and automatic email notifications
  • ๐Ÿ–ฅ๏ธ Command-line interface for project management
  • โœ… Built for automation workflows, cron jobs, and AI pipelines

๐Ÿš€ Getting Started

1. Install

pip install waveassist

2. Initialize the SDK

import waveassist

# Option 1: Use no arguments (recommended)
waveassist.init()

# Option 2: With explicit parameters
waveassist.init(
    token="your-user-id",
    project_key="your-project-key",
    environment_key="your-env-key",  # optional
    run_id="run-123",  # optional
    check_credits=True  # optional: raises RuntimeError if credits_available is "0"
)

# When check_credits=True, a missing credits_available key is treated as credits available (default "1").
# Will auto-resolve from:
# 1. Explicit args (if passed)
# 2. .env file (uid, project_key, environment_key)
# 3. Worker-injected credentials (on [WaveAssist Cloud](https://waveassist.io))

๐Ÿ›  Setting up .env (for local runs)

uid=your-user-id
project_key=your-project-key

# optional
environment_key=your-env-key

This file will be ignored by Git if you use our default .gitignore.


3. Store Data

Data is serialized by type. You can rely on type-safe storage and retrieval.

๐Ÿงพ Store a string

waveassist.store_data("welcome_message", "Hello, world!")

๐Ÿ“Š Store a DataFrame

import pandas as pd

df = pd.DataFrame({"name": ["Alice", "Bob"], "score": [95, 88]})
waveassist.store_data("user_scores", df)

๐Ÿง  Store JSON/dict/array

profile = {"name": "Alice", "age": 30}
waveassist.store_data("profile_data", profile)

๐Ÿ“Œ Optional: Force storage type

Store data as a specific type regardless of input:

# Store a dict as a string
waveassist.store_data("config", {"a": 1}, data_type="string")

# Store a string as JSON (wraps as {"value": "..."})
waveassist.store_data("greeting", "Hello", data_type="json")

Parameters: store_data(key, data, run_based=False, data_type=None). Use data_type="string", "json", or "dataframe" to force that storage type.


4. Fetch Data

result = waveassist.fetch_data("user_scores")

# Returns the correct type:
# - pd.DataFrame (if stored as dataframe)
# - dict or list (if stored as JSON)
# - str (if stored as string)

Use a default when the key might be missing:

# Return a default if key is missing or API fails
count = waveassist.fetch_data("failure_count", default=0)
greeting = waveassist.fetch_data("welcome", default="Hello")
df = waveassist.fetch_data("results", default=pd.DataFrame())  # empty DataFrame

Parameters: fetch_data(key, run_based=False, default=None).


5. Send Email

Send emails (e.g. for notifications) via the WaveAssist backend:

waveassist.send_email(
    subject="Daily report",
    html_content="<p>Summary: ...</p>",
    attachment_file=open("report.pdf", "rb"),  # optional
    raise_on_failure=True  # default: raise WaveAssistEmailError on validation or API failure
)
  • Validation: Subject and HTML body must be non-empty (and within length limits). Attachments must be file-like with a .read() method.
  • Retry: The SDK retries the send once on transient failure.
  • Errors: By default, validation failures raise ValueError and API failures raise RuntimeError. Pass raise_on_failure=False to return False instead.

6. Publish an HTML Dashboard

Generate a shareable public URL for an HTML dashboard. Anyone with the link can view it โ€” no login required.

import waveassist

waveassist.init()

html = """
<html>
<head><title>Weekly Report</title></head>
<body>
  <h1>Sales Summary</h1>
  <p>Total revenue: $12,340</p>
</body>
</html>
"""

# Publish and get a shareable URL
url = waveassist.publish_dashboard(html)
print(url)  # https://api.waveassist.io/d/a3f8c2d19e7b4f2ab5c8.../

# Email the link to yourself
waveassist.send_email(
    subject="Your Dashboard is Ready",
    html_content=f'<p>View your dashboard: <a href="{url}">{url}</a></p>'
)

Static vs Per-Run Dashboards:

# Static โ€” same data_key, URL always shows the latest content
url = waveassist.publish_dashboard(html, data_key="weekly_report")

# Per-run โ€” each run gets its own unique dashboard URL
url = waveassist.publish_dashboard(html, run_based=True)

Parameters: publish_dashboard(html_content, data_key="dashboard_html", run_based=False). Returns the public URL string, or None on failure.


7. Check Credits and Notify

Check OpenRouter credits and automatically send email notifications if insufficient credits are available:

# Check if you have enough credits for an operation
has_credits = waveassist.check_credits_and_notify(
    required_credits=10.5,
    assistant_name="WavePredict"
)

if has_credits:
    # Proceed with your operation
    print("Credits available, proceeding...")
else:
    # Credits insufficient - email notification sent (max 3 times)
    print("Insufficient credits, operation skipped")

Features:

  • Automatically checks OpenRouter credit balance
  • Sends email notification if credits are insufficient (max 3 times)
  • Resets notification count when credits become sufficient
  • Stores credit availability status for workflow control

8. Call LLM with Structured Outputs

Get structured responses from LLMs via OpenRouter with Pydantic models:

from pydantic import BaseModel

# Define your response structure
class UserInfo(BaseModel):
    name: str
    age: int
    email: str

# Call LLM with structured output
result = waveassist.call_llm(
    model="gpt-4o",
    prompt="Extract user info: John Doe, 30, john@example.com",
    response_model=UserInfo
)

print(result.name)  # "John Doe"
print(result.age)    # 30
print(result.email)  # "john@example.com"

Setup:

  1. Store your OpenRouter API key:
waveassist.store_data('open_router_key', 'your_openrouter_api_key')
  1. Use call_llm() with any Pydantic model for structured outputs

Advanced Usage:

result = waveassist.call_llm(
    model="anthropic/claude-3-opus",
    prompt="Analyze this data...",
    response_model=MyModel,
    should_retry=True,  # retry once on JSON/format errors
    max_tokens=3000,
    extra_body={"web_search_options": {"search_context_size": "medium"}}
)

Errors: RuntimeError (API/network failure), ValueError (invalid or non-JSON response). Transport errors are retried once automatically.

Local Testing with Claude CLI

Route call_llm through the Claude Code CLI for free local testing โ€” no OpenRouter credits needed. Requires claude CLI installed and authenticated (works with Claude Max, Pro, or an Anthropic API key).

LLM_PROVIDER=claude_cli        # activates CLI routing
CLAUDE_CLI_MODEL=claude-sonnet-4-6  # optional: pin a specific model

No code changes needed โ€” OpenRouter model names (e.g. anthropic/claude-sonnet-4.6) are auto-converted. Non-Claude models require CLAUDE_CLI_MODEL to be set. Unset LLM_PROVIDER to switch back to OpenRouter.


๐Ÿ–ฅ๏ธ Command Line Interface

WaveAssist CLI comes bundled with the Python package. After installation, you can use the following commands:

๐Ÿ”‘ Authentication

waveassist login

This will open your browser for authentication and store the token locally.

๐Ÿ“ค Push Code

waveassist push PROJECT_KEY [--force]

Push your local Python code to a WaveAssist project.

๐Ÿ“ฅ Pull Code

waveassist pull PROJECT_KEY [--force]

Pull Python code from a WaveAssist project to your local machine.

โ„น๏ธ Version Info

waveassist version

Display CLI version and environment information.


๐Ÿงช Running Tests

Run with pytest (recommended) or the test scripts:

# All tests (use project Python if you have a venv)
python -m pytest tests/ -v

# Or run modules directly
python tests/test_core.py
python tests/test_json_generate.py
python tests/test_json_extract.py

โœ… Includes tests for:

  • String, JSON, and DataFrame roundtrips; store_data with explicit data_type; fetch_data with default
  • send_email validation, attachments, and raise_on_failure
  • Error handling when init() is not called (RuntimeError)
  • Environment variable and .env file resolution
  • JSON template generation for Pydantic models
  • JSON extraction from various formats (pure JSON, markdown code blocks, embedded text)
  • Soft parsing with missing required fields (safety fallback for LLM responses)
  • Type coercion and nested model handling
  • Resilience / never-crash tests (test_never_crash.py): 45 tests ensuring fetch_data, store_data, send_email, publish_dashboard, and fetch_openrouter_credits never throw unhandled exceptions โ€” they return defaults (default, False, None, {}) on garbage inputs, corrupted API responses, and network failures

๐Ÿ›  Project Structure

WaveAssist/
โ”œโ”€โ”€ waveassist/
โ”‚   โ”œโ”€โ”€ __init__.py          # Public API: init(), store_data(), fetch_data(), publish_dashboard(),
โ”‚   โ”‚                         # send_email(), check_credits_and_notify(), call_llm()
โ”‚   โ”œโ”€โ”€ _config.py            # Global config and version
โ”‚   โ”œโ”€โ”€ constants.py         # API_BASE_URL, OpenRouter, dashboard URLs
โ”‚   โ”œโ”€โ”€ utils.py             # API helpers, JSON parsing, soft_parse, exception classes
โ”‚   โ”œโ”€โ”€ core.py              # CLI: login, pull, push (uses constants for URLs)
โ”‚   โ””โ”€โ”€ cli.py               # Command-line entry (waveassist login/push/pull/version)
โ”œโ”€โ”€ tests/
โ”‚   โ”œโ”€โ”€ test_core.py         # Core SDK + send_email tests
โ”‚   โ”œโ”€โ”€ test_json_generate.py # JSON template generation tests
โ”‚   โ”œโ”€โ”€ test_json_extract.py  # JSON extraction/parsing tests
โ”‚   โ”œโ”€โ”€ test_llm_call.py     # call_llm integration tests (skipped without API key)
โ”‚   โ””โ”€โ”€ test_never_crash.py  # Resilience tests: no SDK function crashes on bad input

๐Ÿ“Œ Notes

  • Data is stored in your WaveAssist backend (e.g. MongoDB) as serialized content
  • store_data() auto-detects the object type and serializes it (dataframe/JSON/string), or use data_type to force a type
  • fetch_data() returns the correct Python type and supports a default when the key is missing or the API fails
  • Logging: The SDK uses the standard library logging module (logger name "waveassist"). Configure level or handlers to control or suppress SDK messages (e.g. logging.getLogger("waveassist").setLevel(logging.WARNING)).
  • Errors: The SDK raises standard exceptions: ValueError for bad or missing input (e.g. missing uid/project_key in init, email validation, OpenRouter key not found, LLM JSON/format failure) and RuntimeError for invalid state or API failures (e.g. not initialized, credits not available, send email failed, LLM API/network failure). Catch ValueError or RuntimeError (or Exception) as needed.

Failure behavior per function:

Function On failure Never crashes?
fetch_data() Returns default (default None) on any failure โ€” bad API response, corrupted data, network error Yes
store_data() Returns False on API failure; falls back to string serialization for non-serializable data Yes
send_email(raise_on_failure=False) Returns False on validation errors, API failures, or bad attachments Yes
send_email(raise_on_failure=True) Raises ValueError (validation) or RuntimeError (API failure) Raises on purpose
publish_dashboard() Returns None on store or API failure Yes
fetch_openrouter_credits() Returns {} on API failure Yes
check_credits_and_notify() Raises RuntimeError if API fails or response is malformed Raises on purpose
call_llm() Raises RuntimeError (network) or ValueError (bad JSON) after 1 auto-retry Raises on purpose

๐Ÿง  Example Use Cases

Basic Data Storage

import waveassist
waveassist.init()  # Auto-initialized from .env or worker

# Store GitHub PR data
waveassist.store_data("latest_pr", {
    "title": "Fix bug in auth",
    "author": "alice",
    "status": "open"
})

# Later, fetch it for further processing
pr = waveassist.fetch_data("latest_pr")
print(pr["title"])

LLM Integration with Credit Management

import waveassist
from pydantic import BaseModel

waveassist.init()

# Store OpenRouter API key
waveassist.store_data('open_router_key', 'your_api_key')

# Check credits before expensive operation
required_credits = 5.0
if waveassist.check_credits_and_notify(required_credits, "MyAssistant"):
    # Use LLM with structured output
    class AnalysisResult(BaseModel):
        summary: str
        confidence: float
        recommendations: list[str]

    result = waveassist.call_llm(
        model="gpt-4o",
        prompt="Analyze this data and provide recommendations...",
        response_model=AnalysisResult
    )

    # Store the structured result
    waveassist.store_data("analysis_result", result.dict())

๐Ÿค Contributing

Want to add formats, features, or cloud extensions? PRs welcome!


๐Ÿ“ฌ Contact

Need help or have feedback? Reach out at connect@waveassist.io, visit WaveAssist.io, or open an issue.


ยฉ 2026 WaveAssist

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

waveassist-0.8.0.tar.gz (46.9 kB view details)

Uploaded Source

Built Distribution

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

waveassist-0.8.0-py3-none-any.whl (23.6 kB view details)

Uploaded Python 3

File details

Details for the file waveassist-0.8.0.tar.gz.

File metadata

  • Download URL: waveassist-0.8.0.tar.gz
  • Upload date:
  • Size: 46.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for waveassist-0.8.0.tar.gz
Algorithm Hash digest
SHA256 b74e7744d6c48f79d991084a4d5d023e618764628899b1ca95f645f910ff5ac3
MD5 0398e4ccc80f2df0e1cdd0a7ff33bda1
BLAKE2b-256 80179136346902563d87071b14d6cf00651e82a3acbade673ecd981cf4a9554f

See more details on using hashes here.

Provenance

The following attestation bundles were made for waveassist-0.8.0.tar.gz:

Publisher: python-publish.yml on WaveAssist/WaveAssist

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file waveassist-0.8.0-py3-none-any.whl.

File metadata

  • Download URL: waveassist-0.8.0-py3-none-any.whl
  • Upload date:
  • Size: 23.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for waveassist-0.8.0-py3-none-any.whl
Algorithm Hash digest
SHA256 77a6727acb438a63bad119ba20fe23ad0f8145463a6bc3595ac75bfcaecbedae
MD5 08fa220fe42fe9c445d6e495fdfa3656
BLAKE2b-256 4c2f8761bab00975fa1b33c9df7bb0b3a1ac2ef3b11de2aa8638847b0c6d55c0

See more details on using hashes here.

Provenance

The following attestation bundles were made for waveassist-0.8.0-py3-none-any.whl:

Publisher: python-publish.yml on WaveAssist/WaveAssist

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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