codex-autorunner 0.1.2__py3-none-any.whl → 1.0.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 (189) hide show
  1. codex_autorunner/__main__.py +4 -0
  2. codex_autorunner/agents/opencode/client.py +68 -35
  3. codex_autorunner/agents/opencode/logging.py +21 -5
  4. codex_autorunner/agents/opencode/run_prompt.py +1 -0
  5. codex_autorunner/agents/opencode/runtime.py +118 -30
  6. codex_autorunner/agents/opencode/supervisor.py +36 -48
  7. codex_autorunner/agents/registry.py +136 -8
  8. codex_autorunner/api.py +25 -0
  9. codex_autorunner/bootstrap.py +16 -35
  10. codex_autorunner/cli.py +157 -139
  11. codex_autorunner/core/about_car.py +44 -32
  12. codex_autorunner/core/adapter_utils.py +21 -0
  13. codex_autorunner/core/app_server_logging.py +7 -3
  14. codex_autorunner/core/app_server_prompts.py +27 -260
  15. codex_autorunner/core/app_server_threads.py +15 -26
  16. codex_autorunner/core/codex_runner.py +6 -0
  17. codex_autorunner/core/config.py +390 -100
  18. codex_autorunner/core/docs.py +10 -2
  19. codex_autorunner/core/drafts.py +82 -0
  20. codex_autorunner/core/engine.py +278 -262
  21. codex_autorunner/core/flows/__init__.py +25 -0
  22. codex_autorunner/core/flows/controller.py +178 -0
  23. codex_autorunner/core/flows/definition.py +82 -0
  24. codex_autorunner/core/flows/models.py +75 -0
  25. codex_autorunner/core/flows/runtime.py +351 -0
  26. codex_autorunner/core/flows/store.py +485 -0
  27. codex_autorunner/core/flows/transition.py +133 -0
  28. codex_autorunner/core/flows/worker_process.py +242 -0
  29. codex_autorunner/core/hub.py +15 -9
  30. codex_autorunner/core/locks.py +4 -0
  31. codex_autorunner/core/prompt.py +15 -7
  32. codex_autorunner/core/redaction.py +29 -0
  33. codex_autorunner/core/review_context.py +5 -8
  34. codex_autorunner/core/run_index.py +6 -0
  35. codex_autorunner/core/runner_process.py +5 -2
  36. codex_autorunner/core/state.py +0 -88
  37. codex_autorunner/core/static_assets.py +55 -0
  38. codex_autorunner/core/supervisor_utils.py +67 -0
  39. codex_autorunner/core/update.py +20 -11
  40. codex_autorunner/core/update_runner.py +2 -0
  41. codex_autorunner/core/utils.py +29 -2
  42. codex_autorunner/discovery.py +2 -4
  43. codex_autorunner/flows/ticket_flow/__init__.py +3 -0
  44. codex_autorunner/flows/ticket_flow/definition.py +91 -0
  45. codex_autorunner/integrations/agents/__init__.py +27 -0
  46. codex_autorunner/integrations/agents/agent_backend.py +142 -0
  47. codex_autorunner/integrations/agents/codex_backend.py +307 -0
  48. codex_autorunner/integrations/agents/opencode_backend.py +325 -0
  49. codex_autorunner/integrations/agents/run_event.py +71 -0
  50. codex_autorunner/integrations/app_server/client.py +576 -92
  51. codex_autorunner/integrations/app_server/supervisor.py +59 -33
  52. codex_autorunner/integrations/telegram/adapter.py +141 -167
  53. codex_autorunner/integrations/telegram/api_schemas.py +120 -0
  54. codex_autorunner/integrations/telegram/config.py +175 -0
  55. codex_autorunner/integrations/telegram/constants.py +16 -1
  56. codex_autorunner/integrations/telegram/dispatch.py +17 -0
  57. codex_autorunner/integrations/telegram/doctor.py +47 -0
  58. codex_autorunner/integrations/telegram/handlers/callbacks.py +0 -4
  59. codex_autorunner/integrations/telegram/handlers/commands/__init__.py +2 -0
  60. codex_autorunner/integrations/telegram/handlers/commands/execution.py +53 -57
  61. codex_autorunner/integrations/telegram/handlers/commands/files.py +2 -6
  62. codex_autorunner/integrations/telegram/handlers/commands/flows.py +227 -0
  63. codex_autorunner/integrations/telegram/handlers/commands/formatting.py +1 -1
  64. codex_autorunner/integrations/telegram/handlers/commands/github.py +41 -582
  65. codex_autorunner/integrations/telegram/handlers/commands/workspace.py +8 -8
  66. codex_autorunner/integrations/telegram/handlers/commands_runtime.py +133 -475
  67. codex_autorunner/integrations/telegram/handlers/commands_spec.py +11 -4
  68. codex_autorunner/integrations/telegram/handlers/messages.py +120 -9
  69. codex_autorunner/integrations/telegram/helpers.py +88 -16
  70. codex_autorunner/integrations/telegram/outbox.py +208 -37
  71. codex_autorunner/integrations/telegram/progress_stream.py +3 -10
  72. codex_autorunner/integrations/telegram/service.py +214 -40
  73. codex_autorunner/integrations/telegram/state.py +100 -2
  74. codex_autorunner/integrations/telegram/ticket_flow_bridge.py +322 -0
  75. codex_autorunner/integrations/telegram/transport.py +36 -3
  76. codex_autorunner/integrations/telegram/trigger_mode.py +53 -0
  77. codex_autorunner/manifest.py +2 -0
  78. codex_autorunner/plugin_api.py +22 -0
  79. codex_autorunner/routes/__init__.py +23 -14
  80. codex_autorunner/routes/analytics.py +239 -0
  81. codex_autorunner/routes/base.py +81 -109
  82. codex_autorunner/routes/file_chat.py +836 -0
  83. codex_autorunner/routes/flows.py +980 -0
  84. codex_autorunner/routes/messages.py +459 -0
  85. codex_autorunner/routes/system.py +6 -1
  86. codex_autorunner/routes/usage.py +87 -0
  87. codex_autorunner/routes/workspace.py +271 -0
  88. codex_autorunner/server.py +2 -1
  89. codex_autorunner/static/agentControls.js +1 -0
  90. codex_autorunner/static/agentEvents.js +248 -0
  91. codex_autorunner/static/app.js +25 -22
  92. codex_autorunner/static/autoRefresh.js +29 -1
  93. codex_autorunner/static/bootstrap.js +1 -0
  94. codex_autorunner/static/bus.js +1 -0
  95. codex_autorunner/static/cache.js +1 -0
  96. codex_autorunner/static/constants.js +20 -4
  97. codex_autorunner/static/dashboard.js +162 -196
  98. codex_autorunner/static/diffRenderer.js +37 -0
  99. codex_autorunner/static/docChatCore.js +324 -0
  100. codex_autorunner/static/docChatStorage.js +65 -0
  101. codex_autorunner/static/docChatVoice.js +65 -0
  102. codex_autorunner/static/docEditor.js +133 -0
  103. codex_autorunner/static/env.js +1 -0
  104. codex_autorunner/static/eventSummarizer.js +166 -0
  105. codex_autorunner/static/fileChat.js +182 -0
  106. codex_autorunner/static/health.js +155 -0
  107. codex_autorunner/static/hub.js +41 -118
  108. codex_autorunner/static/index.html +787 -858
  109. codex_autorunner/static/liveUpdates.js +1 -0
  110. codex_autorunner/static/loader.js +1 -0
  111. codex_autorunner/static/messages.js +470 -0
  112. codex_autorunner/static/mobileCompact.js +2 -1
  113. codex_autorunner/static/settings.js +24 -211
  114. codex_autorunner/static/styles.css +7567 -3865
  115. codex_autorunner/static/tabs.js +28 -5
  116. codex_autorunner/static/terminal.js +14 -0
  117. codex_autorunner/static/terminalManager.js +34 -59
  118. codex_autorunner/static/ticketChatActions.js +333 -0
  119. codex_autorunner/static/ticketChatEvents.js +16 -0
  120. codex_autorunner/static/ticketChatStorage.js +16 -0
  121. codex_autorunner/static/ticketChatStream.js +264 -0
  122. codex_autorunner/static/ticketEditor.js +750 -0
  123. codex_autorunner/static/ticketVoice.js +9 -0
  124. codex_autorunner/static/tickets.js +1315 -0
  125. codex_autorunner/static/utils.js +32 -3
  126. codex_autorunner/static/voice.js +1 -0
  127. codex_autorunner/static/workspace.js +672 -0
  128. codex_autorunner/static/workspaceApi.js +53 -0
  129. codex_autorunner/static/workspaceFileBrowser.js +504 -0
  130. codex_autorunner/tickets/__init__.py +20 -0
  131. codex_autorunner/tickets/agent_pool.py +377 -0
  132. codex_autorunner/tickets/files.py +85 -0
  133. codex_autorunner/tickets/frontmatter.py +55 -0
  134. codex_autorunner/tickets/lint.py +102 -0
  135. codex_autorunner/tickets/models.py +95 -0
  136. codex_autorunner/tickets/outbox.py +232 -0
  137. codex_autorunner/tickets/replies.py +179 -0
  138. codex_autorunner/tickets/runner.py +823 -0
  139. codex_autorunner/tickets/spec_ingest.py +77 -0
  140. codex_autorunner/web/app.py +269 -91
  141. codex_autorunner/web/middleware.py +3 -4
  142. codex_autorunner/web/schemas.py +89 -109
  143. codex_autorunner/web/static_assets.py +1 -44
  144. codex_autorunner/workspace/__init__.py +40 -0
  145. codex_autorunner/workspace/paths.py +319 -0
  146. {codex_autorunner-0.1.2.dist-info → codex_autorunner-1.0.0.dist-info}/METADATA +18 -21
  147. codex_autorunner-1.0.0.dist-info/RECORD +251 -0
  148. {codex_autorunner-0.1.2.dist-info → codex_autorunner-1.0.0.dist-info}/WHEEL +1 -1
  149. codex_autorunner/agents/execution/policy.py +0 -292
  150. codex_autorunner/agents/factory.py +0 -52
  151. codex_autorunner/agents/orchestrator.py +0 -358
  152. codex_autorunner/core/doc_chat.py +0 -1446
  153. codex_autorunner/core/snapshot.py +0 -580
  154. codex_autorunner/integrations/github/chatops.py +0 -268
  155. codex_autorunner/integrations/github/pr_flow.py +0 -1314
  156. codex_autorunner/routes/docs.py +0 -381
  157. codex_autorunner/routes/github.py +0 -327
  158. codex_autorunner/routes/runs.py +0 -250
  159. codex_autorunner/spec_ingest.py +0 -812
  160. codex_autorunner/static/docChatActions.js +0 -287
  161. codex_autorunner/static/docChatEvents.js +0 -300
  162. codex_autorunner/static/docChatRender.js +0 -205
  163. codex_autorunner/static/docChatStream.js +0 -361
  164. codex_autorunner/static/docs.js +0 -20
  165. codex_autorunner/static/docsClipboard.js +0 -69
  166. codex_autorunner/static/docsCrud.js +0 -257
  167. codex_autorunner/static/docsDocUpdates.js +0 -62
  168. codex_autorunner/static/docsDrafts.js +0 -16
  169. codex_autorunner/static/docsElements.js +0 -69
  170. codex_autorunner/static/docsInit.js +0 -285
  171. codex_autorunner/static/docsParse.js +0 -160
  172. codex_autorunner/static/docsSnapshot.js +0 -87
  173. codex_autorunner/static/docsSpecIngest.js +0 -263
  174. codex_autorunner/static/docsState.js +0 -127
  175. codex_autorunner/static/docsThreadRegistry.js +0 -44
  176. codex_autorunner/static/docsUi.js +0 -153
  177. codex_autorunner/static/docsVoice.js +0 -56
  178. codex_autorunner/static/github.js +0 -504
  179. codex_autorunner/static/logs.js +0 -678
  180. codex_autorunner/static/review.js +0 -157
  181. codex_autorunner/static/runs.js +0 -418
  182. codex_autorunner/static/snapshot.js +0 -124
  183. codex_autorunner/static/state.js +0 -94
  184. codex_autorunner/static/todoPreview.js +0 -27
  185. codex_autorunner/workspace.py +0 -16
  186. codex_autorunner-0.1.2.dist-info/RECORD +0 -222
  187. {codex_autorunner-0.1.2.dist-info → codex_autorunner-1.0.0.dist-info}/entry_points.txt +0 -0
  188. {codex_autorunner-0.1.2.dist-info → codex_autorunner-1.0.0.dist-info}/licenses/LICENSE +0 -0
  189. {codex_autorunner-0.1.2.dist-info → codex_autorunner-1.0.0.dist-info}/top_level.txt +0 -0
