ottili-coder 1.0.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,3 @@
1
+ .venv/
2
+ dist/
3
+ *.egg-info/
@@ -0,0 +1,38 @@
1
+ Metadata-Version: 2.4
2
+ Name: ottili-coder
3
+ Version: 1.0.0
4
+ Summary: Ottili ONE Coder — autonomous AI coding agent CLI for the terminal
5
+ Project-URL: Homepage, https://ottili.one/coder
6
+ Project-URL: Documentation, https://ottili.one/coder/docs
7
+ Project-URL: Repository, https://github.com/Ottili-ONE/coder-cli
8
+ Project-URL: Issues, https://github.com/Ottili-ONE/coder-cli/issues
9
+ Author-email: Ottili ONE <hello@ottili.one>
10
+ License-Expression: MIT
11
+ Keywords: agent,ai,cli,coder,coding-agent,ottili,ottili-one
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Topic :: Software Development
19
+ Requires-Python: >=3.9
20
+ Description-Content-Type: text/markdown
21
+
22
+ # ottili-coder (Python)
23
+
24
+ Python distribution for [Ottili ONE Coder](https://ottili.one/coder).
25
+
26
+ Install:
27
+
28
+ ```bash
29
+ pip install ottili-coder
30
+ ```
31
+
32
+ Run:
33
+
34
+ ```bash
35
+ ottili-coder --help
36
+ ```
37
+
38
+ The package downloads the platform-native CLI binary on first use and delegates to it.
@@ -0,0 +1,17 @@
1
+ # ottili-coder (Python)
2
+
3
+ Python distribution for [Ottili ONE Coder](https://ottili.one/coder).
4
+
5
+ Install:
6
+
7
+ ```bash
8
+ pip install ottili-coder
9
+ ```
10
+
11
+ Run:
12
+
13
+ ```bash
14
+ ottili-coder --help
15
+ ```
16
+
17
+ The package downloads the platform-native CLI binary on first use and delegates to it.
@@ -0,0 +1,35 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.24.0"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "ottili-coder"
7
+ version = "1.0.0"
8
+ description = "Ottili ONE Coder — autonomous AI coding agent CLI for the terminal"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.9"
12
+ authors = [{ name = "Ottili ONE", email = "hello@ottili.one" }]
13
+ keywords = ["ottili", "ottili-one", "coder", "ai", "cli", "agent", "coding-agent"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Environment :: Console",
17
+ "Intended Audience :: Developers",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Operating System :: OS Independent",
20
+ "Programming Language :: Python :: 3",
21
+ "Topic :: Software Development",
22
+ ]
23
+ dependencies = []
24
+
25
+ [project.urls]
26
+ Homepage = "https://ottili.one/coder"
27
+ Documentation = "https://ottili.one/coder/docs"
28
+ Repository = "https://github.com/Ottili-ONE/coder-cli"
29
+ Issues = "https://github.com/Ottili-ONE/coder-cli/issues"
30
+
31
+ [project.scripts]
32
+ ottili-coder = "ottili_coder.cli:main"
33
+
34
+ [tool.hatch.build.targets.wheel]
35
+ packages = ["src/ottili_coder"]
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env python3
2
+ from __future__ import annotations
3
+
4
+ import os
5
+ import subprocess
6
+ import sys
7
+ from pathlib import Path
8
+
9
+ ROOT = Path(__file__).resolve().parents[1]
10
+
11
+
12
+ def main() -> int:
13
+ token = os.environ.get("PYPI_TOKEN") or os.environ.get("PYPI_API_TOKEN")
14
+ env = os.environ.copy()
15
+ if token:
16
+ env["TWINE_USERNAME"] = "__token__"
17
+ env["TWINE_PASSWORD"] = token
18
+
19
+ subprocess.run([sys.executable, "-m", "pip", "install", "--upgrade", "build", "twine"], check=True)
20
+ subprocess.run([sys.executable, "-m", "build", str(ROOT)], check=True, cwd=ROOT)
21
+ subprocess.run([sys.executable, "-m", "twine", "upload", "dist/*"], check=True, cwd=ROOT, env=env)
22
+ return 0
23
+
24
+
25
+ if __name__ == "__main__":
26
+ raise SystemExit(main())
@@ -0,0 +1,3 @@
1
+ """Ottili ONE Coder Python distribution."""
2
+
3
+ __version__ = "1.0.0"
@@ -0,0 +1,145 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ import platform
5
+ import shutil
6
+ import stat
7
+ import subprocess
8
+ import sys
9
+ import tempfile
10
+ import urllib.error
11
+ import urllib.request
12
+ import zipfile
13
+ from pathlib import Path
14
+
15
+ from . import __version__
16
+
17
+ DEFAULT_RELEASE_REPO = "Ottili-ONE/coder-cli"
18
+ DEFAULT_VERSION = __version__
19
+
20
+
21
+ def _release_repo() -> str:
22
+ return os.environ.get("OTTILI_CODER_RELEASE_REPO", DEFAULT_RELEASE_REPO)
23
+
24
+
25
+ def _release_version() -> str:
26
+ return os.environ.get("OTTILI_CODER_VERSION", DEFAULT_VERSION).lstrip("v")
27
+
28
+
29
+ def _platform_key() -> tuple[str, str]:
30
+ system = platform.system().lower()
31
+ machine = platform.machine().lower()
32
+
33
+ if system == "darwin":
34
+ os_name = "darwin"
35
+ elif system == "linux":
36
+ os_name = "linux"
37
+ elif system == "windows":
38
+ os_name = "windows"
39
+ else:
40
+ raise RuntimeError(f"Unsupported operating system: {system}")
41
+
42
+ if machine in {"x86_64", "amd64"}:
43
+ arch = "x64"
44
+ elif machine in {"aarch64", "arm64"}:
45
+ arch = "arm64"
46
+ else:
47
+ raise RuntimeError(f"Unsupported CPU architecture: {machine}")
48
+
49
+ return os_name, arch
50
+
51
+
52
+ def _asset_name(os_name: str, arch: str) -> tuple[str, str]:
53
+ if os_name == "windows":
54
+ return f"ottili-coder-{os_name}-{arch}.zip", "ottili-coder.exe"
55
+ return f"ottili-coder-{os_name}-{arch}.tar.gz", "ottili-coder"
56
+
57
+
58
+ def _download(url: str, destination: Path) -> None:
59
+ destination.parent.mkdir(parents=True, exist_ok=True)
60
+ request = urllib.request.Request(url, headers={"User-Agent": "ottili-coder-python"})
61
+ with urllib.request.urlopen(request, timeout=120) as response:
62
+ destination.write_bytes(response.read())
63
+
64
+
65
+ def _extract(archive: Path, destination: Path, binary_name: str) -> Path:
66
+ if archive.suffix == ".zip":
67
+ with zipfile.ZipFile(archive) as zf:
68
+ members = [name for name in zf.namelist() if name.endswith(binary_name)]
69
+ if not members:
70
+ raise RuntimeError(f"Could not find {binary_name} in {archive.name}")
71
+ extracted = destination / binary_name
72
+ extracted.parent.mkdir(parents=True, exist_ok=True)
73
+ with zf.open(members[0]) as src, extracted.open("wb") as dst:
74
+ dst.write(src.read())
75
+ return extracted
76
+
77
+ import tarfile
78
+
79
+ with tarfile.open(archive) as tf:
80
+ members = [member for member in tf.getmembers() if member.name.endswith(binary_name)]
81
+ if not members:
82
+ raise RuntimeError(f"Could not find {binary_name} in {archive.name}")
83
+ tf.extract(members[0], destination, filter="data")
84
+ extracted = destination / members[0].name
85
+ target = destination / binary_name
86
+ if extracted != target:
87
+ if target.exists():
88
+ target.unlink()
89
+ extracted.rename(target)
90
+ return target
91
+
92
+
93
+ def _install_dir() -> Path:
94
+ override = os.environ.get("OTTILI_CODER_INSTALL_DIR")
95
+ if override:
96
+ return Path(override)
97
+ return Path.home() / ".ottili-coder" / "bin"
98
+
99
+
100
+ def ensure_binary() -> Path:
101
+ env_path = os.environ.get("OTTILI_CODER_BIN_PATH")
102
+ if env_path:
103
+ path = Path(env_path)
104
+ if path.exists():
105
+ return path
106
+
107
+ install_dir = _install_dir()
108
+ binary_name = "ottili-coder.exe" if platform.system().lower() == "windows" else "ottili-coder"
109
+ installed = install_dir / binary_name
110
+ if installed.exists():
111
+ return installed
112
+
113
+ os_name, arch = _platform_key()
114
+ asset, inner_binary = _asset_name(os_name, arch)
115
+ version = _release_version()
116
+ repo = _release_repo()
117
+ url = f"https://github.com/{repo}/releases/download/v{version}/{asset}"
118
+
119
+ with tempfile.TemporaryDirectory(prefix="ottili-coder-py-") as tmp:
120
+ archive = Path(tmp) / asset
121
+ try:
122
+ _download(url, archive)
123
+ except urllib.error.HTTPError as error:
124
+ raise RuntimeError(
125
+ f"Failed to download Ottili Coder v{version} for {os_name}-{arch} from {url}: {error}"
126
+ ) from error
127
+
128
+ extracted = _extract(archive, Path(tmp), inner_binary)
129
+ install_dir.mkdir(parents=True, exist_ok=True)
130
+ if installed.exists():
131
+ installed.unlink()
132
+ shutil.copy2(extracted, installed)
133
+ if os_name != "windows":
134
+ installed.chmod(installed.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
135
+ return installed
136
+
137
+
138
+ def main() -> None:
139
+ binary = ensure_binary()
140
+ completed = subprocess.run([str(binary), *sys.argv[1:]], check=False)
141
+ raise SystemExit(completed.returncode)
142
+
143
+
144
+ if __name__ == "__main__":
145
+ main()