codex-autorunner 0.1.0__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.
- codex_autorunner/__init__.py +3 -0
- codex_autorunner/bootstrap.py +151 -0
- codex_autorunner/cli.py +886 -0
- codex_autorunner/codex_cli.py +79 -0
- codex_autorunner/codex_runner.py +17 -0
- codex_autorunner/core/__init__.py +1 -0
- codex_autorunner/core/about_car.py +125 -0
- codex_autorunner/core/codex_runner.py +100 -0
- codex_autorunner/core/config.py +1465 -0
- codex_autorunner/core/doc_chat.py +547 -0
- codex_autorunner/core/docs.py +37 -0
- codex_autorunner/core/engine.py +720 -0
- codex_autorunner/core/git_utils.py +206 -0
- codex_autorunner/core/hub.py +756 -0
- codex_autorunner/core/injected_context.py +9 -0
- codex_autorunner/core/locks.py +57 -0
- codex_autorunner/core/logging_utils.py +158 -0
- codex_autorunner/core/notifications.py +465 -0
- codex_autorunner/core/optional_dependencies.py +41 -0
- codex_autorunner/core/prompt.py +107 -0
- codex_autorunner/core/prompts.py +275 -0
- codex_autorunner/core/request_context.py +21 -0
- codex_autorunner/core/runner_controller.py +116 -0
- codex_autorunner/core/runner_process.py +29 -0
- codex_autorunner/core/snapshot.py +576 -0
- codex_autorunner/core/state.py +156 -0
- codex_autorunner/core/update.py +567 -0
- codex_autorunner/core/update_runner.py +44 -0
- codex_autorunner/core/usage.py +1221 -0
- codex_autorunner/core/utils.py +108 -0
- codex_autorunner/discovery.py +102 -0
- codex_autorunner/housekeeping.py +423 -0
- codex_autorunner/integrations/__init__.py +1 -0
- codex_autorunner/integrations/app_server/__init__.py +6 -0
- codex_autorunner/integrations/app_server/client.py +1386 -0
- codex_autorunner/integrations/app_server/supervisor.py +206 -0
- codex_autorunner/integrations/github/__init__.py +10 -0
- codex_autorunner/integrations/github/service.py +889 -0
- codex_autorunner/integrations/telegram/__init__.py +1 -0
- codex_autorunner/integrations/telegram/adapter.py +1401 -0
- codex_autorunner/integrations/telegram/commands_registry.py +104 -0
- codex_autorunner/integrations/telegram/config.py +450 -0
- codex_autorunner/integrations/telegram/constants.py +154 -0
- codex_autorunner/integrations/telegram/dispatch.py +162 -0
- codex_autorunner/integrations/telegram/handlers/__init__.py +0 -0
- codex_autorunner/integrations/telegram/handlers/approvals.py +241 -0
- codex_autorunner/integrations/telegram/handlers/callbacks.py +72 -0
- codex_autorunner/integrations/telegram/handlers/commands.py +160 -0
- codex_autorunner/integrations/telegram/handlers/commands_runtime.py +5262 -0
- codex_autorunner/integrations/telegram/handlers/messages.py +477 -0
- codex_autorunner/integrations/telegram/handlers/selections.py +545 -0
- codex_autorunner/integrations/telegram/helpers.py +2084 -0
- codex_autorunner/integrations/telegram/notifications.py +164 -0
- codex_autorunner/integrations/telegram/outbox.py +174 -0
- codex_autorunner/integrations/telegram/rendering.py +102 -0
- codex_autorunner/integrations/telegram/retry.py +37 -0
- codex_autorunner/integrations/telegram/runtime.py +270 -0
- codex_autorunner/integrations/telegram/service.py +921 -0
- codex_autorunner/integrations/telegram/state.py +1223 -0
- codex_autorunner/integrations/telegram/transport.py +318 -0
- codex_autorunner/integrations/telegram/types.py +57 -0
- codex_autorunner/integrations/telegram/voice.py +413 -0
- codex_autorunner/manifest.py +150 -0
- codex_autorunner/routes/__init__.py +53 -0
- codex_autorunner/routes/base.py +470 -0
- codex_autorunner/routes/docs.py +275 -0
- codex_autorunner/routes/github.py +197 -0
- codex_autorunner/routes/repos.py +121 -0
- codex_autorunner/routes/sessions.py +137 -0
- codex_autorunner/routes/shared.py +137 -0
- codex_autorunner/routes/system.py +175 -0
- codex_autorunner/routes/terminal_images.py +107 -0
- codex_autorunner/routes/voice.py +128 -0
- codex_autorunner/server.py +23 -0
- codex_autorunner/spec_ingest.py +113 -0
- codex_autorunner/static/app.js +95 -0
- codex_autorunner/static/autoRefresh.js +209 -0
- codex_autorunner/static/bootstrap.js +105 -0
- codex_autorunner/static/bus.js +23 -0
- codex_autorunner/static/cache.js +52 -0
- codex_autorunner/static/constants.js +48 -0
- codex_autorunner/static/dashboard.js +795 -0
- codex_autorunner/static/docs.js +1514 -0
- codex_autorunner/static/env.js +99 -0
- codex_autorunner/static/github.js +168 -0
- codex_autorunner/static/hub.js +1511 -0
- codex_autorunner/static/index.html +622 -0
- codex_autorunner/static/loader.js +28 -0
- codex_autorunner/static/logs.js +690 -0
- codex_autorunner/static/mobileCompact.js +300 -0
- codex_autorunner/static/snapshot.js +116 -0
- codex_autorunner/static/state.js +87 -0
- codex_autorunner/static/styles.css +4966 -0
- codex_autorunner/static/tabs.js +50 -0
- codex_autorunner/static/terminal.js +21 -0
- codex_autorunner/static/terminalManager.js +3535 -0
- codex_autorunner/static/todoPreview.js +25 -0
- codex_autorunner/static/types.d.ts +8 -0
- codex_autorunner/static/utils.js +597 -0
- codex_autorunner/static/vendor/LICENSE.xterm +24 -0
- codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-400-cyrillic-ext.woff2 +0 -0
- codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-400-cyrillic.woff2 +0 -0
- codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-400-greek.woff2 +0 -0
- codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-400-latin-ext.woff2 +0 -0
- codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-400-latin.woff2 +0 -0
- codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-400-vietnamese.woff2 +0 -0
- codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-500-cyrillic-ext.woff2 +0 -0
- codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-500-cyrillic.woff2 +0 -0
- codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-500-greek.woff2 +0 -0
- codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-500-latin-ext.woff2 +0 -0
- codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-500-latin.woff2 +0 -0
- codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-500-vietnamese.woff2 +0 -0
- codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-600-cyrillic-ext.woff2 +0 -0
- codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-600-cyrillic.woff2 +0 -0
- codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-600-greek.woff2 +0 -0
- codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-600-latin-ext.woff2 +0 -0
- codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-600-latin.woff2 +0 -0
- codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-600-vietnamese.woff2 +0 -0
- codex_autorunner/static/vendor/fonts/jetbrains-mono/OFL.txt +93 -0
- codex_autorunner/static/vendor/xterm-addon-fit.js +2 -0
- codex_autorunner/static/vendor/xterm.css +209 -0
- codex_autorunner/static/vendor/xterm.js +2 -0
- codex_autorunner/static/voice.js +591 -0
- codex_autorunner/voice/__init__.py +39 -0
- codex_autorunner/voice/capture.py +349 -0
- codex_autorunner/voice/config.py +167 -0
- codex_autorunner/voice/provider.py +66 -0
- codex_autorunner/voice/providers/__init__.py +7 -0
- codex_autorunner/voice/providers/openai_whisper.py +345 -0
- codex_autorunner/voice/resolver.py +36 -0
- codex_autorunner/voice/service.py +210 -0
- codex_autorunner/web/__init__.py +1 -0
- codex_autorunner/web/app.py +1037 -0
- codex_autorunner/web/hub_jobs.py +181 -0
- codex_autorunner/web/middleware.py +552 -0
- codex_autorunner/web/pty_session.py +357 -0
- codex_autorunner/web/runner_manager.py +25 -0
- codex_autorunner/web/schemas.py +253 -0
- codex_autorunner/web/static_assets.py +430 -0
- codex_autorunner/web/terminal_sessions.py +78 -0
- codex_autorunner/workspace.py +16 -0
- codex_autorunner-0.1.0.dist-info/METADATA +240 -0
- codex_autorunner-0.1.0.dist-info/RECORD +147 -0
- codex_autorunner-0.1.0.dist-info/WHEEL +5 -0
- codex_autorunner-0.1.0.dist-info/entry_points.txt +3 -0
- codex_autorunner-0.1.0.dist-info/licenses/LICENSE +21 -0
- codex_autorunner-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Centralized Git utilities for consistent git operations across the codebase.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import subprocess
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import List, Optional
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class GitError(Exception):
|
|
11
|
+
"""Raised when a git operation fails."""
|
|
12
|
+
|
|
13
|
+
def __init__(self, message: str, *, returncode: int = 1):
|
|
14
|
+
super().__init__(message)
|
|
15
|
+
self.returncode = returncode
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def run_git(
|
|
19
|
+
args: List[str],
|
|
20
|
+
cwd: Path,
|
|
21
|
+
*,
|
|
22
|
+
timeout_seconds: int = 30,
|
|
23
|
+
check: bool = False,
|
|
24
|
+
) -> subprocess.CompletedProcess[str]:
|
|
25
|
+
"""
|
|
26
|
+
Run a git command with consistent error handling.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
args: Git subcommand and arguments (e.g., ["status", "--porcelain"])
|
|
30
|
+
cwd: Working directory for the command
|
|
31
|
+
timeout_seconds: Timeout in seconds
|
|
32
|
+
check: If True, raise GitError on non-zero exit code
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
CompletedProcess with stdout/stderr as text
|
|
36
|
+
"""
|
|
37
|
+
try:
|
|
38
|
+
proc = subprocess.run(
|
|
39
|
+
["git"] + args,
|
|
40
|
+
cwd=str(cwd),
|
|
41
|
+
capture_output=True,
|
|
42
|
+
text=True,
|
|
43
|
+
timeout=timeout_seconds,
|
|
44
|
+
)
|
|
45
|
+
except FileNotFoundError as exc:
|
|
46
|
+
raise GitError("git binary not found", returncode=127) from exc
|
|
47
|
+
except subprocess.TimeoutExpired as exc:
|
|
48
|
+
raise GitError(
|
|
49
|
+
f"git command timed out: git {' '.join(args)}", returncode=124
|
|
50
|
+
) from exc
|
|
51
|
+
|
|
52
|
+
if check and proc.returncode != 0:
|
|
53
|
+
stderr = (proc.stderr or "").strip()
|
|
54
|
+
stdout = (proc.stdout or "").strip()
|
|
55
|
+
detail = stderr or stdout or f"exit {proc.returncode}"
|
|
56
|
+
raise GitError(f"git {args[0]} failed: {detail}", returncode=proc.returncode)
|
|
57
|
+
|
|
58
|
+
return proc
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def git_available(repo_root: Path) -> bool:
|
|
62
|
+
"""Check if the directory is inside a git repository."""
|
|
63
|
+
if not (repo_root / ".git").exists():
|
|
64
|
+
return False
|
|
65
|
+
try:
|
|
66
|
+
proc = run_git(["rev-parse", "--is-inside-work-tree"], repo_root)
|
|
67
|
+
except GitError:
|
|
68
|
+
return False
|
|
69
|
+
return proc.returncode == 0
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def git_head_sha(repo_root: Path) -> Optional[str]:
|
|
73
|
+
"""Get the current HEAD SHA, or None if unavailable."""
|
|
74
|
+
try:
|
|
75
|
+
proc = run_git(["rev-parse", "HEAD"], repo_root)
|
|
76
|
+
except GitError:
|
|
77
|
+
return None
|
|
78
|
+
sha = (proc.stdout or "").strip()
|
|
79
|
+
return sha if proc.returncode == 0 and sha else None
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def git_branch(repo_root: Path) -> Optional[str]:
|
|
83
|
+
"""Get the current branch name, or None if detached HEAD or unavailable."""
|
|
84
|
+
try:
|
|
85
|
+
proc = run_git(["rev-parse", "--abbrev-ref", "HEAD"], repo_root)
|
|
86
|
+
except GitError:
|
|
87
|
+
return None
|
|
88
|
+
branch = (proc.stdout or "").strip()
|
|
89
|
+
if proc.returncode != 0 or not branch:
|
|
90
|
+
return None
|
|
91
|
+
if branch == "HEAD":
|
|
92
|
+
return None
|
|
93
|
+
return branch
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def git_is_clean(repo_root: Path) -> bool:
|
|
97
|
+
"""Check if the working tree has no uncommitted changes."""
|
|
98
|
+
try:
|
|
99
|
+
proc = run_git(["status", "--porcelain"], repo_root, check=False)
|
|
100
|
+
except GitError:
|
|
101
|
+
return False
|
|
102
|
+
if proc.returncode != 0:
|
|
103
|
+
return False
|
|
104
|
+
return not bool((proc.stdout or "").strip())
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def git_ls_files(repo_root: Path) -> List[str]:
|
|
108
|
+
"""
|
|
109
|
+
List all tracked files in the repository.
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
List of relative file paths
|
|
113
|
+
"""
|
|
114
|
+
try:
|
|
115
|
+
proc = subprocess.run(
|
|
116
|
+
["git", "ls-files", "-z"],
|
|
117
|
+
cwd=str(repo_root),
|
|
118
|
+
capture_output=True,
|
|
119
|
+
)
|
|
120
|
+
except FileNotFoundError:
|
|
121
|
+
return []
|
|
122
|
+
if proc.returncode != 0:
|
|
123
|
+
return []
|
|
124
|
+
paths = [p for p in proc.stdout.split(b"\x00") if p]
|
|
125
|
+
decoded: List[str] = []
|
|
126
|
+
for p in paths:
|
|
127
|
+
try:
|
|
128
|
+
decoded.append(p.decode("utf-8"))
|
|
129
|
+
except UnicodeDecodeError:
|
|
130
|
+
decoded.append(p.decode("utf-8", errors="replace"))
|
|
131
|
+
return decoded
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def git_diff_name_status(
|
|
135
|
+
repo_root: Path, from_ref: str, to_ref: str = "HEAD"
|
|
136
|
+
) -> Optional[str]:
|
|
137
|
+
"""
|
|
138
|
+
Get diff --name-status output between two refs.
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
The diff output as a string, or None on error
|
|
142
|
+
"""
|
|
143
|
+
try:
|
|
144
|
+
proc = run_git(["diff", "--name-status", f"{from_ref}..{to_ref}"], repo_root)
|
|
145
|
+
except GitError:
|
|
146
|
+
return None
|
|
147
|
+
if proc.returncode != 0:
|
|
148
|
+
return None
|
|
149
|
+
return (proc.stdout or "").strip()
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def git_status_porcelain(repo_root: Path) -> Optional[str]:
|
|
153
|
+
"""
|
|
154
|
+
Get status --porcelain output.
|
|
155
|
+
|
|
156
|
+
Returns:
|
|
157
|
+
The status output as a string, or None on error
|
|
158
|
+
"""
|
|
159
|
+
try:
|
|
160
|
+
proc = run_git(["status", "--porcelain"], repo_root)
|
|
161
|
+
except GitError:
|
|
162
|
+
return None
|
|
163
|
+
if proc.returncode != 0:
|
|
164
|
+
return None
|
|
165
|
+
return (proc.stdout or "").strip()
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def git_upstream_status(repo_root: Path) -> Optional[dict]:
|
|
169
|
+
"""
|
|
170
|
+
Get upstream tracking status for the current branch.
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
Dict with has_upstream, ahead, behind, or None if git is unavailable.
|
|
174
|
+
"""
|
|
175
|
+
if not git_available(repo_root):
|
|
176
|
+
return None
|
|
177
|
+
try:
|
|
178
|
+
proc = run_git(
|
|
179
|
+
["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"],
|
|
180
|
+
repo_root,
|
|
181
|
+
check=False,
|
|
182
|
+
)
|
|
183
|
+
except GitError:
|
|
184
|
+
return None
|
|
185
|
+
if proc.returncode != 0:
|
|
186
|
+
return {"has_upstream": False, "ahead": 0, "behind": 0}
|
|
187
|
+
proc = run_git(
|
|
188
|
+
["rev-list", "--left-right", "--count", "HEAD...@{u}"],
|
|
189
|
+
repo_root,
|
|
190
|
+
check=False,
|
|
191
|
+
)
|
|
192
|
+
if proc.returncode != 0:
|
|
193
|
+
return {"has_upstream": True, "ahead": 0, "behind": 0}
|
|
194
|
+
raw = (proc.stdout or "").strip()
|
|
195
|
+
ahead = 0
|
|
196
|
+
behind = 0
|
|
197
|
+
if raw:
|
|
198
|
+
parts = raw.split()
|
|
199
|
+
if len(parts) >= 2:
|
|
200
|
+
try:
|
|
201
|
+
ahead = int(parts[0])
|
|
202
|
+
behind = int(parts[1])
|
|
203
|
+
except ValueError:
|
|
204
|
+
ahead = 0
|
|
205
|
+
behind = 0
|
|
206
|
+
return {"has_upstream": True, "ahead": ahead, "behind": behind}
|