fluctlightdb 0.4.2__tar.gz → 0.4.3__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.
- {fluctlightdb-0.4.2 → fluctlightdb-0.4.3}/PKG-INFO +20 -5
- {fluctlightdb-0.4.2 → fluctlightdb-0.4.3}/README.md +18 -3
- {fluctlightdb-0.4.2 → fluctlightdb-0.4.3}/fluctlightdb/__init__.py +3 -0
- fluctlightdb-0.4.3/fluctlightdb/brain.py +151 -0
- {fluctlightdb-0.4.2 → fluctlightdb-0.4.3}/fluctlightdb/worker.py +56 -22
- {fluctlightdb-0.4.2 → fluctlightdb-0.4.3}/fluctlightdb.egg-info/PKG-INFO +20 -5
- {fluctlightdb-0.4.2 → fluctlightdb-0.4.3}/fluctlightdb.egg-info/SOURCES.txt +1 -0
- fluctlightdb-0.4.3/fluctlightdb.egg-info/requires.txt +3 -0
- {fluctlightdb-0.4.2 → fluctlightdb-0.4.3}/pyproject.toml +2 -2
- fluctlightdb-0.4.2/fluctlightdb.egg-info/requires.txt +0 -3
- {fluctlightdb-0.4.2 → fluctlightdb-0.4.3}/LICENSE +0 -0
- {fluctlightdb-0.4.2 → fluctlightdb-0.4.3}/fluctlightdb.egg-info/dependency_links.txt +0 -0
- {fluctlightdb-0.4.2 → fluctlightdb-0.4.3}/fluctlightdb.egg-info/top_level.txt +0 -0
- {fluctlightdb-0.4.2 → fluctlightdb-0.4.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fluctlightdb
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.3
|
|
4
4
|
Summary: Python client for FluctlightDB — brain-native memory for AI agents
|
|
5
5
|
Author-email: Voxmastery <voxmastery@roppashreeganesh.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -23,7 +23,7 @@ Requires-Python: >=3.9
|
|
|
23
23
|
Description-Content-Type: text/markdown
|
|
24
24
|
License-File: LICENSE
|
|
25
25
|
Provides-Extra: native
|
|
26
|
-
Requires-Dist: fluctlightdb-native>=0.4.
|
|
26
|
+
Requires-Dist: fluctlightdb-native>=0.4.3; extra == "native"
|
|
27
27
|
Dynamic: license-file
|
|
28
28
|
|
|
29
29
|
# fluctlightdb
|
|
@@ -32,10 +32,20 @@ Python client for [FluctlightDB](https://github.com/voxmastery/FluctlightDB) —
|
|
|
32
32
|
|
|
33
33
|
## Install
|
|
34
34
|
|
|
35
|
+
On **Debian/Ubuntu 23.04+**, **Debian 12+**, and **Fedora 38+**, system Python is [PEP 668](https://peps.python.org/pep-0668/) *externally managed* — bare `pip install` fails with `externally-managed-environment`. Use a **virtual environment** (same as any other PyPI library):
|
|
36
|
+
|
|
35
37
|
```bash
|
|
38
|
+
python3 -m venv .venv
|
|
39
|
+
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
|
36
40
|
pip install fluctlightdb
|
|
37
41
|
```
|
|
38
42
|
|
|
43
|
+
From a clone of this repo you can also run:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
./scripts/install-python-client.sh
|
|
47
|
+
```
|
|
48
|
+
|
|
39
49
|
Optional in-process recall (Rust extension, when wheels are available for your platform):
|
|
40
50
|
|
|
41
51
|
```bash
|
|
@@ -75,17 +85,22 @@ client = FluctlightClient.from_env()
|
|
|
75
85
|
print(client.activate("dark mode"))
|
|
76
86
|
```
|
|
77
87
|
|
|
78
|
-
## In-process
|
|
88
|
+
## In-process brain (like `sqlite3`)
|
|
79
89
|
|
|
80
90
|
When `fluctlightdb-native` is installed:
|
|
81
91
|
|
|
82
92
|
```python
|
|
83
|
-
from fluctlightdb import
|
|
93
|
+
from fluctlightdb import connect
|
|
84
94
|
|
|
85
|
-
brain =
|
|
95
|
+
brain = connect("/tmp/my-agent-brain")
|
|
96
|
+
brain.experience("user prefers dark mode", context="settings")
|
|
86
97
|
print(brain.activate("dark mode"))
|
|
87
98
|
```
|
|
88
99
|
|
|
100
|
+
Read-only recall path: `get_recall_client(path)`.
|
|
101
|
+
|
|
102
|
+
## In-process recall (read-only helper)
|
|
103
|
+
|
|
89
104
|
## Docs
|
|
90
105
|
|
|
91
106
|
- [Getting started](https://github.com/voxmastery/FluctlightDB/blob/main/docs/GETTING_STARTED.md)
|
|
@@ -4,10 +4,20 @@ Python client for [FluctlightDB](https://github.com/voxmastery/FluctlightDB) —
|
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
|
+
On **Debian/Ubuntu 23.04+**, **Debian 12+**, and **Fedora 38+**, system Python is [PEP 668](https://peps.python.org/pep-0668/) *externally managed* — bare `pip install` fails with `externally-managed-environment`. Use a **virtual environment** (same as any other PyPI library):
|
|
8
|
+
|
|
7
9
|
```bash
|
|
10
|
+
python3 -m venv .venv
|
|
11
|
+
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
|
8
12
|
pip install fluctlightdb
|
|
9
13
|
```
|
|
10
14
|
|
|
15
|
+
From a clone of this repo you can also run:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
./scripts/install-python-client.sh
|
|
19
|
+
```
|
|
20
|
+
|
|
11
21
|
Optional in-process recall (Rust extension, when wheels are available for your platform):
|
|
12
22
|
|
|
13
23
|
```bash
|
|
@@ -47,17 +57,22 @@ client = FluctlightClient.from_env()
|
|
|
47
57
|
print(client.activate("dark mode"))
|
|
48
58
|
```
|
|
49
59
|
|
|
50
|
-
## In-process
|
|
60
|
+
## In-process brain (like `sqlite3`)
|
|
51
61
|
|
|
52
62
|
When `fluctlightdb-native` is installed:
|
|
53
63
|
|
|
54
64
|
```python
|
|
55
|
-
from fluctlightdb import
|
|
65
|
+
from fluctlightdb import connect
|
|
56
66
|
|
|
57
|
-
brain =
|
|
67
|
+
brain = connect("/tmp/my-agent-brain")
|
|
68
|
+
brain.experience("user prefers dark mode", context="settings")
|
|
58
69
|
print(brain.activate("dark mode"))
|
|
59
70
|
```
|
|
60
71
|
|
|
72
|
+
Read-only recall path: `get_recall_client(path)`.
|
|
73
|
+
|
|
74
|
+
## In-process recall (read-only helper)
|
|
75
|
+
|
|
61
76
|
## Docs
|
|
62
77
|
|
|
63
78
|
- [Getting started](https://github.com/voxmastery/FluctlightDB/blob/main/docs/GETTING_STARTED.md)
|
|
@@ -11,12 +11,15 @@ import urllib.request
|
|
|
11
11
|
from dataclasses import dataclass, field
|
|
12
12
|
from typing import Any, Optional
|
|
13
13
|
|
|
14
|
+
from .brain import FluctlightBrain, connect
|
|
14
15
|
from .worker import FluctlightNative, FluctlightWorker, get_recall_client, get_worker
|
|
15
16
|
|
|
16
17
|
__all__ = [
|
|
17
18
|
"FluctlightClient",
|
|
19
|
+
"FluctlightBrain",
|
|
18
20
|
"FluctlightNative",
|
|
19
21
|
"FluctlightWorker",
|
|
22
|
+
"connect",
|
|
20
23
|
"get_recall_client",
|
|
21
24
|
"get_worker",
|
|
22
25
|
]
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"""Embedded brain client — sqlite3-style in-process API when native is installed."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import os
|
|
7
|
+
from typing import Any, Optional
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class FluctlightBrain:
|
|
11
|
+
"""In-process Fluctlight brain (like ``sqlite3.connect``). Requires ``fluctlightdb-native``."""
|
|
12
|
+
|
|
13
|
+
def __init__(self, brain: Any, *, readonly: bool = False) -> None:
|
|
14
|
+
self._brain = brain
|
|
15
|
+
self.readonly = readonly
|
|
16
|
+
self.brain_path: Optional[str] = getattr(brain, "brain_path", None)
|
|
17
|
+
|
|
18
|
+
@classmethod
|
|
19
|
+
def connect(cls, path: str, *, readonly: bool = False) -> "FluctlightBrain":
|
|
20
|
+
import fluctlightdb_native as native # type: ignore
|
|
21
|
+
|
|
22
|
+
brain = native.Brain.open_readonly(path) if readonly else native.Brain.open(path)
|
|
23
|
+
obj = cls(brain, readonly=readonly)
|
|
24
|
+
obj.brain_path = path
|
|
25
|
+
return obj
|
|
26
|
+
|
|
27
|
+
@classmethod
|
|
28
|
+
def new(cls) -> "FluctlightBrain":
|
|
29
|
+
import fluctlightdb_native as native # type: ignore
|
|
30
|
+
|
|
31
|
+
return cls(native.Brain.new(), readonly=False)
|
|
32
|
+
|
|
33
|
+
def experience(
|
|
34
|
+
self,
|
|
35
|
+
content: str,
|
|
36
|
+
*,
|
|
37
|
+
context: str = "api",
|
|
38
|
+
salience: float = 0.5,
|
|
39
|
+
outcome: Optional[str] = None,
|
|
40
|
+
semantic_vector: Optional[list[float]] = None,
|
|
41
|
+
agent_id: Optional[str] = None,
|
|
42
|
+
tenant_id: Optional[str] = None,
|
|
43
|
+
verified: Optional[bool] = None,
|
|
44
|
+
provenance_kind: Optional[str] = None,
|
|
45
|
+
source_uri: Optional[str] = None,
|
|
46
|
+
confidence: Optional[float] = None,
|
|
47
|
+
doc_id: Optional[str] = None,
|
|
48
|
+
chunk_id: Optional[str] = None,
|
|
49
|
+
**extra: Any,
|
|
50
|
+
) -> dict[str, Any]:
|
|
51
|
+
payload: dict[str, Any] = {
|
|
52
|
+
"content": content,
|
|
53
|
+
"context": context,
|
|
54
|
+
"salience_hint": salience,
|
|
55
|
+
}
|
|
56
|
+
if outcome is not None:
|
|
57
|
+
payload["outcome"] = outcome
|
|
58
|
+
if semantic_vector is not None:
|
|
59
|
+
payload["semantic_vector"] = semantic_vector
|
|
60
|
+
if agent_id is not None:
|
|
61
|
+
payload["agent_id"] = agent_id
|
|
62
|
+
if tenant_id is not None:
|
|
63
|
+
payload["tenant_id"] = tenant_id
|
|
64
|
+
if doc_id or chunk_id or source_uri:
|
|
65
|
+
payload["rag"] = {
|
|
66
|
+
"doc_id": doc_id,
|
|
67
|
+
"chunk_id": chunk_id,
|
|
68
|
+
"source_uri": source_uri,
|
|
69
|
+
}
|
|
70
|
+
if verified is not None or provenance_kind or source_uri:
|
|
71
|
+
payload["provenance"] = {
|
|
72
|
+
"kind": provenance_kind or "ledger_verified",
|
|
73
|
+
"source_uri": source_uri,
|
|
74
|
+
"confidence": confidence if confidence is not None else 0.95,
|
|
75
|
+
"verified": bool(verified),
|
|
76
|
+
}
|
|
77
|
+
payload.update(extra)
|
|
78
|
+
return self._brain.experience(json.dumps(payload))
|
|
79
|
+
|
|
80
|
+
def activate(
|
|
81
|
+
self,
|
|
82
|
+
cue: str,
|
|
83
|
+
semantic_vector: Optional[list[float]] = None,
|
|
84
|
+
agent_id: Optional[str] = None,
|
|
85
|
+
limit: Optional[int] = None,
|
|
86
|
+
) -> dict[str, Any]:
|
|
87
|
+
return self._brain.activate(cue, semantic_vector, agent_id, limit)
|
|
88
|
+
|
|
89
|
+
def activate_batch(
|
|
90
|
+
self,
|
|
91
|
+
items: list[dict[str, Any]],
|
|
92
|
+
limit: Optional[int] = None,
|
|
93
|
+
) -> dict[str, Any]:
|
|
94
|
+
return self._brain.activate_batch_json(json.dumps(items), limit)
|
|
95
|
+
|
|
96
|
+
def verify_fact(
|
|
97
|
+
self,
|
|
98
|
+
engram_id: str,
|
|
99
|
+
*,
|
|
100
|
+
provenance_kind: str = "ledger_verified",
|
|
101
|
+
source_uri: Optional[str] = None,
|
|
102
|
+
confidence: float = 0.95,
|
|
103
|
+
) -> None:
|
|
104
|
+
self._brain.verify_fact(engram_id, provenance_kind, source_uri, confidence)
|
|
105
|
+
|
|
106
|
+
def sleep(self) -> dict[str, Any]:
|
|
107
|
+
return self._brain.sleep()
|
|
108
|
+
|
|
109
|
+
def tick(self, n: int = 1) -> list[dict[str, Any]]:
|
|
110
|
+
return self._brain.tick(n)
|
|
111
|
+
|
|
112
|
+
def preplay(self, goal: str, steps: int = 4) -> dict[str, Any]:
|
|
113
|
+
return self._brain.preplay(goal, steps)
|
|
114
|
+
|
|
115
|
+
def neurogenesis(self) -> dict[str, Any]:
|
|
116
|
+
return self._brain.neurogenesis_pulse()
|
|
117
|
+
|
|
118
|
+
def compact(self) -> dict[str, Any]:
|
|
119
|
+
return self._brain.compact()
|
|
120
|
+
|
|
121
|
+
def reward(self, magnitude: float = 0.5) -> None:
|
|
122
|
+
self._brain.reward(magnitude)
|
|
123
|
+
|
|
124
|
+
def mark_core(self, engram_id: str, key: str) -> None:
|
|
125
|
+
self._brain.mark_core(engram_id, key)
|
|
126
|
+
|
|
127
|
+
def death(self, cause: str = "api") -> str:
|
|
128
|
+
return str(self._brain.death(cause))
|
|
129
|
+
|
|
130
|
+
def status(self) -> dict[str, Any]:
|
|
131
|
+
return self._brain.status()
|
|
132
|
+
|
|
133
|
+
def stage_report(self) -> dict[str, Any]:
|
|
134
|
+
return self._brain.stage_report()
|
|
135
|
+
|
|
136
|
+
def verified_context(self, limit: int = 12) -> dict[str, Any]:
|
|
137
|
+
return self._brain.verified_context(limit)
|
|
138
|
+
|
|
139
|
+
def stage(self) -> str:
|
|
140
|
+
return str(self._brain.stage())
|
|
141
|
+
|
|
142
|
+
def checkpoint(self) -> None:
|
|
143
|
+
self._brain.checkpoint()
|
|
144
|
+
|
|
145
|
+
def has_sidecar_index(self) -> bool:
|
|
146
|
+
return bool(self._brain.has_sidecar_index())
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def connect(path: str, *, readonly: bool = False) -> FluctlightBrain:
|
|
150
|
+
"""Open a brain directory like ``sqlite3.connect(path)``."""
|
|
151
|
+
return FluctlightBrain.connect(path, readonly=readonly)
|
|
@@ -58,6 +58,7 @@ class FluctlightNative:
|
|
|
58
58
|
else:
|
|
59
59
|
self._brain = native.Brain.open(brain_path)
|
|
60
60
|
self.brain_path = brain_path
|
|
61
|
+
self.readonly = readonly
|
|
61
62
|
|
|
62
63
|
def activate(
|
|
63
64
|
self,
|
|
@@ -75,15 +76,55 @@ class FluctlightNative:
|
|
|
75
76
|
) -> dict[str, Any]:
|
|
76
77
|
return self._brain.activate_batch_json(json.dumps(items), limit)
|
|
77
78
|
|
|
79
|
+
def experience(self, episode_json: str) -> dict[str, Any]:
|
|
80
|
+
if self.readonly:
|
|
81
|
+
raise RuntimeError("brain opened readonly — reopen with readonly=False")
|
|
82
|
+
return self._brain.experience(episode_json)
|
|
83
|
+
|
|
84
|
+
def experience_dict(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
85
|
+
return self.experience(json.dumps(payload))
|
|
86
|
+
|
|
87
|
+
def verify_fact(
|
|
88
|
+
self,
|
|
89
|
+
engram_id: str,
|
|
90
|
+
provenance_kind: str = "ledger_verified",
|
|
91
|
+
source_uri: Optional[str] = None,
|
|
92
|
+
confidence: float = 0.95,
|
|
93
|
+
) -> None:
|
|
94
|
+
if self.readonly:
|
|
95
|
+
raise RuntimeError("brain opened readonly")
|
|
96
|
+
self._brain.verify_fact(engram_id, provenance_kind, source_uri, confidence)
|
|
97
|
+
|
|
98
|
+
def sleep(self) -> dict[str, Any]:
|
|
99
|
+
if self.readonly:
|
|
100
|
+
raise RuntimeError("brain opened readonly")
|
|
101
|
+
return self._brain.sleep()
|
|
102
|
+
|
|
103
|
+
def tick(self, n: int = 1) -> list[dict[str, Any]]:
|
|
104
|
+
if self.readonly:
|
|
105
|
+
raise RuntimeError("brain opened readonly")
|
|
106
|
+
return self._brain.tick(n)
|
|
107
|
+
|
|
108
|
+
def preplay(self, goal: str, steps: int = 4) -> dict[str, Any]:
|
|
109
|
+
return self._brain.preplay(goal, steps)
|
|
110
|
+
|
|
78
111
|
def status(self) -> dict[str, Any]:
|
|
79
112
|
return self._brain.status()
|
|
80
113
|
|
|
114
|
+
def stage_report(self) -> dict[str, Any]:
|
|
115
|
+
return self._brain.stage_report()
|
|
116
|
+
|
|
81
117
|
def verified_context(self, limit: int = 12) -> dict[str, Any]:
|
|
82
118
|
return self._brain.verified_context(limit)
|
|
83
119
|
|
|
84
120
|
def has_sidecar_index(self) -> bool:
|
|
85
121
|
return bool(self._brain.has_sidecar_index())
|
|
86
122
|
|
|
123
|
+
def checkpoint(self) -> None:
|
|
124
|
+
if self.readonly:
|
|
125
|
+
raise RuntimeError("brain opened readonly")
|
|
126
|
+
self._brain.checkpoint()
|
|
127
|
+
|
|
87
128
|
|
|
88
129
|
class FluctlightWorker:
|
|
89
130
|
"""Long-lived `fluctlight worker` subprocess — brain loaded once, sub-ms recall."""
|
|
@@ -118,7 +159,8 @@ class FluctlightWorker:
|
|
|
118
159
|
with self._lock:
|
|
119
160
|
if self._proc and self._proc.poll() is None:
|
|
120
161
|
try:
|
|
121
|
-
self.
|
|
162
|
+
self._proc.stdin.write('{"op":"shutdown"}\n')
|
|
163
|
+
self._proc.stdin.flush()
|
|
122
164
|
except Exception:
|
|
123
165
|
pass
|
|
124
166
|
self._proc.terminate()
|
|
@@ -128,24 +170,18 @@ class FluctlightWorker:
|
|
|
128
170
|
with self._lock:
|
|
129
171
|
if self._proc is None or self._proc.poll() is not None:
|
|
130
172
|
self._start()
|
|
131
|
-
assert self._proc
|
|
132
|
-
assert self._proc.stdin is not None
|
|
133
|
-
assert self._proc.stdout is not None
|
|
173
|
+
assert self._proc and self._proc.stdin and self._proc.stdout
|
|
134
174
|
self._id += 1
|
|
135
|
-
req = {"
|
|
175
|
+
req = {"id": self._id, "op": op, **kwargs}
|
|
136
176
|
self._proc.stdin.write(json.dumps(req) + "\n")
|
|
137
177
|
self._proc.stdin.flush()
|
|
138
178
|
line = self._proc.stdout.readline()
|
|
139
179
|
if not line:
|
|
140
|
-
|
|
141
|
-
raise RuntimeError(f"worker closed: {err}")
|
|
180
|
+
raise RuntimeError("worker closed stdout")
|
|
142
181
|
resp = json.loads(line)
|
|
143
|
-
if
|
|
144
|
-
raise RuntimeError(resp
|
|
145
|
-
return resp
|
|
146
|
-
|
|
147
|
-
def ping(self) -> bool:
|
|
148
|
-
return bool(self._call("ping").get("pong"))
|
|
182
|
+
if "error" in resp:
|
|
183
|
+
raise RuntimeError(resp["error"])
|
|
184
|
+
return resp.get("result", resp)
|
|
149
185
|
|
|
150
186
|
def activate(
|
|
151
187
|
self,
|
|
@@ -161,21 +197,17 @@ class FluctlightWorker:
|
|
|
161
197
|
payload["agent_id"] = agent_id
|
|
162
198
|
if limit is not None:
|
|
163
199
|
payload["limit"] = limit
|
|
164
|
-
return self._call("activate", **payload)
|
|
200
|
+
return self._call("activate", **payload)
|
|
165
201
|
|
|
166
202
|
def activate_batch(
|
|
167
203
|
self,
|
|
168
204
|
items: list[dict[str, Any]],
|
|
169
205
|
limit: Optional[int] = None,
|
|
170
206
|
) -> dict[str, Any]:
|
|
171
|
-
|
|
172
|
-
if limit is not None:
|
|
173
|
-
payload["limit"] = limit
|
|
174
|
-
resp = self._call("activate_batch", **payload)
|
|
175
|
-
return {"results": resp.get("results") or [], "count": resp.get("count", 0)}
|
|
207
|
+
return self._call("activate_batch", batch=items, limit=limit)
|
|
176
208
|
|
|
177
209
|
def status(self) -> dict[str, Any]:
|
|
178
|
-
return self._call("status")
|
|
210
|
+
return self._call("status")
|
|
179
211
|
|
|
180
212
|
def verified_context(self, limit: int = 12) -> dict[str, Any]:
|
|
181
213
|
return self._call("verified_context", limit=limit)["context"]
|
|
@@ -192,6 +224,8 @@ _client_lock = threading.Lock()
|
|
|
192
224
|
def get_recall_client(
|
|
193
225
|
brain_path: Optional[str] = None,
|
|
194
226
|
bin_path: Optional[str] = None,
|
|
227
|
+
*,
|
|
228
|
+
readonly: bool = True,
|
|
195
229
|
) -> RecallClient:
|
|
196
230
|
"""Best available in-process recall: native library > worker subprocess."""
|
|
197
231
|
global _native_singleton, _worker_singleton
|
|
@@ -210,7 +244,7 @@ def get_recall_client(
|
|
|
210
244
|
with _client_lock:
|
|
211
245
|
if prefer_native and _native_singleton is None:
|
|
212
246
|
try:
|
|
213
|
-
_native_singleton = FluctlightNative(path, readonly=
|
|
247
|
+
_native_singleton = FluctlightNative(path, readonly=readonly)
|
|
214
248
|
return _native_singleton
|
|
215
249
|
except ImportError:
|
|
216
250
|
pass
|
|
@@ -227,7 +261,7 @@ def get_worker(
|
|
|
227
261
|
brain_path: Optional[str] = None,
|
|
228
262
|
bin_path: Optional[str] = None,
|
|
229
263
|
) -> FluctlightWorker:
|
|
230
|
-
client = get_recall_client(brain_path=brain_path, bin_path=bin_path)
|
|
264
|
+
client = get_recall_client(brain_path=brain_path, bin_path=bin_path, readonly=True)
|
|
231
265
|
if isinstance(client, FluctlightWorker):
|
|
232
266
|
return client
|
|
233
267
|
raise TypeError("native client active — use get_recall_client() instead")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fluctlightdb
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.3
|
|
4
4
|
Summary: Python client for FluctlightDB — brain-native memory for AI agents
|
|
5
5
|
Author-email: Voxmastery <voxmastery@roppashreeganesh.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -23,7 +23,7 @@ Requires-Python: >=3.9
|
|
|
23
23
|
Description-Content-Type: text/markdown
|
|
24
24
|
License-File: LICENSE
|
|
25
25
|
Provides-Extra: native
|
|
26
|
-
Requires-Dist: fluctlightdb-native>=0.4.
|
|
26
|
+
Requires-Dist: fluctlightdb-native>=0.4.3; extra == "native"
|
|
27
27
|
Dynamic: license-file
|
|
28
28
|
|
|
29
29
|
# fluctlightdb
|
|
@@ -32,10 +32,20 @@ Python client for [FluctlightDB](https://github.com/voxmastery/FluctlightDB) —
|
|
|
32
32
|
|
|
33
33
|
## Install
|
|
34
34
|
|
|
35
|
+
On **Debian/Ubuntu 23.04+**, **Debian 12+**, and **Fedora 38+**, system Python is [PEP 668](https://peps.python.org/pep-0668/) *externally managed* — bare `pip install` fails with `externally-managed-environment`. Use a **virtual environment** (same as any other PyPI library):
|
|
36
|
+
|
|
35
37
|
```bash
|
|
38
|
+
python3 -m venv .venv
|
|
39
|
+
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
|
36
40
|
pip install fluctlightdb
|
|
37
41
|
```
|
|
38
42
|
|
|
43
|
+
From a clone of this repo you can also run:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
./scripts/install-python-client.sh
|
|
47
|
+
```
|
|
48
|
+
|
|
39
49
|
Optional in-process recall (Rust extension, when wheels are available for your platform):
|
|
40
50
|
|
|
41
51
|
```bash
|
|
@@ -75,17 +85,22 @@ client = FluctlightClient.from_env()
|
|
|
75
85
|
print(client.activate("dark mode"))
|
|
76
86
|
```
|
|
77
87
|
|
|
78
|
-
## In-process
|
|
88
|
+
## In-process brain (like `sqlite3`)
|
|
79
89
|
|
|
80
90
|
When `fluctlightdb-native` is installed:
|
|
81
91
|
|
|
82
92
|
```python
|
|
83
|
-
from fluctlightdb import
|
|
93
|
+
from fluctlightdb import connect
|
|
84
94
|
|
|
85
|
-
brain =
|
|
95
|
+
brain = connect("/tmp/my-agent-brain")
|
|
96
|
+
brain.experience("user prefers dark mode", context="settings")
|
|
86
97
|
print(brain.activate("dark mode"))
|
|
87
98
|
```
|
|
88
99
|
|
|
100
|
+
Read-only recall path: `get_recall_client(path)`.
|
|
101
|
+
|
|
102
|
+
## In-process recall (read-only helper)
|
|
103
|
+
|
|
89
104
|
## Docs
|
|
90
105
|
|
|
91
106
|
- [Getting started](https://github.com/voxmastery/FluctlightDB/blob/main/docs/GETTING_STARTED.md)
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "fluctlightdb"
|
|
7
|
-
version = "0.4.
|
|
7
|
+
version = "0.4.3"
|
|
8
8
|
description = "Python client for FluctlightDB — brain-native memory for AI agents"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -32,7 +32,7 @@ Repository = "https://github.com/voxmastery/FluctlightDB"
|
|
|
32
32
|
Issues = "https://github.com/voxmastery/FluctlightDB/issues"
|
|
33
33
|
|
|
34
34
|
[project.optional-dependencies]
|
|
35
|
-
native = ["fluctlightdb-native>=0.4.
|
|
35
|
+
native = ["fluctlightdb-native>=0.4.3"]
|
|
36
36
|
|
|
37
37
|
[tool.setuptools.packages.find]
|
|
38
38
|
where = ["."]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|