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,99 @@
1
+ const hasWindow = typeof window !== "undefined" && typeof window.location !== "undefined";
2
+ const pathname = hasWindow ? window.location.pathname || "/" : "/";
3
+ const AUTH_TOKEN_KEY = "car_auth_token";
4
+
5
+ function getAuthToken() {
6
+ let token = null;
7
+ try {
8
+ token = sessionStorage.getItem(AUTH_TOKEN_KEY);
9
+ } catch (_err) {
10
+ token = null;
11
+ }
12
+ if (token) {
13
+ return token;
14
+ }
15
+ if (hasWindow && window.__CAR_AUTH_TOKEN) {
16
+ return window.__CAR_AUTH_TOKEN;
17
+ }
18
+ return null;
19
+ }
20
+
21
+ function normalizeBase(base) {
22
+ if (!base || base === "/") return "";
23
+ let normalized = base.startsWith("/") ? base : `/${base}`;
24
+ while (normalized.endsWith("/") && normalized.length > 1) {
25
+ normalized = normalized.slice(0, -1);
26
+ }
27
+ return normalized === "/" ? "" : normalized;
28
+ }
29
+
30
+ function detectBasePrefix(path) {
31
+ const prefixes = ["/repos/", "/hub/", "/api/", "/static/", "/cat/"];
32
+ let idx = -1;
33
+ for (const prefix of prefixes) {
34
+ const found = path.indexOf(prefix);
35
+ if (found === 0) {
36
+ return "";
37
+ }
38
+ if (found > 0 && (idx === -1 || found < idx)) {
39
+ idx = found;
40
+ }
41
+ }
42
+ if (idx > 0) {
43
+ return normalizeBase(path.slice(0, idx));
44
+ }
45
+ const parts = path.split("/").filter(Boolean);
46
+ if (parts.length) {
47
+ return normalizeBase(`/${parts[0]}`);
48
+ }
49
+ return "";
50
+ }
51
+
52
+ const basePrefix =
53
+ hasWindow && typeof window.__CAR_BASE_PREFIX !== "undefined"
54
+ ? window.__CAR_BASE_PREFIX
55
+ : detectBasePrefix(pathname);
56
+
57
+ const repoId =
58
+ hasWindow && typeof window.__CAR_REPO_ID !== "undefined"
59
+ ? window.__CAR_REPO_ID
60
+ : (() => {
61
+ const match = pathname.match(/\/repos\/([^/]+)/);
62
+ return match && match[1] ? match[1] : null;
63
+ })();
64
+
65
+ const derivedBasePath = repoId ? `${basePrefix}/repos/${repoId}` : basePrefix;
66
+ const basePath =
67
+ hasWindow && typeof window.__CAR_BASE_PATH !== "undefined"
68
+ ? window.__CAR_BASE_PATH
69
+ : derivedBasePath;
70
+
71
+ export const REPO_ID = repoId;
72
+ export const BASE_PATH = basePath;
73
+ export const HUB_BASE = basePrefix || "/";
74
+
75
+ let mode = repoId ? "repo" : "unknown";
76
+ const hubEndpoint = `${basePrefix || ""}/hub/repos`;
77
+
78
+ export async function detectContext() {
79
+ if (mode !== "unknown") {
80
+ return { mode, repoId: REPO_ID };
81
+ }
82
+ if (!hasWindow || typeof fetch !== "function") {
83
+ mode = "repo";
84
+ return { mode, repoId: REPO_ID };
85
+ }
86
+ try {
87
+ /** @type {Record<string, string>} */
88
+ const headers = {};
89
+ const token = getAuthToken();
90
+ if (token) {
91
+ headers.Authorization = `Bearer ${token}`;
92
+ }
93
+ const res = await fetch(hubEndpoint, { headers });
94
+ mode = res.ok ? "hub" : "repo";
95
+ } catch (err) {
96
+ mode = "repo";
97
+ }
98
+ return { mode, repoId: REPO_ID };
99
+ }
@@ -0,0 +1,168 @@
1
+ import { api, flash, statusPill } from "./utils.js";
2
+ import { registerAutoRefresh } from "./autoRefresh.js";
3
+ import { CONSTANTS } from "./constants.js";
4
+
5
+ function $(id) {
6
+ return document.getElementById(id);
7
+ }
8
+
9
+ function setText(el, text) {
10
+ if (!el) return;
11
+ el.textContent = text ?? "–";
12
+ }
13
+
14
+ function setLink(el, { href, text, title } = {}) {
15
+ if (!el) return;
16
+ if (href) {
17
+ el.href = href;
18
+ el.target = "_blank";
19
+ el.rel = "noopener noreferrer";
20
+ el.classList.remove("muted");
21
+ el.textContent = text || href;
22
+ if (title) el.title = title;
23
+ } else {
24
+ el.removeAttribute("href");
25
+ el.removeAttribute("target");
26
+ el.removeAttribute("rel");
27
+ el.classList.add("muted");
28
+ el.textContent = text || "–";
29
+ if (title) el.title = title;
30
+ }
31
+ }
32
+
33
+ async function copyToClipboard(text) {
34
+ if (!text) return false;
35
+ try {
36
+ if (navigator.clipboard?.writeText) {
37
+ await navigator.clipboard.writeText(text);
38
+ return true;
39
+ }
40
+ } catch (err) {
41
+ // ignore
42
+ }
43
+ return false;
44
+ }
45
+
46
+ async function loadGitHubStatus() {
47
+ const pill = $("github-status-pill");
48
+ const note = $("github-note");
49
+ const syncBtn = $("github-sync-pr");
50
+ const openFilesBtn = $("github-open-pr-files");
51
+ const copyPrBtn = $("github-copy-pr");
52
+
53
+ try {
54
+ const data = await api("/api/github/status");
55
+ const gh = data.gh || {};
56
+ const repo = data.repo || null;
57
+ const git = data.git || {};
58
+ const link = data.link || {};
59
+ const issue = link.issue || null;
60
+ const pr = data.pr || link.pr || null;
61
+ const prLinks = data.pr_links || null;
62
+
63
+ if (!gh.available) {
64
+ statusPill(pill, "error");
65
+ setText(note, "GitHub CLI (gh) not available.");
66
+ if (syncBtn) syncBtn.disabled = true;
67
+ } else if (!gh.authenticated) {
68
+ statusPill(pill, "warn");
69
+ setText(note, "GitHub CLI not authenticated.");
70
+ if (syncBtn) syncBtn.disabled = true;
71
+ } else {
72
+ statusPill(pill, "idle");
73
+ setText(note, git.clean ? "Clean working tree." : "Uncommitted changes.");
74
+ if (syncBtn) syncBtn.disabled = false;
75
+ }
76
+
77
+ setLink($("github-repo-link"), {
78
+ href: repo?.url,
79
+ text: repo?.nameWithOwner || "–",
80
+ title: repo?.url || "",
81
+ });
82
+ setText($("github-branch"), git.branch || "–");
83
+
84
+ setLink($("github-issue-link"), {
85
+ href: issue?.url,
86
+ text: issue?.number ? `#${issue.number}` : "–",
87
+ title: issue?.title || issue?.url || "",
88
+ });
89
+
90
+ const prUrl = prLinks?.url || pr?.url || null;
91
+ setLink($("github-pr-link"), {
92
+ href: prUrl,
93
+ text: pr?.number ? `#${pr.number}` : prUrl ? "PR" : "–",
94
+ title: pr?.title || prUrl || "",
95
+ });
96
+
97
+ const hasPr = !!prUrl;
98
+ if (openFilesBtn) openFilesBtn.disabled = !hasPr;
99
+ if (copyPrBtn) copyPrBtn.disabled = !hasPr;
100
+
101
+ if (openFilesBtn) {
102
+ openFilesBtn.onclick = () => {
103
+ const files = prLinks?.files || (prUrl ? `${prUrl}/files` : null);
104
+ if (!files) return;
105
+ window.open(files, "_blank", "noopener,noreferrer");
106
+ };
107
+ }
108
+ if (copyPrBtn) {
109
+ copyPrBtn.onclick = async () => {
110
+ if (!prUrl) return;
111
+ const ok = await copyToClipboard(prUrl);
112
+ flash(ok ? "Copied PR link" : "Copy failed", ok ? "info" : "error");
113
+ };
114
+ }
115
+
116
+ if (syncBtn) {
117
+ // Repo mode: PR sync always operates on the current working tree/branch.
118
+ syncBtn.dataset.mode = "current";
119
+ }
120
+ } catch (err) {
121
+ statusPill(pill, "error");
122
+ setText(note, err.message || "Failed to load GitHub status");
123
+ if (syncBtn) syncBtn.disabled = true;
124
+ }
125
+ }
126
+
127
+ async function syncPr() {
128
+ const syncBtn = $("github-sync-pr");
129
+ const note = $("github-note");
130
+ if (!syncBtn) return;
131
+
132
+ syncBtn.disabled = true;
133
+ syncBtn.classList.add("loading");
134
+ try {
135
+ const res = await api("/api/github/pr/sync", {
136
+ method: "POST",
137
+ body: { draft: true },
138
+ });
139
+ const created = res.created;
140
+ flash(created ? "PR created" : "PR synced");
141
+ setText(note, "");
142
+ await loadGitHubStatus();
143
+ } catch (err) {
144
+ flash(err.message || "PR sync failed", "error");
145
+ } finally {
146
+ syncBtn.disabled = false;
147
+ syncBtn.classList.remove("loading");
148
+ }
149
+ }
150
+
151
+ export function initGitHub() {
152
+ const card = $("github-card");
153
+ if (!card) return;
154
+ const syncBtn = $("github-sync-pr");
155
+ if (syncBtn) syncBtn.addEventListener("click", syncPr);
156
+
157
+ // Initial load + auto-refresh while dashboard is active.
158
+ loadGitHubStatus();
159
+ registerAutoRefresh("github-status", {
160
+ callback: loadGitHubStatus,
161
+ tabId: null, // global: keep PR link available while browsing other tabs (mobile-friendly)
162
+ interval: CONSTANTS.UI.AUTO_REFRESH_INTERVAL,
163
+ refreshOnActivation: true,
164
+ immediate: false,
165
+ });
166
+ }
167
+
168
+