Skip to repository content333 lines · 10.5 KB · python
tenant.openagents/omega
No repository description is available.
OpenAgents Git authority 2026-07-28T02:31:14.320Z Public web read
NIP-34 coordinate
30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omegaMaintainersHidden in public view
References2 branches · 1 tag
Read-only clone
git clone https://openagents.com/git/tenant.openagents/omega.gitBrowse files
source.py
1from __future__ import annotations
2
3import hashlib
4import json
5import os
6import re
7import subprocess
8from pathlib import Path
9from typing import Any
10
11BUILD_SCHEMA_VERSION = "agent-evals-build-v3"
12SOURCE_SCHEMA_VERSION = "agent-evals-source-v1"
13BUILD_TARGET = "x86_64-unknown-linux-musl"
14BUILD_IMAGE_RECIPE_VERSION = "agent-evals-build-image-v1"
15RUST_VERSION = "1.95.0"
16RUST_IMAGE_TAG = f"rust:{RUST_VERSION}"
17RUST_IMAGE_DIGEST = (
18 "sha256:f49565f188ee00bc2a18dd418183f2c5f23ef7d6e691890517ed341a598f67c3"
19)
20RUST_IMAGE = f"{RUST_IMAGE_TAG}@{RUST_IMAGE_DIGEST}"
21ZIG_VERSION = "0.15.2"
22CARGO_ZIGBUILD_VERSION = "0.22.3"
23DEFAULT_REPO_URL = os.environ.get(
24 "AGENT_EVALS_REPO_URL", "https://github.com/zed-industries/zed.git"
25)
26
27
28def package_root() -> Path:
29 return Path(__file__).resolve().parent
30
31
32def eval_cli_root() -> Path:
33 return package_root().parent
34
35
36def repo_root() -> Path:
37 try:
38 result = subprocess.run(
39 ["git", "rev-parse", "--show-toplevel"],
40 cwd=eval_cli_root(),
41 check=True,
42 capture_output=True,
43 text=True,
44 )
45 return Path(result.stdout.strip())
46 except (OSError, subprocess.CalledProcessError):
47 return eval_cli_root().parents[1]
48
49
50def git_output(args: list[str], cwd: Path | None = None) -> str:
51 result = subprocess.run(
52 ["git", *args],
53 cwd=cwd or repo_root(),
54 check=True,
55 capture_output=True,
56 text=True,
57 )
58 return result.stdout.strip()
59
60
61def git_bytes(args: list[str], cwd: Path | None = None) -> bytes:
62 result = subprocess.run(
63 ["git", *args],
64 cwd=cwd or repo_root(),
65 check=True,
66 capture_output=True,
67 )
68 return result.stdout
69
70
71def git_path_list(args: list[str]) -> list[str]:
72 data = git_bytes([*args, "-z"])
73 return [path.decode("utf-8") for path in data.split(b"\0") if path]
74
75
76def current_base_sha() -> str:
77 return git_output(["rev-parse", "HEAD"])
78
79
80def commit_present(sha: str) -> bool:
81 """Whether `sha` resolves to a commit object in the local repo."""
82 result = subprocess.run(
83 ["git", "-C", repo_root(), "cat-file", "-e", f"{sha}^{{commit}}"],
84 capture_output=True,
85 )
86 return result.returncode == 0
87
88
89def base_sha_on_main(base_sha: str, repo_url: str) -> bool:
90 """Whether `base_sha` is reachable from origin/main.
91
92 Resolves origin/main's tip against the remote (so it doesn't depend on the
93 caller's possibly-stale local refs), fetching main if the objects aren't
94 present locally, then checks ancestry. Raises only when the main tip can't be
95 made available locally (a network/remote problem), so callers can
96 distinguish that from a definitive "not on main".
97 """
98 main_sha = resolve_remote_ref(repo_url, "main")
99 if base_sha.lower() == main_sha.lower():
100 return True
101 if not (commit_present(base_sha) and commit_present(main_sha)):
102 subprocess.run(
103 ["git", "-C", repo_root(), "fetch", "--quiet", repo_url, "main"],
104 capture_output=True,
105 )
106 if not commit_present(main_sha):
107 raise RuntimeError(
108 f"origin/main tip {main_sha[:12]} unavailable locally after fetch"
109 )
110 if not commit_present(base_sha):
111 # Not present even after pulling main's history -> not reachable from main.
112 return False
113 ancestry = subprocess.run(
114 ["git", "-C", repo_root(), "merge-base", "--is-ancestor", base_sha, main_sha],
115 capture_output=True,
116 )
117 if ancestry.returncode in (0, 1):
118 return ancestry.returncode == 0
119 raise RuntimeError(
120 (ancestry.stderr or b"").decode(errors="replace").strip()
121 or "git merge-base --is-ancestor failed"
122 )
123
124
125def resolve_git_ref(ref: str) -> str:
126 return git_output(["rev-parse", "--verify", f"{ref}^{{commit}}"])
127
128
129_FULL_SHA_RE = re.compile(r"[0-9a-fA-F]{40}")
130
131
132def resolve_remote_ref(repo_url: str, ref: str) -> str:
133 """Resolve a git ref/tag/branch/SHA to a canonical commit SHA against the
134 *remote* repo, so the resulting build id is identical for every launcher
135 regardless of what they happen to have fetched locally.
136
137 A full 40-char SHA is already canonical and is returned (lowercased) without
138 a network call. For named refs and tags this uses `git ls-remote`, preferring
139 the peeled commit of an annotated tag.
140 """
141 if _FULL_SHA_RE.fullmatch(ref):
142 return ref.lower()
143 output = git_output(
144 [
145 "ls-remote",
146 repo_url,
147 ref,
148 f"refs/tags/{ref}",
149 f"refs/heads/{ref}",
150 ]
151 )
152 entries: list[tuple[str, str]] = []
153 for line in output.splitlines():
154 sha, _, name = line.partition("\t")
155 if sha and name:
156 entries.append((name, sha))
157 # An annotated tag yields both the tag object and a peeled "<ref>^{}" entry
158 # pointing at the underlying commit; the commit is what we want to build.
159 for name, sha in entries:
160 if name.endswith("^{}"):
161 return sha
162 if entries:
163 return entries[0][1]
164 raise ValueError(
165 f"could not resolve ref '{ref}' against {repo_url}. "
166 "Push the commit/tag, or pass a full commit SHA."
167 )
168
169
170def current_ref_name() -> str | None:
171 try:
172 ref_name = git_output(["rev-parse", "--abbrev-ref", "HEAD"])
173 except (OSError, subprocess.CalledProcessError):
174 return None
175 return None if ref_name == "HEAD" else ref_name
176
177
178def current_tracked_patch(base_sha: str) -> str:
179 result = subprocess.run(
180 ["git", "diff", "--binary", base_sha],
181 cwd=repo_root(),
182 check=True,
183 capture_output=True,
184 )
185 return result.stdout.decode("utf-8")
186
187
188def read_patch(patch_path: str | None, base_sha: str, *, clean: bool = False) -> str:
189 if clean:
190 return ""
191 if not patch_path:
192 return current_tracked_patch(base_sha)
193 return Path(patch_path).read_text()
194
195
196def untracked_files() -> list[str]:
197 return git_path_list(["ls-files", "--others", "--exclude-standard"])
198
199
200def sha256_text(text: str) -> str:
201 return hashlib.sha256(text.encode()).hexdigest()
202
203
204def format_untracked_warning(files: list[str]) -> str:
205 preview = "\n".join(f" - {path}" for path in files[:20])
206 if len(files) > 20:
207 preview += f"\n ... and {len(files) - 20} more"
208 return (
209 "untracked files are present and will NOT be included in the build patch.\n"
210 "Commit/remove them, or pass --allow-untracked to proceed anyway.\n"
211 f"{preview}"
212 )
213
214
215def prepare_build_source(
216 *,
217 base_sha: str | None,
218 patch_path: str | None,
219 allow_untracked: bool,
220 require_clean: bool,
221 repo_url: str | None,
222 clean: bool = False,
223 source_label: str | None = None,
224 pre_resolved_base_sha: str | None = None,
225) -> tuple[dict[str, Any], str]:
226 # `pre_resolved_base_sha` is a canonical SHA already resolved against the
227 # remote (see `resolve_remote_ref`); it must be used verbatim because the
228 # launcher may not have that commit fetched locally to `rev-parse`.
229 if pre_resolved_base_sha:
230 resolved_base_sha = pre_resolved_base_sha
231 elif base_sha:
232 resolved_base_sha = resolve_git_ref(base_sha)
233 else:
234 resolved_base_sha = current_base_sha()
235 resolved_repo_url = repo_url or DEFAULT_REPO_URL
236 patch = read_patch(patch_path, resolved_base_sha, clean=clean)
237 patch_sha256 = sha256_text(patch) if patch.strip() else None
238 untracked = [] if clean else untracked_files()
239 is_dirty = bool(patch.strip())
240
241 if untracked and not allow_untracked:
242 raise ValueError(format_untracked_warning(untracked))
243
244 if require_clean and is_dirty:
245 raise ValueError(
246 "tracked changes are present. Commit or stash them, or omit --require-clean."
247 )
248
249 return {
250 "schema": SOURCE_SCHEMA_VERSION,
251 "type": "git_patch",
252 "repo_url": resolved_repo_url,
253 "base_sha": resolved_base_sha,
254 "base_ref": source_label or (base_sha if clean else current_ref_name()),
255 "patch_sha256": patch_sha256,
256 "is_dirty": is_dirty,
257 "patch_path": "source.patch" if patch.strip() else None,
258 "untracked_files": untracked,
259 "untracked_files_included": False,
260 "allow_untracked": allow_untracked,
261 "require_clean": require_clean,
262 "clean_source": clean,
263 }, patch
264
265
266def public_source_info(source_info: dict[str, Any]) -> dict[str, Any]:
267 return dict(source_info)
268
269
270def build_toolchain_info(
271 *,
272 target: str = BUILD_TARGET,
273 rust_image: str = RUST_IMAGE,
274 zig_version: str = ZIG_VERSION,
275 cargo_zigbuild_version: str = CARGO_ZIGBUILD_VERSION,
276) -> dict[str, str]:
277 return {
278 "build_image_recipe_version": BUILD_IMAGE_RECIPE_VERSION,
279 "target": target,
280 "rust_version": RUST_VERSION,
281 "rust_image": rust_image,
282 "rust_image_tag": RUST_IMAGE_TAG,
283 "rust_image_digest": RUST_IMAGE_DIGEST,
284 "zig_version": zig_version,
285 "cargo_zigbuild_version": cargo_zigbuild_version,
286 }
287
288
289def compute_build_id(
290 *,
291 source_info: dict[str, Any],
292 target: str = BUILD_TARGET,
293 rust_image: str = RUST_IMAGE,
294 zig_version: str = ZIG_VERSION,
295 cargo_zigbuild_version: str = CARGO_ZIGBUILD_VERSION,
296) -> str:
297 payload = {
298 "schema": BUILD_SCHEMA_VERSION,
299 "source_type": "git_patch",
300 "base_sha": source_info["base_sha"],
301 "patch_sha256": source_info["patch_sha256"],
302 **build_toolchain_info(
303 target=target,
304 rust_image=rust_image,
305 zig_version=zig_version,
306 cargo_zigbuild_version=cargo_zigbuild_version,
307 ),
308 }
309 digest = hashlib.sha256(json.dumps(payload, sort_keys=True).encode()).hexdigest()
310 return f"bld-{digest[:20]}"
311
312
313def sanitize_namespace(value: str) -> str:
314 sanitized = re.sub(r"[^A-Za-z0-9_.-]+", "-", value.strip().lower()).strip("-.")
315 return sanitized or "default"
316
317
318def default_namespace() -> str:
319 configured = os.environ.get("AGENT_EVALS_NAMESPACE")
320 if configured:
321 return sanitize_namespace(configured)
322
323 try:
324 email = git_output(["config", "user.email"])
325 if email:
326 return sanitize_namespace(email.split("@", 1)[0])
327 except (OSError, subprocess.CalledProcessError):
328 pass
329
330 return sanitize_namespace(
331 os.environ.get("USER") or os.environ.get("LOGNAME") or "default"
332 )
333