twoody 0.2.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.
- twoody-0.2.0/.gitignore +5 -0
- twoody-0.2.0/LICENSE +11 -0
- twoody-0.2.0/PKG-INFO +69 -0
- twoody-0.2.0/README.md +49 -0
- twoody-0.2.0/pyproject.toml +37 -0
- twoody-0.2.0/src/twoody/__init__.py +9 -0
- twoody-0.2.0/src/twoody/__main__.py +3 -0
- twoody-0.2.0/src/twoody/cli.py +85 -0
twoody-0.2.0/.gitignore
ADDED
twoody-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Copyright (c) 2026 Osmove SASU. All rights reserved.
|
|
2
|
+
|
|
3
|
+
Osmove lets you install and use this software free of charge, for personal
|
|
4
|
+
and professional purposes alike, including in your company or practice,
|
|
5
|
+
under the terms of use of Twoody: https://www.twoody.com/terms
|
|
6
|
+
|
|
7
|
+
You may not sell or rent it, or present it as your own. No other right is
|
|
8
|
+
granted.
|
|
9
|
+
|
|
10
|
+
It is built with free software, including llama.cpp (MIT licence), whose
|
|
11
|
+
licences ship with it.
|
twoody-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: twoody
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Twoody from the command line: run this computer's models (`twoody run`, `pull`, `list`), an OpenAI-compatible local API, chat, and `twoody serve`; the same command as `npm install -g twoody`, needs Node.js 22+
|
|
5
|
+
Project-URL: Homepage, https://twoody.com
|
|
6
|
+
Author-email: Osmove <support@twoody.com>
|
|
7
|
+
License-Expression: LicenseRef-Twoody
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Keywords: assistant,llama.cpp,llm,local-llm,ollama,openai-compatible,private-ai,raspberry-pi,self-hosted,twoody
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
13
|
+
Classifier: Operating System :: MacOS
|
|
14
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
15
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
18
|
+
Requires-Python: >=3.9
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# twoody
|
|
22
|
+
|
|
23
|
+
Twoody from the command line, on a Mac, a Raspberry Pi 5, a NAS or any
|
|
24
|
+
server: the same `twoody` command as `npm install -g twoody`.
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install twoody # or: pipx install twoody
|
|
28
|
+
twoody --help
|
|
29
|
+
twoody serve --llm http://127.0.0.1:11434/v1 # start Twoody Server
|
|
30
|
+
twoody setup # create the account
|
|
31
|
+
twoody chat --effort think
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
With Twoody Desktop (or `twoody serve`) on the computer, the same command runs
|
|
35
|
+
its models and gives programs an OpenAI-compatible API, on this computer only:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
twoody list # the models here
|
|
39
|
+
twoody run Qwen3.5-9B-Q4_K_M "Bonjour" # one answer, or a conversation without a prompt
|
|
40
|
+
twoody api-key create "my script" # a key for http://127.0.0.1:47821/v1
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The Twoody CLI is a Node.js program: this package is a small launcher. The
|
|
44
|
+
`twoody` command checks that **Node.js 22 or later** is installed (and says
|
|
45
|
+
how to install it if not), then runs `npx -y twoody@0.2.0` with the same
|
|
46
|
+
arguments; npm downloads the CLI, and Twoody Server with it, once and caches
|
|
47
|
+
it. Set `TWOODY_NPM_VERSION` to run another release (for example `latest`);
|
|
48
|
+
`twoody --launcher-version` prints this launcher's version.
|
|
49
|
+
|
|
50
|
+
`twoody serve` (alias `twoody server [options]`) starts Twoody Server with its
|
|
51
|
+
options: `--port`, `--host`, `--data-dir`, `--llm`, `--pairing-code`,
|
|
52
|
+
`--local-only`, `--no-bonjour`. The server has no model of its own: run
|
|
53
|
+
[Ollama](https://ollama.com) (`ollama pull qwen3.5:4b`, or a model of your
|
|
54
|
+
choice), llama.cpp's `llama-server` or LM Studio next to it and point `--llm`
|
|
55
|
+
at its OpenAI-compatible `/v1` address. On first start the server prints a
|
|
56
|
+
setup token: `twoody setup` or the Twoody app asks for it to create the
|
|
57
|
+
account.
|
|
58
|
+
|
|
59
|
+
`twoody ask` and `twoody chat` take the apps' choices: `--effort
|
|
60
|
+
fast|think|deep`, `--model` (`twoody models`), `--documents
|
|
61
|
+
off|all|selected|only` with `--folders` (`twoody folders`).
|
|
62
|
+
|
|
63
|
+
Without Node.js, use the Docker image for the server
|
|
64
|
+
(`ghcr.io/osmove/twoody-server`, with a compose file that includes Ollama),
|
|
65
|
+
or Homebrew for the CLI (`brew install osmove/twoody/twoody`).
|
|
66
|
+
|
|
67
|
+
Free to install and use, for personal and professional purposes alike,
|
|
68
|
+
under the terms of use of Twoody (https://www.twoody.com/terms): see
|
|
69
|
+
[LICENSE](LICENSE).
|
twoody-0.2.0/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# twoody
|
|
2
|
+
|
|
3
|
+
Twoody from the command line, on a Mac, a Raspberry Pi 5, a NAS or any
|
|
4
|
+
server: the same `twoody` command as `npm install -g twoody`.
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
pip install twoody # or: pipx install twoody
|
|
8
|
+
twoody --help
|
|
9
|
+
twoody serve --llm http://127.0.0.1:11434/v1 # start Twoody Server
|
|
10
|
+
twoody setup # create the account
|
|
11
|
+
twoody chat --effort think
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
With Twoody Desktop (or `twoody serve`) on the computer, the same command runs
|
|
15
|
+
its models and gives programs an OpenAI-compatible API, on this computer only:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
twoody list # the models here
|
|
19
|
+
twoody run Qwen3.5-9B-Q4_K_M "Bonjour" # one answer, or a conversation without a prompt
|
|
20
|
+
twoody api-key create "my script" # a key for http://127.0.0.1:47821/v1
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The Twoody CLI is a Node.js program: this package is a small launcher. The
|
|
24
|
+
`twoody` command checks that **Node.js 22 or later** is installed (and says
|
|
25
|
+
how to install it if not), then runs `npx -y twoody@0.2.0` with the same
|
|
26
|
+
arguments; npm downloads the CLI, and Twoody Server with it, once and caches
|
|
27
|
+
it. Set `TWOODY_NPM_VERSION` to run another release (for example `latest`);
|
|
28
|
+
`twoody --launcher-version` prints this launcher's version.
|
|
29
|
+
|
|
30
|
+
`twoody serve` (alias `twoody server [options]`) starts Twoody Server with its
|
|
31
|
+
options: `--port`, `--host`, `--data-dir`, `--llm`, `--pairing-code`,
|
|
32
|
+
`--local-only`, `--no-bonjour`. The server has no model of its own: run
|
|
33
|
+
[Ollama](https://ollama.com) (`ollama pull qwen3.5:4b`, or a model of your
|
|
34
|
+
choice), llama.cpp's `llama-server` or LM Studio next to it and point `--llm`
|
|
35
|
+
at its OpenAI-compatible `/v1` address. On first start the server prints a
|
|
36
|
+
setup token: `twoody setup` or the Twoody app asks for it to create the
|
|
37
|
+
account.
|
|
38
|
+
|
|
39
|
+
`twoody ask` and `twoody chat` take the apps' choices: `--effort
|
|
40
|
+
fast|think|deep`, `--model` (`twoody models`), `--documents
|
|
41
|
+
off|all|selected|only` with `--folders` (`twoody folders`).
|
|
42
|
+
|
|
43
|
+
Without Node.js, use the Docker image for the server
|
|
44
|
+
(`ghcr.io/osmove/twoody-server`, with a compose file that includes Ollama),
|
|
45
|
+
or Homebrew for the CLI (`brew install osmove/twoody/twoody`).
|
|
46
|
+
|
|
47
|
+
Free to install and use, for personal and professional purposes alike,
|
|
48
|
+
under the terms of use of Twoody (https://www.twoody.com/terms): see
|
|
49
|
+
[LICENSE](LICENSE).
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling>=1.27"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "twoody"
|
|
7
|
+
version = "0.2.0"
|
|
8
|
+
description = "Twoody from the command line: run this computer's models (`twoody run`, `pull`, `list`), an OpenAI-compatible local API, chat, and `twoody serve`; the same command as `npm install -g twoody`, needs Node.js 22+"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = "LicenseRef-Twoody"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [{ name = "Osmove", email = "support@twoody.com" }]
|
|
14
|
+
keywords = ["twoody", "assistant", "local-llm", "llm", "openai-compatible", "llama.cpp", "ollama", "self-hosted", "raspberry-pi", "private-ai"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 4 - Beta",
|
|
17
|
+
"Environment :: Console",
|
|
18
|
+
"Intended Audience :: End Users/Desktop",
|
|
19
|
+
"Operating System :: POSIX :: Linux",
|
|
20
|
+
"Operating System :: MacOS",
|
|
21
|
+
"Operating System :: Microsoft :: Windows",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
24
|
+
]
|
|
25
|
+
dependencies = []
|
|
26
|
+
|
|
27
|
+
[project.urls]
|
|
28
|
+
Homepage = "https://twoody.com"
|
|
29
|
+
|
|
30
|
+
[project.scripts]
|
|
31
|
+
twoody = "twoody.cli:main"
|
|
32
|
+
|
|
33
|
+
[tool.hatch.build.targets.wheel]
|
|
34
|
+
packages = ["src/twoody"]
|
|
35
|
+
|
|
36
|
+
[tool.hatch.build.targets.sdist]
|
|
37
|
+
include = ["src/twoody", "README.md", "LICENSE", "pyproject.toml"]
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""Twoody: the `twoody` command (the `twoody` npm package) through Node.js."""
|
|
2
|
+
|
|
3
|
+
__version__ = "0.2.0"
|
|
4
|
+
|
|
5
|
+
# The `twoody` npm release this launcher runs: the Twoody CLI, whose
|
|
6
|
+
# `twoody serve` starts Twoody Server. Pinned, so `pip install twoody==X`
|
|
7
|
+
# always runs the same CLI; TWOODY_NPM_VERSION overrides it (for example
|
|
8
|
+
# "latest").
|
|
9
|
+
NPM_VERSION = "0.2.0"
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""The `twoody` command.
|
|
2
|
+
|
|
3
|
+
The Twoody CLI is a Node.js program published on npm as `twoody`. This
|
|
4
|
+
command checks that Node.js 22 or later is installed, then runs
|
|
5
|
+
`npx -y twoody@<version>` with the arguments it was given: npm downloads the
|
|
6
|
+
CLI (and Twoody Server, which `twoody serve` starts) once and caches it.
|
|
7
|
+
`pip install twoody` and `npm install -g twoody` give the same commands.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
import re
|
|
14
|
+
import shutil
|
|
15
|
+
import subprocess
|
|
16
|
+
import sys
|
|
17
|
+
|
|
18
|
+
from twoody import NPM_VERSION, __version__
|
|
19
|
+
|
|
20
|
+
MIN_NODE_MAJOR = 22
|
|
21
|
+
|
|
22
|
+
INSTALL_NODE = f"""Twoody runs on Node.js {MIN_NODE_MAJOR} or later, and {{problem}}.
|
|
23
|
+
|
|
24
|
+
Install Node.js {MIN_NODE_MAJOR}+ (it comes with npm and npx), then run twoody again:
|
|
25
|
+
- macOS: brew install node@{MIN_NODE_MAJOR} (or https://nodejs.org)
|
|
26
|
+
- Debian, Ubuntu,
|
|
27
|
+
Raspberry Pi OS: curl -fsSL https://deb.nodesource.com/setup_{MIN_NODE_MAJOR}.x | sudo bash -
|
|
28
|
+
sudo apt-get install -y nodejs
|
|
29
|
+
- Windows: winget install OpenJS.NodeJS.LTS (or https://nodejs.org)
|
|
30
|
+
|
|
31
|
+
Or skip Node.js: the Docker image ghcr.io/osmove/twoody-server runs the
|
|
32
|
+
server, and `brew install osmove/twoody/twoody` gives the CLI."""
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def node_major(node: str) -> int | None:
|
|
36
|
+
try:
|
|
37
|
+
out = subprocess.run([node, "--version"], capture_output=True, text=True, timeout=15).stdout
|
|
38
|
+
except (OSError, subprocess.SubprocessError):
|
|
39
|
+
return None
|
|
40
|
+
match = re.match(r"v(\d+)\.", out.strip())
|
|
41
|
+
return int(match.group(1)) if match else None
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def npm_version() -> str:
|
|
45
|
+
return os.environ.get("TWOODY_NPM_VERSION") or NPM_VERSION
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def main(argv: list[str] | None = None) -> int:
|
|
49
|
+
args = list(sys.argv[1:] if argv is None else argv)
|
|
50
|
+
|
|
51
|
+
# Every argument is the CLI's (`twoody --help`, `twoody serve --llm …`,
|
|
52
|
+
# `twoody chat`…); only `--launcher-version` is this package's.
|
|
53
|
+
if args == ["--launcher-version"]:
|
|
54
|
+
print(f"twoody {__version__} for PyPI (runs twoody@{npm_version()} from npm)")
|
|
55
|
+
return 0
|
|
56
|
+
|
|
57
|
+
node = shutil.which("node")
|
|
58
|
+
if node is None:
|
|
59
|
+
print(INSTALL_NODE.format(problem="it is not installed (no `node` on the PATH)"), file=sys.stderr)
|
|
60
|
+
return 1
|
|
61
|
+
major = node_major(node)
|
|
62
|
+
if major is None or major < MIN_NODE_MAJOR:
|
|
63
|
+
found = f"this one is version {major}" if major is not None else "`node --version` did not answer"
|
|
64
|
+
print(INSTALL_NODE.format(problem=found), file=sys.stderr)
|
|
65
|
+
return 1
|
|
66
|
+
npx = shutil.which("npx")
|
|
67
|
+
if npx is None:
|
|
68
|
+
print(INSTALL_NODE.format(problem="npx (installed with npm) is missing"), file=sys.stderr)
|
|
69
|
+
return 1
|
|
70
|
+
|
|
71
|
+
command = [npx, "-y", f"twoody@{npm_version()}", *args]
|
|
72
|
+
|
|
73
|
+
if os.name == "posix":
|
|
74
|
+
# Replace this process: signals from a terminal, systemd or Docker
|
|
75
|
+
# reach the CLI (and the server `twoody serve` runs) directly, and
|
|
76
|
+
# its exit code is the command's.
|
|
77
|
+
os.execv(npx, command)
|
|
78
|
+
try:
|
|
79
|
+
return subprocess.call(command)
|
|
80
|
+
except KeyboardInterrupt:
|
|
81
|
+
return 130
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
if __name__ == "__main__":
|
|
85
|
+
raise SystemExit(main())
|