oortmem 0.2.0__py3-none-any.whl
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.
- oortmem/__init__.py +3 -0
- oortmem/__main__.py +5 -0
- oortmem/cli.py +108 -0
- oortmem-0.2.0.dist-info/METADATA +36 -0
- oortmem-0.2.0.dist-info/RECORD +7 -0
- oortmem-0.2.0.dist-info/WHEEL +4 -0
- oortmem-0.2.0.dist-info/entry_points.txt +3 -0
oortmem/__init__.py
ADDED
oortmem/__main__.py
ADDED
oortmem/cli.py
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""Run the Oort CLI from Python.
|
|
2
|
+
|
|
3
|
+
Oort is written in TypeScript and ships on npm as `oortmem`; it needs Node 22.15 or newer.
|
|
4
|
+
This launcher runs an `oort` command that is already installed. Otherwise it runs the
|
|
5
|
+
matching npm release through npx. Arguments, stdin, stdout and the exit code pass through
|
|
6
|
+
unchanged.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
import re
|
|
13
|
+
import shutil
|
|
14
|
+
import subprocess
|
|
15
|
+
import sys
|
|
16
|
+
from typing import Callable, Iterable, Optional, Sequence
|
|
17
|
+
|
|
18
|
+
from . import __version__
|
|
19
|
+
|
|
20
|
+
MIN_NODE = (22, 15)
|
|
21
|
+
NPM_SPEC = f"oortmem@{__version__}"
|
|
22
|
+
# Set on the child so a launcher that finds itself (or another copy of itself) on PATH
|
|
23
|
+
# skips the PATH lookup instead of starting itself forever.
|
|
24
|
+
GUARD = "OORTMEM_PY_LAUNCHER"
|
|
25
|
+
|
|
26
|
+
HELP = f"""oort needs Node.js {MIN_NODE[0]}.{MIN_NODE[1]} or newer, and none was found.
|
|
27
|
+
|
|
28
|
+
Install Node from https://nodejs.org, then run this command again. Or install the CLI
|
|
29
|
+
directly with npm:
|
|
30
|
+
|
|
31
|
+
npm install -g oortmem
|
|
32
|
+
|
|
33
|
+
Docs: https://oortcloud.dev/docs
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def node_version(node: str) -> Optional[tuple[int, int]]:
|
|
38
|
+
"""The (major, minor) of `node --version`, or None when it cannot be run or read."""
|
|
39
|
+
try:
|
|
40
|
+
out = subprocess.run(
|
|
41
|
+
[node, "--version"], capture_output=True, text=True, timeout=10, check=False
|
|
42
|
+
).stdout
|
|
43
|
+
except (OSError, subprocess.SubprocessError):
|
|
44
|
+
return None
|
|
45
|
+
m = re.match(r"v?(\d+)\.(\d+)", out.strip())
|
|
46
|
+
return (int(m.group(1)), int(m.group(2))) if m else None
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def path_candidates(name: str, path: Optional[str]) -> Iterable[str]:
|
|
50
|
+
"""Every executable called `name` on PATH, in PATH order."""
|
|
51
|
+
seen = set()
|
|
52
|
+
for d in (path or "").split(os.pathsep):
|
|
53
|
+
if not d:
|
|
54
|
+
continue
|
|
55
|
+
found = shutil.which(name, path=d)
|
|
56
|
+
if found and found not in seen:
|
|
57
|
+
seen.add(found)
|
|
58
|
+
yield found
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def same_file(a: str, b: Optional[str]) -> bool:
|
|
62
|
+
if not b:
|
|
63
|
+
return False
|
|
64
|
+
try:
|
|
65
|
+
return os.path.samefile(a, b)
|
|
66
|
+
except OSError:
|
|
67
|
+
return False
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def resolve(
|
|
71
|
+
env: Optional[dict] = None,
|
|
72
|
+
self_path: Optional[str] = None,
|
|
73
|
+
candidates: Callable[[str, Optional[str]], Iterable[str]] = path_candidates,
|
|
74
|
+
which: Callable[[str], Optional[str]] = shutil.which,
|
|
75
|
+
version: Callable[[str], Optional[tuple[int, int]]] = node_version,
|
|
76
|
+
) -> Optional[list[str]]:
|
|
77
|
+
"""The command to run: an installed `oort`, else npx with the pinned release, else None."""
|
|
78
|
+
env = os.environ if env is None else env
|
|
79
|
+
if not env.get(GUARD):
|
|
80
|
+
for oort in candidates("oort", env.get("PATH")):
|
|
81
|
+
if not same_file(oort, self_path):
|
|
82
|
+
return [oort]
|
|
83
|
+
node, npx = which("node"), which("npx")
|
|
84
|
+
if node and npx:
|
|
85
|
+
v = version(node)
|
|
86
|
+
if v is not None and v >= MIN_NODE:
|
|
87
|
+
return [npx, "--yes", NPM_SPEC]
|
|
88
|
+
return None
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def main(argv: Optional[Sequence[str]] = None) -> int:
|
|
92
|
+
args = list(sys.argv[1:] if argv is None else argv)
|
|
93
|
+
if args == ["--launcher-version"]:
|
|
94
|
+
print(f"oortmem (Python launcher) {__version__}, runs {NPM_SPEC}")
|
|
95
|
+
return 0
|
|
96
|
+
self_path = shutil.which(sys.argv[0]) or sys.argv[0]
|
|
97
|
+
cmd = resolve(self_path=self_path)
|
|
98
|
+
if cmd is None:
|
|
99
|
+
sys.stderr.write(HELP)
|
|
100
|
+
return 1
|
|
101
|
+
try:
|
|
102
|
+
return subprocess.call(cmd + args, env={**os.environ, GUARD: "1"})
|
|
103
|
+
except KeyboardInterrupt:
|
|
104
|
+
return 130
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
if __name__ == "__main__":
|
|
108
|
+
sys.exit(main())
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: oortmem
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Open-source memory for AI agents. Runs the Oort CLI (Node 22.15 or newer) from Python.
|
|
5
|
+
Project-URL: Homepage, https://oortcloud.dev
|
|
6
|
+
Project-URL: Source, https://github.com/oortmem/oort
|
|
7
|
+
Project-URL: Documentation, https://oortcloud.dev/docs
|
|
8
|
+
Author: Oort
|
|
9
|
+
License-Expression: Apache-2.0
|
|
10
|
+
Keywords: agents,ai,claude,llm,mcp,memory
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Topic :: Software Development
|
|
17
|
+
Requires-Python: >=3.9
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# oortmem
|
|
21
|
+
|
|
22
|
+
Open-source memory for AI agents. Old facts are closed out, not overwritten, and every recall can explain why it was picked.
|
|
23
|
+
|
|
24
|
+
This package installs the `oort` command for Python users. Oort itself is written in TypeScript and published on npm, so it needs **Node.js 22.15 or newer**. The launcher runs an `oort` you already have, or the matching npm release through `npx`. Arguments and exit codes pass straight through.
|
|
25
|
+
|
|
26
|
+
```sh
|
|
27
|
+
pipx install oortmem
|
|
28
|
+
oort setup
|
|
29
|
+
oort recall "where does the user live"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Without Node, `oort` tells you how to install it. You can also skip Python entirely with `npm install -g oortmem`.
|
|
33
|
+
|
|
34
|
+
- Docs: https://oortcloud.dev/docs
|
|
35
|
+
- Source: https://github.com/oortmem/oort
|
|
36
|
+
- License: Apache 2.0
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
oortmem/__init__.py,sha256=7k6Q6sXoODpWPj0q75JoZPyuskSgrgc4PtbHnJxT7jw,117
|
|
2
|
+
oortmem/__main__.py,sha256=E6Gls0DNz8GQK2K-kOUIx8cYhgANW_CH54VKrfCfs14,52
|
|
3
|
+
oortmem/cli.py,sha256=4PyEo6nMQzeh-Of6FZKW71jZK41edjmHVCM9SZyYJoM,3426
|
|
4
|
+
oortmem-0.2.0.dist-info/METADATA,sha256=iOOxqaGhzuBscmJav8ZTRnxA3UVtqKmWkhbnXHk1uNw,1439
|
|
5
|
+
oortmem-0.2.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
6
|
+
oortmem-0.2.0.dist-info/entry_points.txt,sha256=0HDeacgVkFkVIlJuZzR4v2j668qD4hZ1xMQzN9553v0,69
|
|
7
|
+
oortmem-0.2.0.dist-info/RECORD,,
|