Metadata-Version: 2.4
Name: glyph-py
Version: 1.0.1
Summary: Token-efficient serialization for AI agents
Author-email: Neumenon <contact@neumenon.ai>
License: Apache-2.0
Project-URL: Homepage, https://github.com/Neumenon/glyph
Project-URL: Documentation, https://github.com/Neumenon/glyph/tree/main/docs
Project-URL: Repository, https://github.com/Neumenon/glyph
Project-URL: Issues, https://github.com/Neumenon/glyph/issues
Keywords: serialization,json,llm,ai,tokens,glyph
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"

# GLYPH Python

Python implementation of the GLYPH codec.

The primary surface is still codec-first:
- parse and emit values
- JSON bridge helpers
- canonicalization and fingerprinting
- streaming validation

Higher-level agent helpers exist, but they are optional layers on top of the codec.

## Install

```bash
pip install glyph-py
```

## Quick Start

```python
import glyph

data = {"action": "search", "query": "weather", "max_results": 10}

text = glyph.json_to_glyph(data)
print(text)

restored = glyph.glyph_to_json(text)
assert restored == data

value = glyph.parse('{name=Alice age=30 active=t}')
print(value.get("name").as_str())
print(value.get("age").as_int())

fp = glyph.fingerprint_loose(glyph.from_json(data))
print(fp)
```

## Core Functions

| Function | Description |
|----------|-------------|
| `parse(text)` | Parse GLYPH text to `GValue` |
| `emit(value)` | Emit a `GValue` as canonical loose GLYPH |
| `json_to_glyph(data)` | Convert Python data directly to GLYPH text |
| `glyph_to_json(text)` | Parse GLYPH text to Python data |
| `from_json(data)` | Convert Python data to `GValue` |
| `to_json(value)` | Convert `GValue` to Python data |
| `fingerprint_loose(value)` | SHA-256 fingerprint of canonical loose form |
| `equal_loose(a, b)` | Equality by canonical loose form |

## Building Values

```python
from glyph import g, field

team = g.struct(
    "Team",
    field("name", g.str("Arsenal")),
    field("rank", g.int(1)),
)

print(glyph.emit(team))
```

## Streaming Validation

```python
from glyph import StreamingValidator, ToolRegistry

registry = ToolRegistry()
registry.add_tool("search", {
    "query": {"type": "str", "required": True},
    "max_results": {"type": "int", "min": 1, "max": 100},
})

validator = StreamingValidator(registry)

for token in 'search{query="glyph" max_results=5}':
    result = validator.push_token(token)

assert result.complete
assert result.valid
assert result.tool_name == "search"
```

## Optional Higher-Level Layer

The Python package also contains an optional agent-oriented runtime in `glyph.agent`.
Treat that as an example consumer of the codec layer, not the definition of the format.

For repo-wide docs, start at [../README.md](../README.md).
