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.
Files changed (147) hide show
  1. codex_autorunner/__init__.py +3 -0
  2. codex_autorunner/bootstrap.py +151 -0
  3. codex_autorunner/cli.py +886 -0
  4. codex_autorunner/codex_cli.py +79 -0
  5. codex_autorunner/codex_runner.py +17 -0
  6. codex_autorunner/core/__init__.py +1 -0
  7. codex_autorunner/core/about_car.py +125 -0
  8. codex_autorunner/core/codex_runner.py +100 -0
  9. codex_autorunner/core/config.py +1465 -0
  10. codex_autorunner/core/doc_chat.py +547 -0
  11. codex_autorunner/core/docs.py +37 -0
  12. codex_autorunner/core/engine.py +720 -0
  13. codex_autorunner/core/git_utils.py +206 -0
  14. codex_autorunner/core/hub.py +756 -0
  15. codex_autorunner/core/injected_context.py +9 -0
  16. codex_autorunner/core/locks.py +57 -0
  17. codex_autorunner/core/logging_utils.py +158 -0
  18. codex_autorunner/core/notifications.py +465 -0
  19. codex_autorunner/core/optional_dependencies.py +41 -0
  20. codex_autorunner/core/prompt.py +107 -0
  21. codex_autorunner/core/prompts.py +275 -0
  22. codex_autorunner/core/request_context.py +21 -0
  23. codex_autorunner/core/runner_controller.py +116 -0
  24. codex_autorunner/core/runner_process.py +29 -0
  25. codex_autorunner/core/snapshot.py +576 -0
  26. codex_autorunner/core/state.py +156 -0
  27. codex_autorunner/core/update.py +567 -0
  28. codex_autorunner/core/update_runner.py +44 -0
  29. codex_autorunner/core/usage.py +1221 -0
  30. codex_autorunner/core/utils.py +108 -0
  31. codex_autorunner/discovery.py +102 -0
  32. codex_autorunner/housekeeping.py +423 -0
  33. codex_autorunner/integrations/__init__.py +1 -0
  34. codex_autorunner/integrations/app_server/__init__.py +6 -0
  35. codex_autorunner/integrations/app_server/client.py +1386 -0
  36. codex_autorunner/integrations/app_server/supervisor.py +206 -0
  37. codex_autorunner/integrations/github/__init__.py +10 -0
  38. codex_autorunner/integrations/github/service.py +889 -0
  39. codex_autorunner/integrations/telegram/__init__.py +1 -0
  40. codex_autorunner/integrations/telegram/adapter.py +1401 -0
  41. codex_autorunner/integrations/telegram/commands_registry.py +104 -0
  42. codex_autorunner/integrations/telegram/config.py +450 -0
  43. codex_autorunner/integrations/telegram/constants.py +154 -0
  44. codex_autorunner/integrations/telegram/dispatch.py +162 -0
  45. codex_autorunner/integrations/telegram/handlers/__init__.py +0 -0
  46. codex_autorunner/integrations/telegram/handlers/approvals.py +241 -0
  47. codex_autorunner/integrations/telegram/handlers/callbacks.py +72 -0
  48. codex_autorunner/integrations/telegram/handlers/commands.py +160 -0
  49. codex_autorunner/integrations/telegram/handlers/commands_runtime.py +5262 -0
  50. codex_autorunner/integrations/telegram/handlers/messages.py +477 -0
  51. codex_autorunner/integrations/telegram/handlers/selections.py +545 -0
  52. codex_autorunner/integrations/telegram/helpers.py +2084 -0
  53. codex_autorunner/integrations/telegram/notifications.py +164 -0
  54. codex_autorunner/integrations/telegram/outbox.py +174 -0
  55. codex_autorunner/integrations/telegram/rendering.py +102 -0
  56. codex_autorunner/integrations/telegram/retry.py +37 -0
  57. codex_autorunner/integrations/telegram/runtime.py +270 -0
  58. codex_autorunner/integrations/telegram/service.py +921 -0
  59. codex_autorunner/integrations/telegram/state.py +1223 -0
  60. codex_autorunner/integrations/telegram/transport.py +318 -0
  61. codex_autorunner/integrations/telegram/types.py +57 -0
  62. codex_autorunner/integrations/telegram/voice.py +413 -0
  63. codex_autorunner/manifest.py +150 -0
  64. codex_autorunner/routes/__init__.py +53 -0
  65. codex_autorunner/routes/base.py +470 -0
  66. codex_autorunner/routes/docs.py +275 -0
  67. codex_autorunner/routes/github.py +197 -0
  68. codex_autorunner/routes/repos.py +121 -0
  69. codex_autorunner/routes/sessions.py +137 -0
  70. codex_autorunner/routes/shared.py +137 -0
  71. codex_autorunner/routes/system.py +175 -0
  72. codex_autorunner/routes/terminal_images.py +107 -0
  73. codex_autorunner/routes/voice.py +128 -0
  74. codex_autorunner/server.py +23 -0
  75. codex_autorunner/spec_ingest.py +113 -0
  76. codex_autorunner/static/app.js +95 -0
  77. codex_autorunner/static/autoRefresh.js +209 -0
  78. codex_autorunner/static/bootstrap.js +105 -0
  79. codex_autorunner/static/bus.js +23 -0
  80. codex_autorunner/static/cache.js +52 -0
  81. codex_autorunner/static/constants.js +48 -0
  82. codex_autorunner/static/dashboard.js +795 -0
  83. codex_autorunner/static/docs.js +1514 -0
  84. codex_autorunner/static/env.js +99 -0
  85. codex_autorunner/static/github.js +168 -0
  86. codex_autorunner/static/hub.js +1511 -0
  87. codex_autorunner/static/index.html +622 -0
  88. codex_autorunner/static/loader.js +28 -0
  89. codex_autorunner/static/logs.js +690 -0
  90. codex_autorunner/static/mobileCompact.js +300 -0
  91. codex_autorunner/static/snapshot.js +116 -0
  92. codex_autorunner/static/state.js +87 -0
  93. codex_autorunner/static/styles.css +4966 -0
  94. codex_autorunner/static/tabs.js +50 -0
  95. codex_autorunner/static/terminal.js +21 -0
  96. codex_autorunner/static/terminalManager.js +3535 -0
  97. codex_autorunner/static/todoPreview.js +25 -0
  98. codex_autorunner/static/types.d.ts +8 -0
  99. codex_autorunner/static/utils.js +597 -0
  100. codex_autorunner/static/vendor/LICENSE.xterm +24 -0
  101. codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-400-cyrillic-ext.woff2 +0 -0
  102. codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-400-cyrillic.woff2 +0 -0
  103. codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-400-greek.woff2 +0 -0
  104. codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-400-latin-ext.woff2 +0 -0
  105. codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-400-latin.woff2 +0 -0
  106. codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-400-vietnamese.woff2 +0 -0
  107. codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-500-cyrillic-ext.woff2 +0 -0
  108. codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-500-cyrillic.woff2 +0 -0
  109. codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-500-greek.woff2 +0 -0
  110. codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-500-latin-ext.woff2 +0 -0
  111. codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-500-latin.woff2 +0 -0
  112. codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-500-vietnamese.woff2 +0 -0
  113. codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-600-cyrillic-ext.woff2 +0 -0
  114. codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-600-cyrillic.woff2 +0 -0
  115. codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-600-greek.woff2 +0 -0
  116. codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-600-latin-ext.woff2 +0 -0
  117. codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-600-latin.woff2 +0 -0
  118. codex_autorunner/static/vendor/fonts/jetbrains-mono/JetBrainsMono-600-vietnamese.woff2 +0 -0
  119. codex_autorunner/static/vendor/fonts/jetbrains-mono/OFL.txt +93 -0
  120. codex_autorunner/static/vendor/xterm-addon-fit.js +2 -0
  121. codex_autorunner/static/vendor/xterm.css +209 -0
  122. codex_autorunner/static/vendor/xterm.js +2 -0
  123. codex_autorunner/static/voice.js +591 -0
  124. codex_autorunner/voice/__init__.py +39 -0
  125. codex_autorunner/voice/capture.py +349 -0
  126. codex_autorunner/voice/config.py +167 -0
  127. codex_autorunner/voice/provider.py +66 -0
  128. codex_autorunner/voice/providers/__init__.py +7 -0
  129. codex_autorunner/voice/providers/openai_whisper.py +345 -0
  130. codex_autorunner/voice/resolver.py +36 -0
  131. codex_autorunner/voice/service.py +210 -0
  132. codex_autorunner/web/__init__.py +1 -0
  133. codex_autorunner/web/app.py +1037 -0
  134. codex_autorunner/web/hub_jobs.py +181 -0
  135. codex_autorunner/web/middleware.py +552 -0
  136. codex_autorunner/web/pty_session.py +357 -0
  137. codex_autorunner/web/runner_manager.py +25 -0
  138. codex_autorunner/web/schemas.py +253 -0
  139. codex_autorunner/web/static_assets.py +430 -0
  140. codex_autorunner/web/terminal_sessions.py +78 -0
  141. codex_autorunner/workspace.py +16 -0
  142. codex_autorunner-0.1.0.dist-info/METADATA +240 -0
  143. codex_autorunner-0.1.0.dist-info/RECORD +147 -0
  144. codex_autorunner-0.1.0.dist-info/WHEEL +5 -0
  145. codex_autorunner-0.1.0.dist-info/entry_points.txt +3 -0
  146. codex_autorunner-0.1.0.dist-info/licenses/LICENSE +21 -0
  147. 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}