originchain 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- originchain-0.3.0/.gitignore +25 -0
- originchain-0.3.0/CHANGELOG.md +47 -0
- originchain-0.3.0/PKG-INFO +154 -0
- originchain-0.3.0/README.md +125 -0
- originchain-0.3.0/originchain/__init__.py +78 -0
- originchain-0.3.0/originchain/async_client.py +471 -0
- originchain-0.3.0/originchain/client.py +596 -0
- originchain-0.3.0/originchain/errors.py +95 -0
- originchain-0.3.0/originchain/models.py +179 -0
- originchain-0.3.0/pyproject.toml +55 -0
- originchain-0.3.0/tests/__init__.py +0 -0
- originchain-0.3.0/tests/conftest.py +48 -0
- originchain-0.3.0/tests/test_e2e_live.py +83 -0
- originchain-0.3.0/tests/test_errors.py +81 -0
- originchain-0.3.0/tests/test_fts.py +55 -0
- originchain-0.3.0/tests/test_graph.py +97 -0
- originchain-0.3.0/tests/test_idempotency.py +123 -0
- originchain-0.3.0/tests/test_sql.py +86 -0
- originchain-0.3.0/tests/test_vector.py +120 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Build outputs
|
|
2
|
+
backend/target/
|
|
3
|
+
**/node_modules/
|
|
4
|
+
**/dist/
|
|
5
|
+
.build-admin/
|
|
6
|
+
|
|
7
|
+
# Local secrets / tmp
|
|
8
|
+
.env
|
|
9
|
+
.env.local
|
|
10
|
+
*.tfstate
|
|
11
|
+
*.tfstate.backup
|
|
12
|
+
.terraform/
|
|
13
|
+
.terraform.lock.hcl
|
|
14
|
+
|
|
15
|
+
# OS / editor
|
|
16
|
+
.DS_Store
|
|
17
|
+
Thumbs.db
|
|
18
|
+
.vscode/
|
|
19
|
+
.idea/
|
|
20
|
+
|
|
21
|
+
# Logs
|
|
22
|
+
*.log
|
|
23
|
+
admin-backend/logs/
|
|
24
|
+
|
|
25
|
+
# Cargo lock kept; npm lock kept
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to the OriginChain Python SDK. See the repo-root
|
|
4
|
+
`CHANGELOG.md` for engine releases.
|
|
5
|
+
|
|
6
|
+
## 0.3.0
|
|
7
|
+
|
|
8
|
+
### Changed
|
|
9
|
+
- **`vector_topk` `mode` parameter is now `"fast" | "high_recall"`** —
|
|
10
|
+
replaces the previous `"hnsw" | "bruteforce"` value space. The
|
|
11
|
+
parameter is now optional (`mode=None` by default) and is omitted
|
|
12
|
+
from the request body when unset; the server defaults to
|
|
13
|
+
`"high_recall"` when the field is absent. `"fast"` favours latency,
|
|
14
|
+
`"high_recall"` favours recall.
|
|
15
|
+
- Default `User-Agent` bumped to `originchain-python/0.3.0`.
|
|
16
|
+
|
|
17
|
+
## Unreleased
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
- **Typed methods for `/sql`, `/vector/*`, `/fts/*`, `/graph/*`.** Customers
|
|
21
|
+
no longer hand-roll dicts and parse JSON manually for the four
|
|
22
|
+
substrate-extension surfaces. New methods on both `OriginChain` and
|
|
23
|
+
`AsyncOriginChain`:
|
|
24
|
+
- `client.sql(query)` and `client.sql_one(query)` — return a
|
|
25
|
+
`SqlSelect` / `SqlInsert` / `SqlDelete` discriminated union.
|
|
26
|
+
- `client.vector_put(table, *, id, embedding, dim, metric, metadata)`
|
|
27
|
+
and `client.vector_topk(table, *, query, k, dim, metric, filter,
|
|
28
|
+
mode)` — return `list[VectorHit]`.
|
|
29
|
+
- `client.fts_index(table, field, *, doc_id, text)` and
|
|
30
|
+
`client.fts_search(table, field, *, q, mode, k)` — return
|
|
31
|
+
`list[FtsHit]`. Boolean / phrase / BM25 modes share one shape.
|
|
32
|
+
- `client.graph.{neighbors, reverse_neighbors, bfs, path, dijkstra}` —
|
|
33
|
+
return `list[Neighbor]`, `list[GraphBfsHit]`, `GraphPath`, and
|
|
34
|
+
`DijkstraResult` respectively.
|
|
35
|
+
- **Frozen-dataclass response models** — `SqlSelect`, `SqlInsert`,
|
|
36
|
+
`SqlDelete`, `VectorHit`, `FtsHit`, `Neighbor`, `GraphBfsHit`,
|
|
37
|
+
`GraphPath`, `DijkstraResult` — all hashable + immutable, snake_case
|
|
38
|
+
field names matching the wire.
|
|
39
|
+
- **`OCPaymentRequiredError`** — 402 add-on-required mapping. Surfaces
|
|
40
|
+
`addon` / `name` / `monthly_usd` / `preview` / `enterprise_only` /
|
|
41
|
+
`purchase_url` / `msg` as attributes.
|
|
42
|
+
- **Tests** under `sdk/python/tests/` using `httpx.MockTransport`. One
|
|
43
|
+
test per method on the sync client; one e2e test gated behind
|
|
44
|
+
`OC_E2E_TEST=1` against `localhost:8080`.
|
|
45
|
+
|
|
46
|
+
### Changed
|
|
47
|
+
- Default `User-Agent` bumped to `originchain-python/0.2.0`.
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: originchain
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Official Python client for OriginChain — managed database for AI applications.
|
|
5
|
+
Project-URL: Homepage, https://originchain.ai
|
|
6
|
+
Project-URL: Documentation, https://originchain.ai/docs
|
|
7
|
+
Project-URL: Source, https://github.com/silicoyn/originchain-python
|
|
8
|
+
Project-URL: Issues, https://github.com/silicoyn/originchain-python/issues
|
|
9
|
+
Author-email: Silicoyn Technologies <support@originchain.ai>
|
|
10
|
+
License: Proprietary
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Requires-Python: >=3.9
|
|
17
|
+
Requires-Dist: httpx<1,>=0.27
|
|
18
|
+
Requires-Dist: typing-extensions>=4.7
|
|
19
|
+
Provides-Extra: async
|
|
20
|
+
Provides-Extra: dev
|
|
21
|
+
Requires-Dist: h2<5,>=4; extra == 'dev'
|
|
22
|
+
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
23
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
24
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
25
|
+
Requires-Dist: ruff>=0.5; extra == 'dev'
|
|
26
|
+
Provides-Extra: http2
|
|
27
|
+
Requires-Dist: h2<5,>=4; extra == 'http2'
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# originchain (Python)
|
|
31
|
+
|
|
32
|
+
Official Python client for [OriginChain](https://originchain.ai).
|
|
33
|
+
|
|
34
|
+
## Install
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install originchain
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Quick start
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
from originchain import OriginChain
|
|
44
|
+
|
|
45
|
+
# Reads OC_BASE_URL, OC_BEARER, OC_TENANT from env.
|
|
46
|
+
db = OriginChain.from_env()
|
|
47
|
+
|
|
48
|
+
# Register a schema.
|
|
49
|
+
db.schemas.register(open("orders.toml").read())
|
|
50
|
+
|
|
51
|
+
# Insert a row.
|
|
52
|
+
db.rows.put(
|
|
53
|
+
"trading.orders",
|
|
54
|
+
{"order_id": "o1", "symbol": "AAPL", "qty": 100},
|
|
55
|
+
idempotency_key="user-action-42",
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# Ask in natural language.
|
|
59
|
+
result = db.ask("orders for AAPL above 50 shares last week")
|
|
60
|
+
for row in result["rows"]:
|
|
61
|
+
print(row)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Async
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
import asyncio
|
|
68
|
+
from originchain import AsyncOriginChain
|
|
69
|
+
|
|
70
|
+
async def main() -> None:
|
|
71
|
+
async with AsyncOriginChain.from_env() as db:
|
|
72
|
+
await db.rows.put("trading.orders", {"order_id": "o2", "symbol": "MSFT", "qty": 50})
|
|
73
|
+
print(await db.ask("show me the largest MSFT order this hour"))
|
|
74
|
+
|
|
75
|
+
asyncio.run(main())
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## SQL
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
resp = db.sql("SELECT order_id, qty FROM trading.orders WHERE symbol = 'AAPL'")
|
|
82
|
+
for row in resp.rows:
|
|
83
|
+
print(row["order_id"], row["qty"])
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
`db.sql_one("SELECT ... LIMIT 1")` returns the first row dict (or `None`).
|
|
87
|
+
|
|
88
|
+
## Vector
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
db.vector_put("embeddings", id="doc-1", embedding=[0.1, 0.2, 0.3], dim=3)
|
|
92
|
+
hits = db.vector_topk("embeddings", query=[0.1, 0.2, 0.3], k=5, dim=3)
|
|
93
|
+
for h in hits:
|
|
94
|
+
print(h.id, h.score)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Full-text
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
db.fts_index("articles", "body", doc_id="d1", text="the quick brown fox")
|
|
101
|
+
hits = db.fts_search("articles", "body", q="quick fox", mode="bm25", k=5)
|
|
102
|
+
print([(h.doc_id, h.score) for h in hits])
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Graph
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
nbrs = db.graph.neighbors("users", rel="follows", pk="u1")
|
|
109
|
+
for n in nbrs:
|
|
110
|
+
print(n.pk)
|
|
111
|
+
result = db.graph.dijkstra("users", rel="follows", src="u1", dst="u9",
|
|
112
|
+
weights={"u1|u2": 1.0, "u2|u9": 0.5})
|
|
113
|
+
print(result.cost)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Auth
|
|
117
|
+
|
|
118
|
+
Bearer tokens are minted in the OriginChain console and scoped to a
|
|
119
|
+
single instance. Treat them like database passwords — env vars or
|
|
120
|
+
secrets manager, never committed.
|
|
121
|
+
|
|
122
|
+
## Errors
|
|
123
|
+
|
|
124
|
+
The client maps HTTP errors to a typed hierarchy:
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
from originchain import (
|
|
128
|
+
OCAuthError,
|
|
129
|
+
OCPaymentRequiredError,
|
|
130
|
+
OCRateLimitedError,
|
|
131
|
+
OCServerError,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
try:
|
|
135
|
+
db.rows.put("trading.orders", row)
|
|
136
|
+
except OCRateLimitedError as e:
|
|
137
|
+
time.sleep(e.retry_after)
|
|
138
|
+
db.rows.put("trading.orders", row)
|
|
139
|
+
except OCPaymentRequiredError as e:
|
|
140
|
+
print(f"enable {e.name} at {e.purchase_url}")
|
|
141
|
+
except OCAuthError:
|
|
142
|
+
print("rotate your bearer in the console")
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
When the leader returns 200 but synchronous replication didn't ack
|
|
146
|
+
within the configured timeout, the client emits an
|
|
147
|
+
`OCReplicationDegraded` warning. The write IS durable on the leader;
|
|
148
|
+
the warning surfaces a follower-lag signal callers can monitor or page
|
|
149
|
+
on.
|
|
150
|
+
|
|
151
|
+
## Versioning
|
|
152
|
+
|
|
153
|
+
This client follows semver. The `0.x` line is for design partners;
|
|
154
|
+
the API surface may change before `1.0`.
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# originchain (Python)
|
|
2
|
+
|
|
3
|
+
Official Python client for [OriginChain](https://originchain.ai).
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install originchain
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick start
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from originchain import OriginChain
|
|
15
|
+
|
|
16
|
+
# Reads OC_BASE_URL, OC_BEARER, OC_TENANT from env.
|
|
17
|
+
db = OriginChain.from_env()
|
|
18
|
+
|
|
19
|
+
# Register a schema.
|
|
20
|
+
db.schemas.register(open("orders.toml").read())
|
|
21
|
+
|
|
22
|
+
# Insert a row.
|
|
23
|
+
db.rows.put(
|
|
24
|
+
"trading.orders",
|
|
25
|
+
{"order_id": "o1", "symbol": "AAPL", "qty": 100},
|
|
26
|
+
idempotency_key="user-action-42",
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
# Ask in natural language.
|
|
30
|
+
result = db.ask("orders for AAPL above 50 shares last week")
|
|
31
|
+
for row in result["rows"]:
|
|
32
|
+
print(row)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Async
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
import asyncio
|
|
39
|
+
from originchain import AsyncOriginChain
|
|
40
|
+
|
|
41
|
+
async def main() -> None:
|
|
42
|
+
async with AsyncOriginChain.from_env() as db:
|
|
43
|
+
await db.rows.put("trading.orders", {"order_id": "o2", "symbol": "MSFT", "qty": 50})
|
|
44
|
+
print(await db.ask("show me the largest MSFT order this hour"))
|
|
45
|
+
|
|
46
|
+
asyncio.run(main())
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## SQL
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
resp = db.sql("SELECT order_id, qty FROM trading.orders WHERE symbol = 'AAPL'")
|
|
53
|
+
for row in resp.rows:
|
|
54
|
+
print(row["order_id"], row["qty"])
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`db.sql_one("SELECT ... LIMIT 1")` returns the first row dict (or `None`).
|
|
58
|
+
|
|
59
|
+
## Vector
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
db.vector_put("embeddings", id="doc-1", embedding=[0.1, 0.2, 0.3], dim=3)
|
|
63
|
+
hits = db.vector_topk("embeddings", query=[0.1, 0.2, 0.3], k=5, dim=3)
|
|
64
|
+
for h in hits:
|
|
65
|
+
print(h.id, h.score)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Full-text
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
db.fts_index("articles", "body", doc_id="d1", text="the quick brown fox")
|
|
72
|
+
hits = db.fts_search("articles", "body", q="quick fox", mode="bm25", k=5)
|
|
73
|
+
print([(h.doc_id, h.score) for h in hits])
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Graph
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
nbrs = db.graph.neighbors("users", rel="follows", pk="u1")
|
|
80
|
+
for n in nbrs:
|
|
81
|
+
print(n.pk)
|
|
82
|
+
result = db.graph.dijkstra("users", rel="follows", src="u1", dst="u9",
|
|
83
|
+
weights={"u1|u2": 1.0, "u2|u9": 0.5})
|
|
84
|
+
print(result.cost)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Auth
|
|
88
|
+
|
|
89
|
+
Bearer tokens are minted in the OriginChain console and scoped to a
|
|
90
|
+
single instance. Treat them like database passwords — env vars or
|
|
91
|
+
secrets manager, never committed.
|
|
92
|
+
|
|
93
|
+
## Errors
|
|
94
|
+
|
|
95
|
+
The client maps HTTP errors to a typed hierarchy:
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
from originchain import (
|
|
99
|
+
OCAuthError,
|
|
100
|
+
OCPaymentRequiredError,
|
|
101
|
+
OCRateLimitedError,
|
|
102
|
+
OCServerError,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
try:
|
|
106
|
+
db.rows.put("trading.orders", row)
|
|
107
|
+
except OCRateLimitedError as e:
|
|
108
|
+
time.sleep(e.retry_after)
|
|
109
|
+
db.rows.put("trading.orders", row)
|
|
110
|
+
except OCPaymentRequiredError as e:
|
|
111
|
+
print(f"enable {e.name} at {e.purchase_url}")
|
|
112
|
+
except OCAuthError:
|
|
113
|
+
print("rotate your bearer in the console")
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
When the leader returns 200 but synchronous replication didn't ack
|
|
117
|
+
within the configured timeout, the client emits an
|
|
118
|
+
`OCReplicationDegraded` warning. The write IS durable on the leader;
|
|
119
|
+
the warning surfaces a follower-lag signal callers can monitor or page
|
|
120
|
+
on.
|
|
121
|
+
|
|
122
|
+
## Versioning
|
|
123
|
+
|
|
124
|
+
This client follows semver. The `0.x` line is for design partners;
|
|
125
|
+
the API surface may change before `1.0`.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""OriginChain Python client.
|
|
2
|
+
|
|
3
|
+
Two clients ship in this package:
|
|
4
|
+
|
|
5
|
+
- :class:`OriginChain` — synchronous, suitable for scripts and Jupyter.
|
|
6
|
+
- :class:`AsyncOriginChain` — asyncio, suitable for ASGI / async data
|
|
7
|
+
pipelines.
|
|
8
|
+
|
|
9
|
+
Both wrap the same ``/v1`` HTTP surface that the engine exposes; they
|
|
10
|
+
encode bearer auth, idempotency keys, and retries so callers don't have
|
|
11
|
+
to repeat themselves.
|
|
12
|
+
|
|
13
|
+
Quick start::
|
|
14
|
+
|
|
15
|
+
from originchain import OriginChain
|
|
16
|
+
|
|
17
|
+
db = OriginChain.from_env() # OC_BASE_URL + OC_BEARER
|
|
18
|
+
db.schemas.register(open("orders.toml").read())
|
|
19
|
+
db.rows.put("trading.orders", {"order_id": "o1", "symbol": "AAPL", "qty": 100})
|
|
20
|
+
rows = db.ask("orders for AAPL above 50 shares last week")
|
|
21
|
+
|
|
22
|
+
The four substrate-extension surfaces (SQL, vector, full-text, graph)
|
|
23
|
+
are also typed first-class. See :class:`OriginChain.sql`,
|
|
24
|
+
``vector_topk`` / ``vector_put``, ``fts_search``, and the ``graph``
|
|
25
|
+
namespace.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from .client import OriginChain
|
|
29
|
+
from .async_client import AsyncOriginChain
|
|
30
|
+
from .errors import (
|
|
31
|
+
OCAuthError,
|
|
32
|
+
OCError,
|
|
33
|
+
OCNotFoundError,
|
|
34
|
+
OCPaymentRequiredError,
|
|
35
|
+
OCRateLimitedError,
|
|
36
|
+
OCReplicationDegraded,
|
|
37
|
+
OCServerError,
|
|
38
|
+
OCValidationError,
|
|
39
|
+
)
|
|
40
|
+
from .models import (
|
|
41
|
+
DijkstraResult,
|
|
42
|
+
FtsHit,
|
|
43
|
+
GraphBfsHit,
|
|
44
|
+
GraphPath,
|
|
45
|
+
Neighbor,
|
|
46
|
+
SqlDelete,
|
|
47
|
+
SqlInsert,
|
|
48
|
+
SqlResponse,
|
|
49
|
+
SqlSelect,
|
|
50
|
+
VectorHit,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
__all__ = [
|
|
54
|
+
"OriginChain",
|
|
55
|
+
"AsyncOriginChain",
|
|
56
|
+
# Errors
|
|
57
|
+
"OCError",
|
|
58
|
+
"OCAuthError",
|
|
59
|
+
"OCNotFoundError",
|
|
60
|
+
"OCPaymentRequiredError",
|
|
61
|
+
"OCRateLimitedError",
|
|
62
|
+
"OCServerError",
|
|
63
|
+
"OCValidationError",
|
|
64
|
+
"OCReplicationDegraded",
|
|
65
|
+
# Models
|
|
66
|
+
"SqlSelect",
|
|
67
|
+
"SqlInsert",
|
|
68
|
+
"SqlDelete",
|
|
69
|
+
"SqlResponse",
|
|
70
|
+
"VectorHit",
|
|
71
|
+
"FtsHit",
|
|
72
|
+
"Neighbor",
|
|
73
|
+
"GraphBfsHit",
|
|
74
|
+
"GraphPath",
|
|
75
|
+
"DijkstraResult",
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
__version__ = "0.3.0"
|