@@ -1,17 +1,12 @@
1
+ // GENERATED FILE - do not edit directly. Source: static_src/
1
2
  import { api, flash, statusPill, resolvePath, escapeHtml, confirmModal, inputModal, openModal, } from "./utils.js";
2
3
  import { registerAutoRefresh } from "./autoRefresh.js";
3
4
  import { HUB_BASE } from "./env.js";
4
5
  let hubData = { repos: [], last_scan_at: null };
5
- const repoPrCache = new Map();
6
- const repoPrFetches = new Set();
7
6
  const prefetchedUrls = new Set();
8
7
  const HUB_CACHE_TTL_MS = 30000;
9
8
  const HUB_CACHE_KEY = `car:hub:${HUB_BASE || "/"}`;
10
9
  const HUB_USAGE_CACHE_KEY = `car:hub-usage:${HUB_BASE || "/"}`;
11
- const PR_CACHE_TTL_MS = 120000;
12
- const PR_FAILURE_TTL_MS = 15000;
13
- const PR_FETCH_CONCURRENCY = 3;
14
- const PR_PREFETCH_MARGIN = "200px";
15
10
  const HUB_REFRESH_ACTIVE_MS = 5000;
16
11
  const HUB_REFRESH_IDLE_MS = 30000;
17
12
  let lastHubAutoRefreshAt = 0;
