agentic-coding-harness 0.7.1__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.
- agentic_coding_harness/__init__.py +10 -0
- agentic_coding_harness/_cli.py +126 -0
- agentic_coding_harness/_vendor/ach.mjs +4201 -0
- agentic_coding_harness/py.typed +0 -0
- agentic_coding_harness-0.7.1.dist-info/METADATA +61 -0
- agentic_coding_harness-0.7.1.dist-info/RECORD +8 -0
- agentic_coding_harness-0.7.1.dist-info/WHEEL +4 -0
- agentic_coding_harness-0.7.1.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""agentic-coding-harness: run/watch/meter coding agents.
|
|
2
|
+
|
|
3
|
+
Python wrapper that locates a JavaScript runtime (Bun preferred, then
|
|
4
|
+
Node.js >= 18.19) and execs the vendored ach.mjs CLI bundle with full
|
|
5
|
+
argument passthrough.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
__version__ = "0.7.1"
|
|
9
|
+
|
|
10
|
+
__all__ = ["__version__"]
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"""Console-script entry point: locate a JS runtime and exec the vendored ach.mjs.
|
|
2
|
+
|
|
3
|
+
Stdlib only. Prefers Bun, then Node >= 18.19. The runtime may be forced via
|
|
4
|
+
the AGENTIC_CODING_HARNESS_RUNTIME environment variable. On POSIX we execv so
|
|
5
|
+
stdio, signals, and exit codes pass through untouched; on Windows we fall back
|
|
6
|
+
to subprocess.call.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
import shutil
|
|
13
|
+
import subprocess
|
|
14
|
+
import sys
|
|
15
|
+
|
|
16
|
+
_PACKAGE_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
17
|
+
_BUNDLE = os.path.join(_PACKAGE_DIR, "_vendor", "ach.mjs")
|
|
18
|
+
_RUNTIME_ENV = "AGENTIC_CODING_HARNESS_RUNTIME"
|
|
19
|
+
|
|
20
|
+
_COMMON_DIRS = (
|
|
21
|
+
"/opt/homebrew/bin",
|
|
22
|
+
"/usr/local/bin",
|
|
23
|
+
os.path.expanduser("~/.bun/bin"),
|
|
24
|
+
os.path.expanduser("~/.volta/bin"),
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
_MISSING_RUNTIME_MESSAGE = """ach: no JavaScript runtime found.
|
|
28
|
+
|
|
29
|
+
agentic-coding-harness needs Bun or Node.js (>= 18.19) to run.
|
|
30
|
+
|
|
31
|
+
Install one of:
|
|
32
|
+
curl -fsSL https://bun.sh/install | bash # Bun (recommended)
|
|
33
|
+
https://nodejs.org/en/download # Node.js >= 18.19
|
|
34
|
+
|
|
35
|
+
Or point {env} at an existing runtime binary, e.g.:
|
|
36
|
+
export {env}=/usr/local/bin/node
|
|
37
|
+
""".format(env=_RUNTIME_ENV)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _candidate_paths(name: str):
|
|
41
|
+
found = shutil.which(name)
|
|
42
|
+
if found:
|
|
43
|
+
yield found
|
|
44
|
+
seen = {found} if found else set()
|
|
45
|
+
for directory in _COMMON_DIRS:
|
|
46
|
+
candidate = os.path.join(directory, name)
|
|
47
|
+
if candidate not in seen and os.path.isfile(candidate) and os.access(candidate, os.X_OK):
|
|
48
|
+
seen.add(candidate)
|
|
49
|
+
yield candidate
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _node_major_minor(path: str):
|
|
53
|
+
"""Return (major, minor) for a node binary, or None if it can't be probed."""
|
|
54
|
+
try:
|
|
55
|
+
out = subprocess.run(
|
|
56
|
+
[path, "--version"],
|
|
57
|
+
capture_output=True,
|
|
58
|
+
text=True,
|
|
59
|
+
timeout=10,
|
|
60
|
+
check=False,
|
|
61
|
+
)
|
|
62
|
+
except (OSError, subprocess.SubprocessError):
|
|
63
|
+
return None
|
|
64
|
+
version = (out.stdout or "").strip().lstrip("v")
|
|
65
|
+
if not version:
|
|
66
|
+
return None
|
|
67
|
+
parts = version.split(".")
|
|
68
|
+
try:
|
|
69
|
+
return int(parts[0]), int(parts[1])
|
|
70
|
+
except (ValueError, IndexError):
|
|
71
|
+
return None
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def find_runtime(env=None):
|
|
75
|
+
"""Return the path to a usable JS runtime, or None.
|
|
76
|
+
|
|
77
|
+
Honors AGENTIC_CODING_HARNESS_RUNTIME when set.
|
|
78
|
+
"""
|
|
79
|
+
environ = env if env is not None else os.environ
|
|
80
|
+
override = environ.get(_RUNTIME_ENV)
|
|
81
|
+
if override:
|
|
82
|
+
if os.path.isfile(override) and os.access(override, os.X_OK):
|
|
83
|
+
return override
|
|
84
|
+
resolved = shutil.which(override)
|
|
85
|
+
if resolved:
|
|
86
|
+
return resolved
|
|
87
|
+
return None
|
|
88
|
+
|
|
89
|
+
for bun in _candidate_paths("bun"):
|
|
90
|
+
return bun
|
|
91
|
+
|
|
92
|
+
for node in _candidate_paths("node"):
|
|
93
|
+
version = _node_major_minor(node)
|
|
94
|
+
if version is None:
|
|
95
|
+
# Unprobeable (e.g. broken install) - skip rather than fail hard.
|
|
96
|
+
continue
|
|
97
|
+
major, minor = version
|
|
98
|
+
if (major, minor) >= (18, 19):
|
|
99
|
+
return node
|
|
100
|
+
|
|
101
|
+
return None
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def main(argv=None):
|
|
105
|
+
runtime = find_runtime()
|
|
106
|
+
if runtime is None:
|
|
107
|
+
sys.stderr.write(_MISSING_RUNTIME_MESSAGE)
|
|
108
|
+
return 127
|
|
109
|
+
if not os.path.isfile(_BUNDLE):
|
|
110
|
+
sys.stderr.write(
|
|
111
|
+
"ach: vendored bundle missing ({}). The install is broken; "
|
|
112
|
+
"reinstall agentic-coding-harness.\n".format(_BUNDLE)
|
|
113
|
+
)
|
|
114
|
+
return 127
|
|
115
|
+
|
|
116
|
+
args = list(sys.argv[1:] if argv is None else argv)
|
|
117
|
+
|
|
118
|
+
if os.name == "posix":
|
|
119
|
+
os.execv(runtime, [runtime, _BUNDLE] + args) # never returns
|
|
120
|
+
return 127 # pragma: no cover - execv failed to replace us
|
|
121
|
+
|
|
122
|
+
return subprocess.call([runtime, _BUNDLE] + args)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
if __name__ == "__main__":
|
|
126
|
+
sys.exit(main())
|