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.
@@ -0,0 +1,5 @@
1
+ dist/
2
+ build/
3
+ *.egg-info/
4
+ __pycache__/
5
+ .venv/
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,3 @@
1
+ from twoody.cli import main
2
+
3
+ raise SystemExit(main())
@@ -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())