@@ -27,6 +22,8 @@ const hubUsageChartCanvas = document.getElementById("hub-usage-chart-canvas");
27
22
  const hubUsageChartRange = document.getElementById("hub-usage-chart-range");
28
23
  const hubUsageChartSegment = document.getElementById("hub-usage-chart-segment");
29
24
  const hubVersionEl = document.getElementById("hub-version");
25
+ const hubInboxList = document.getElementById("hub-inbox-list");
26
+ const hubInboxRefresh = document.getElementById("hub-inbox-refresh");
30
27
  const UPDATE_STATUS_SEEN_KEY = "car_update_status_seen";
31
28
  const HUB_JOB_POLL_INTERVAL_MS = 1200;
32
29
  const HUB_JOB_TIMEOUT_MS = 180000;
@@ -37,10 +34,6 @@ const hubUsageChartState = {
37
34
  };
38
35
  let hubUsageSeriesRetryTimer = null;
39
36
  let hubUsageSummaryRetryTimer = null;
40
- const repoPrPending = new Set();
41
- const repoPrQueue = [];
42
- let repoPrActive = 0;
43
- let repoPrObserver = null;
44
37
  function saveSessionCache(key, value) {
45
38
  try {
46
39
  const payload = { at: Date.now(), value };
@@ -758,76 +751,9 @@ function inferBaseId(repo) {
758
751
  }
759
752
  return null;
760
753
  }
761
- function initRepoPrObserver() {
762
- if (!("IntersectionObserver" in window))
763
- return null;
764
- if (repoPrObserver)
765
- return repoPrObserver;
766
- repoPrObserver = new IntersectionObserver((entries) => {
767
- entries.forEach((entry) => {
768
- if (!entry.isIntersecting)
769
- return;
770
- const target = entry.target;
771
- const repoId = target?.dataset?.repoId;
772
- if (repoId) {
773
- const repo = (hubData.repos || []).find((item) => item.id === repoId);
774
- if (repo)
775
- scheduleRepoPrFetch(repo);
776
- }
777
- if (target)
778
- repoPrObserver?.unobserve(target);
779
- });
780
- }, { rootMargin: PR_PREFETCH_MARGIN });
781
- return repoPrObserver;
782
- }
783
- function scheduleRepoPrFetch(repo) {
784
- if (!repo || repo.mounted !== true)
785
- return;
786
- const cached = repoPrCache.get(repo.id);
787
- if (cached &&
788
- typeof cached.fetchedAt === "number" &&
789
- Date.now() - cached.fetchedAt <
790
- (cached.failed ? PR_FAILURE_TTL_MS : PR_CACHE_TTL_MS)) {
791
- return;
792
- }
793
- if (repoPrFetches.has(repo.id) || repoPrPending.has(repo.id))
794
- return;
795
- repoPrPending.add(repo.id);
796
- repoPrQueue.push(repo);
797
- pumpRepoPrQueue();
798
- }
799
- function pumpRepoPrQueue() {
800
- while (repoPrActive < PR_FETCH_CONCURRENCY && repoPrQueue.length) {
801
- const repo = repoPrQueue.shift();
802
- if (!repo || repoPrFetches.has(repo.id))
803
- continue;
804
- repoPrPending.delete(repo.id);
805
- repoPrActive += 1;
806
- repoPrFetches.add(repo.id);
807
- api(`/repos/${repo.id}/api/github/pr`, { method: "GET" })
808
- .then((pr) => {
809
- repoPrCache.set(repo.id, { data: pr, fetchedAt: Date.now() });
810
- })
811
- .catch(() => {
812
- repoPrCache.set(repo.id, {
813
- data: null,
814
- fetchedAt: Date.now(),
815
- failed: true,
816
- });
817
- })
818
- .finally(() => {
819
- repoPrFetches.delete(repo.id);
820
- repoPrActive -= 1;
821
- pumpRepoPrQueue();
822
- renderRepos(hubData.repos || []);
823
- });
824
- }
825
- }
826
754
  function renderRepos(repos) {
827
755
  if (!repoListEl)
828
756
  return;
829
- if (repoPrObserver)
830
- repoPrObserver.disconnect();
831
757
  repoListEl.innerHTML = "";
832
758
  if (!repos.length) {
833
759
  repoListEl.innerHTML =
@@ -902,12 +828,6 @@ function renderRepos(repos) {
902
828
  const infoLine = infoItems.length > 0
903
829
  ? `<span class="hub-repo-info-line">${escapeHtml(infoItems.join(" · "))}</span>`
904
830
  : "";
905
- const prInfo = repoPrCache.get(repo.id)?.data;
906
- const prPill = prInfo?.links?.files
907
- ? `<a class="pill pill-small hub-pr-pill" href="${escapeHtml(prInfo.links.files)}" target="_blank" rel="noopener noreferrer" title="${escapeHtml(prInfo.pr?.title || "Open PR files")}">PR${prInfo.pr?.number
908
- ? ` #${escapeHtml(prInfo.pr.number)}`
909
- : ""}</a>`
910
- : "";
911
831
  card.innerHTML = `
912
832
  <div class="hub-repo-row">
913
833
  <div class="hub-repo-left">
@@ -920,7 +840,6 @@ function renderRepos(repos) {
920
840
  <span class="hub-repo-title">${escapeHtml(repo.display_name)}</span>
921
841
  <div class="hub-repo-subline">
922
842
  ${infoLine}
923
- ${prPill}
924
843
  </div>
925
844
  </div>
926
845
  <div class="hub-repo-right">
@@ -935,15 +854,6 @@ function renderRepos(repos) {
935
854
  statusPill(statusEl, repo.status);
936
855
  }
937
856
  repoListEl.appendChild(card);
938
- if (repo.mounted === true) {
939
- const observer = initRepoPrObserver();
940
- if (observer) {
941
- observer.observe(card);
942
- }
943
- else {
944
- scheduleRepoPrFetch(repo);
945
- }
946
- }
947
857
  };
948
858
  orderedGroups.forEach((group) => {
949
859
  const repo = group.base;
@@ -980,25 +890,6 @@ function renderRepos(repos) {
980
890
  .forEach((wt) => renderRepoCard(wt, { isWorktreeRow: true }));
981
891
  }
982
892
  }
983
- async function refreshRepoPrCache(repos) {
984
- const mounted = repos.filter((r) => r && r.mounted === true);
985
- if (!mounted.length)
986
- return;
987
- const observer = initRepoPrObserver();
988
- if (observer && repoListEl) {
989
- mounted.forEach((repo) => {
990
- const card = repoListEl.querySelector(`[data-repo-id="${repo.id}"]`);
991
- if (card) {
992
- observer.observe(card);
993
- }
994
- else {
995
- scheduleRepoPrFetch(repo);
996
- }
997
- });
998
- return;
999
- }
1000
- mounted.forEach((repo) => scheduleRepoPrFetch(repo));
1001
- }
1002
893
  async function refreshHub() {
1003
894
  setButtonLoading(true);
1004
895
  try {
@@ -1008,7 +899,7 @@ async function refreshHub() {
1008
899
  saveSessionCache(HUB_CACHE_KEY, hubData);
1009
900
  renderSummary(data.repos || []);
1010
901
  renderRepos(data.repos || []);
1011
- await refreshRepoPrCache(data.repos || []).catch(() => { });
902
+ await loadHubInbox().catch(() => { });
1012
903
  await loadHubUsage().catch(() => { });
1013
904
  }
1014
905
  catch (err) {
@@ -1018,6 +909,40 @@ async function refreshHub() {
1018
909
  setButtonLoading(false);
1019
910
  }
1020
911
  }
912
+ async function loadHubInbox() {
913
+ if (!hubInboxList)
914
+ return;
915
+ hubInboxList.innerHTML = "Loading…";
916
+ try {
917
+ const payload = (await api("/hub/messages", { method: "GET" }));
918
+ const items = payload?.items || [];
919
+ if (!items.length) {
920
+ hubInboxList.innerHTML = '<div class="muted">No paused runs</div>';
921
+ return;
922
+ }
923
+ hubInboxList.innerHTML = items
924
+ .map((item) => {
925
+ const title = item.message?.title || item.message?.mode || "Message";
926
+ const excerpt = item.message?.body ? item.message.body.slice(0, 160) : "";
927
+ const repoLabel = item.repo_display_name || item.repo_id;
928
+ const href = item.open_url || `/repos/${item.repo_id}/?tab=messages&run_id=${item.run_id}`;
929
+ return `
930
+ <a class="hub-inbox-item" href="${escapeHtml(resolvePath(href))}">
931
+ <div class="hub-inbox-item-header">
932
+ <span class="hub-inbox-repo">${escapeHtml(repoLabel)}</span>
933
+ <span class="pill pill-small pill-warn">paused</span>
934
+ </div>
935
+ <div class="hub-inbox-title">${escapeHtml(title)}</div>
936
+ <div class="hub-inbox-excerpt muted small">${escapeHtml(excerpt)}</div>
937
+ </a>
938
+ `;
939
+ })
940
+ .join("");
941
+ }
942
+ catch (_err) {
943
+ hubInboxList.innerHTML = '';
944
+ }
945
+ }
1021
946
  async function triggerHubScan() {
1022
947
  setButtonLoading(true);
1023
948
  try {
@@ -1266,11 +1191,6 @@ function attachHubHandlers() {
1266
1191
  if (repoListEl) {
1267
1192
  repoListEl.addEventListener("click", (event) => {
1268
1193
  const target = event.target;
1269
- const prLink = target instanceof HTMLElement && target.closest("a.hub-pr-pill");
1270
- if (prLink) {
1271
- event.stopPropagation();
1272
- return;
1273
- }
1274
1194
  const btn = target instanceof HTMLElement && target.closest("button[data-action]");
1275
1195
  if (btn) {
1276
1196
  event.stopPropagation();
@@ -1387,6 +1307,9 @@ export function initHub() {
1387
1307
  return;
1388
1308
  attachHubHandlers();
1389
1309
  initHubUsageChartControls();
1310
+ hubInboxRefresh?.addEventListener("click", () => {
1311
+ void loadHubInbox();
1312
+ });
1390
1313
  const cachedHub = loadSessionCache(HUB_CACHE_KEY, HUB_CACHE_TTL_MS);
1391
1314
  if (cachedHub) {
1392
1315
  hubData = cachedHub;