Metadata-Version: 2.5
Name: statejar
Version: 0.5.0rc1
Summary: Python client for the hosted StateJar memory API.
Project-URL: Homepage, https://statejar.com
Author: Team Hello World
License: StateJar SDK License
        Version 1.0
        
        Copyright (c) 2026 StateJar (Team Hello World). All rights reserved.
        
        This licence covers the StateJar software development kit published as the
        "statejar" package on the Python Package Index and the "statejar" package on
        the npm registry, in each version that includes this file (the "Package").
        The Package is a client for the hosted StateJar memory service (the
        "Service"). It is not the Service, and it is not licensed under any
        open-source licence.
        
        1. Grant of rights
        
           Subject to the conditions of this licence, the copyright holder grants you
           a worldwide, royalty-free, non-exclusive, non-transferable licence to:
        
           (a) Use. Download, install and use unmodified copies of the Package, and
               incorporate the unmodified Package as a dependency of your own
               software, for the purpose of accessing and using the Service.
        
           (b) Redistribute unmodified copies. Reproduce and redistribute exact,
               unmodified copies of the Package as published, including through
               package registries (such as the Python Package Index and the npm
               registry), their users, and any public or private mirror, cache or
               archive of those registries, provided this licence file and all
               copyright and patent notices travel with each copy.
        
           (c) Registry operations. The operator of any package registry to which the
               copyright holder uploads the Package may copy, store, publish, display,
               transmit, mirror, archive and analyse the Package (including automated
               security analysis that executes its code) as needed to operate that
               registry, as that registry's terms require.
        
        2. Restrictions
        
           Except as expressly permitted in section 1, you may not:
        
           (a) modify the Package, or create derivative works of it, for distribution,
               sublicensing or sale;
           (b) sell the Package, or distribute it for a fee, on its own;
           (c) use the Package, the Service, or any output or documentation of either,
               to build, train, benchmark for the purpose of replicating, or operate a
               product or service that competes with the Service;
           (d) reverse engineer, decompile or otherwise attempt to derive the source
               code, algorithms, models or internal structure of the Service (the
               Package's own source is provided as published and may be read);
           (e) remove, alter or obscure any copyright, patent, trademark or licence
               notice in the Package.
        
           Private modifications made solely to use the Package with the Service
           inside your own organisation are permitted, provided they are not
           distributed.
        
        3. Patent rights
        
           The Service implements the method described in Indian patent application
           No. 202621017626 ("Deterministic State-Handle Based Memory for
           Multi-Session Conversational System"). All patent rights, including the
           rights in that application and in any patent granted from it or claiming
           priority to it, are reserved.
        
           The only patent licence granted is a licence, under the copyright holder's
           patent rights, to perform the acts permitted in section 1 with the
           Package in connection with the Service. No other patent licence is
           granted, whether expressly, by implication, by estoppel or otherwise. In
           particular, no licence is granted to implement the patented method
           outside the Service.
        
        4. Service terms
        
           Use of the Service itself (accounts, API keys, usage limits and fees) is
           governed by the StateJar terms of service published at
           https://statejar.com/terms, not by this licence.
        
        5. No warranty
        
           THE PACKAGE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
           IMPLIED, INCLUDING ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
           PARTICULAR PURPOSE, ACCURACY OR NON-INFRINGEMENT.
        
        6. Limitation of liability
        
           TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL THE COPYRIGHT
           HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
           WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
           CONNECTION WITH THE PACKAGE OR ITS USE.
        
        7. Termination
        
           This licence terminates automatically if you breach any of its terms. On
           termination you must stop using and distributing the Package. Copies
           already lawfully redistributed under section 1(b) by others, and the
           rights of registry operators under section 1(c), are not affected by the
           termination of your licence.
        
        8. Changes to these terms
        
           The copyright holder may publish future versions of the Package under
           different terms. Each version of the Package is governed by the licence
           included with that version; a change of terms does not apply retroactively
           to versions already published.
        
        9. Governing law
        
           This licence is governed by the laws of India. The courts at
           Pune, Maharashtra have exclusive
           jurisdiction over any dispute arising under it.
        
        10. Contact
        
           Requests for permissions beyond this licence: mr.yashraj5233@gmail.com.
License-File: LICENSE
Keywords: agents,ai,api-client,llm,memory,statejar
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: Other/Proprietary License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Provides-Extra: test
Requires-Dist: pytest>=8; extra == 'test'
Requires-Dist: respx>=0.21; extra == 'test'
Description-Content-Type: text/markdown

# statejar (Python)

The Python client for the hosted [StateJar](https://statejar.com) memory API.

StateJar keeps conversational memory as structured, versioned state on the
StateJar service. This package sends a message to the service, gets back the
fields a question needs as `memory_context`, and hands that to **your own**
model call. It never calls a language model and never sees your provider key.

## What this package includes — and what it does not

| Included | Not included |
| --- | --- |
| `StateJar`, an HTTP client for `/memory/ingest` and `/memory/query` | Any memory engine: extraction, canonicalization, handles and versioning all run on the StateJar service |
| Typed exceptions (`StateJarError`, `StateJarAuthError`, `StateJarConnectionError`) | Any LLM client or provider integration |
| `py.typed` type information | The StateJar backend, frontend or database code |

The only runtime dependency is `httpx`. Until 0.4.1 this distribution also
carried an embedded engine (`statejar.LocalMemory`); it was removed in 0.5.0
— see [CHANGELOG.md](CHANGELOG.md).

## Licence

Free to use with the StateJar service, under the **StateJar SDK License** in
the [LICENSE](LICENSE) file included with this package. It is a proprietary
licence, not an open-source one: you may install and use the unmodified
package to access the service and redistribute unmodified copies; you may not
distribute modified versions, use the package to build a competing service,
or reverse engineer the service. Use of the service itself is governed by the
terms at https://statejar.com/terms.

## Install

```bash
pip install --pre statejar      # 0.5.0rc1, the current pre-release
```

Requires Python 3.10+. `--pre` is needed until 0.5.0 itself is published;
without it pip finds no installable release.

## Status and limits (0.5.0rc1, pre-release)

- **Tested:** the client's unit tests (HTTP mocked with respx), a clean
  install on CPython 3.11 / Linux, and an end-to-end run of the installed
  wheel against a StateJar server run locally (MariaDB 10.4). The hosted API
  (`api.statejar.com`) was not exercised by an automated test for this
  release.
- **What the service extracts is the service's behaviour, not this
  client's.** Extraction on the service is a deterministic rules tier that
  can misread a sentence; no accuracy figure is claimed in this package.


## Quickstart

Get a key on the **API Keys** page of the [console](https://statejar.com)
(keys look like `sj_live_…`). Then:

```python
from statejar import StateJar

sj = StateJar(api_key="sj_live_...", session_tag="my-app")
turn = sj.turn("My name is Meera Nair and I prefer email")

turn["memory_context"]          # prompt-ready system message for YOUR model
```

`memory_context` goes into **your own** LLM call as the system message, with
the user's text as the user message. With OpenAI, for example:

```python
from openai import OpenAI

client = OpenAI()               # reads OPENAI_API_KEY — never sent to StateJar
reply = client.chat.completions.create(
    model="gpt-4o-mini",        # the example defaults to this via OPENAI_MODEL
    messages=[
        {"role": "system", "content": turn["memory_context"]},
        {"role": "user",   "content": "Book my delivery"},
    ],
)
print(reply.choices[0].message.content)
```

That is the whole integration.

## Statements without questions

For a message that needs no answer, skip retrieval entirely:

```python
turn = sj.turn("Budget is under 25000 and the deadline is 20 September", ask=False)
# one request made; turn["memory_context"] is None
```

## Working with the turn payload

```python
turn["handle"]           # the state handle this turn produced
turn["declined"]         # values extraction refused, with reasons (e.g. a
                         # quantity offered to a money field) — never guessed
turn["subset_keys"]      # exactly which fields were disclosed, e.g. ["facts.name"]
turn["retrieval_mode"]   # field_match | intent_map | full_state | …
turn["audit_id"]         # the disclosure is audited; replay it from the console
```

## Lower-level access

```python
stored = sj.ingest("I'm from Pune")                # full ingest response
got = sj.recall("Where am I from?", audit=False)   # subset + metadata;
                                                   # audit=True pins the
                                                   # disclosure to the trail
```

`recall(audit=True)` writes the disclosure to the server-side audit trail, so
you can prove later what was sent — the same trail the console's Audit page
shows. `turn()` audits by default; `turn(text, audit=False)` skips it.

## API

| Method | Endpoint | Returns |
| --- | --- | --- |
| `ingest(text)` | `POST /memory/ingest` | `handle`, `parent_handle`, `stored`, `state`, `conflicts`, `extraction_*` |
| `recall(query, audit=False)` | `POST /memory/query` | `memory_context`, `subset`, `handle_used`, `metadata`, `audit_id` |
| `turn(text, ask=True, audit=True)` | both, ingest first | all of the above, plus `declined`, `subset_keys`, `retrieval_mode` |

`handle` and `handle_used` are `None` while a session has no stored facts.
Auth is sent as `X-API-Key`; use one `session_tag` per conversation thread.
The client holds a connection pool — close it, or use it as a context manager:

```python
with StateJar(api_key="sj_live_...", base_url="http://localhost:8000/api/v1") as sj:
    sj.turn("I prefer email")
```

## How it works

Every turn is two API calls, **in this order**, then yours:

1. **Ingest** — `POST /memory/ingest` commits the message's facts: extracted,
   canonicalized, sealed into SHA-256 content-addressed state.
2. **Recall** — `POST /memory/query` returns the stored fields the question
   needs, formatted as `memory_context`. While a session's state is small
   (under the service's threshold) the whole state is returned instead —
   `metadata.retrieval_mode` says which.
3. **Your LLM call** — `memory_context` as the system message. Your provider,
   your key, your code; StateJar is not in it.

Two guarantees live in that ordering:

* **BYOK — your key stays yours.** The provider key is used inside *your*
  process, in step 3, and is never sent to StateJar. No transcript is stored
  either: the server sees one message at a time and keeps the facts it extracts,
  not the message.
* **Ingest commits before recall runs**, so the context you send already
  contains the turn that asked the question. Reversing the order retrieves
  state from before that message existed — and the failure is invisible,
  because you still get a fluent answer, just one built on stale memory.
  `turn()` gets the order right by construction; call `ingest()` and
  `recall()` yourself only when you have a reason to.

## Errors


Everything raised is a `StateJarError`:

```python
from statejar import (StateJar, StateJarError,
                      StateJarAuthError, StateJarConnectionError)

try:
    turn = sj.turn("hi")
except StateJarAuthError:        # HTTP 401 — bad/revoked key
    ...
except StateJarConnectionError:  # unreachable host or timeout — nothing was
    ...                          # stored, so retrying ingest is safe
except StateJarError as e:       # anything else; e.status_code, e.body
    print(e.status_code, e.body)  # (decoded JSON or text) and e.response_text
```

A missing `api_key` raises at construction as a `StateJarAuthError` that is
also a `ValueError`, so code written against either earlier client still
catches it.

## Pointing at a local instance

```python
sj = StateJar(api_key="sj_live_...", base_url="http://localhost:8000/api/v1")
```

## Development

```bash
cd sdk && pip install -e ".[dev]" && pytest     # ".[test]" is the same set
```

The tests mock HTTP with respx at the httpx client seam — no network, no
server needed.

Copyright (c) 2026 StateJar. All rights reserved. The StateJar service
implements the method described in Indian patent application No.
202621017626 (filed and published, not granted); see section 3 of
[LICENSE](LICENSE) for the patent terms.
