codex-autorunner 1.1.0__py3-none-any.whl → 1.2.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/agents/opencode/client.py +113 -4
- codex_autorunner/agents/opencode/supervisor.py +4 -0
- codex_autorunner/agents/registry.py +17 -7
- codex_autorunner/bootstrap.py +219 -1
- codex_autorunner/core/__init__.py +17 -1
- codex_autorunner/core/about_car.py +114 -1
- codex_autorunner/core/app_server_threads.py +6 -0
- codex_autorunner/core/config.py +236 -1
- codex_autorunner/core/context_awareness.py +38 -0
- codex_autorunner/core/docs.py +0 -122
- codex_autorunner/core/filebox.py +265 -0
- codex_autorunner/core/flows/controller.py +71 -1
- codex_autorunner/core/flows/reconciler.py +4 -1
- codex_autorunner/core/flows/runtime.py +22 -0
- codex_autorunner/core/flows/store.py +61 -9
- codex_autorunner/core/flows/transition.py +23 -16
- codex_autorunner/core/flows/ux_helpers.py +18 -3
- codex_autorunner/core/flows/worker_process.py +32 -6
- codex_autorunner/core/hub.py +198 -41
- codex_autorunner/core/lifecycle_events.py +253 -0
- codex_autorunner/core/path_utils.py +2 -1
- codex_autorunner/core/pma_audit.py +224 -0
- codex_autorunner/core/pma_context.py +496 -0
- codex_autorunner/core/pma_dispatch_interceptor.py +284 -0
- codex_autorunner/core/pma_lifecycle.py +527 -0
- codex_autorunner/core/pma_queue.py +367 -0
- codex_autorunner/core/pma_safety.py +221 -0
- codex_autorunner/core/pma_state.py +115 -0
- codex_autorunner/core/ports/agent_backend.py +2 -5
- codex_autorunner/core/ports/run_event.py +1 -4
- codex_autorunner/core/prompt.py +0 -80
- codex_autorunner/core/prompts.py +56 -172
- codex_autorunner/core/redaction.py +0 -4
- codex_autorunner/core/review_context.py +11 -9
- codex_autorunner/core/runner_controller.py +35 -33
- codex_autorunner/core/runner_state.py +147 -0
- codex_autorunner/core/runtime.py +829 -0
- codex_autorunner/core/sqlite_utils.py +13 -4
- codex_autorunner/core/state.py +7 -10
- codex_autorunner/core/state_roots.py +5 -0
- codex_autorunner/core/templates/__init__.py +39 -0
- codex_autorunner/core/templates/git_mirror.py +234 -0
- codex_autorunner/core/templates/provenance.py +56 -0
- codex_autorunner/core/templates/scan_cache.py +120 -0
- codex_autorunner/core/ticket_linter_cli.py +17 -0
- codex_autorunner/core/ticket_manager_cli.py +154 -92
- codex_autorunner/core/time_utils.py +11 -0
- codex_autorunner/core/types.py +18 -0
- codex_autorunner/core/utils.py +34 -6
- codex_autorunner/flows/review/service.py +23 -25
- codex_autorunner/flows/ticket_flow/definition.py +43 -1
- codex_autorunner/integrations/agents/__init__.py +2 -0
- codex_autorunner/integrations/agents/backend_orchestrator.py +18 -0
- codex_autorunner/integrations/agents/codex_backend.py +19 -8
- codex_autorunner/integrations/agents/runner.py +3 -8
- codex_autorunner/integrations/agents/wiring.py +8 -0
- codex_autorunner/integrations/telegram/doctor.py +228 -6
- codex_autorunner/integrations/telegram/handlers/commands/execution.py +236 -74
- codex_autorunner/integrations/telegram/handlers/commands/files.py +314 -75
- codex_autorunner/integrations/telegram/handlers/commands/flows.py +346 -58
- codex_autorunner/integrations/telegram/handlers/commands/workspace.py +498 -37
- codex_autorunner/integrations/telegram/handlers/commands_runtime.py +202 -45
- codex_autorunner/integrations/telegram/handlers/commands_spec.py +18 -7
- codex_autorunner/integrations/telegram/handlers/messages.py +26 -1
- codex_autorunner/integrations/telegram/helpers.py +1 -3
- codex_autorunner/integrations/telegram/runtime.py +9 -4
- codex_autorunner/integrations/telegram/service.py +30 -0
- codex_autorunner/integrations/telegram/state.py +38 -0
- codex_autorunner/integrations/telegram/ticket_flow_bridge.py +10 -4
- codex_autorunner/integrations/telegram/transport.py +10 -3
- codex_autorunner/integrations/templates/__init__.py +27 -0
- codex_autorunner/integrations/templates/scan_agent.py +312 -0
- codex_autorunner/server.py +2 -2
- codex_autorunner/static/agentControls.js +21 -5
- codex_autorunner/static/app.js +115 -11
- codex_autorunner/static/chatUploads.js +137 -0
- codex_autorunner/static/docChatCore.js +185 -13
- codex_autorunner/static/fileChat.js +68 -40
- codex_autorunner/static/fileboxUi.js +159 -0
- codex_autorunner/static/hub.js +46 -81
- codex_autorunner/static/index.html +303 -24
- codex_autorunner/static/messages.js +82 -4
- codex_autorunner/static/notifications.js +255 -0
- codex_autorunner/static/pma.js +1167 -0
- codex_autorunner/static/settings.js +3 -0
- codex_autorunner/static/streamUtils.js +57 -0
- codex_autorunner/static/styles.css +9125 -6742
- codex_autorunner/static/templateReposSettings.js +225 -0
- codex_autorunner/static/ticketChatActions.js +165 -3
- codex_autorunner/static/ticketChatStream.js +17 -119
- codex_autorunner/static/ticketEditor.js +41 -13
- codex_autorunner/static/ticketTemplates.js +798 -0
- codex_autorunner/static/tickets.js +69 -19
- codex_autorunner/static/turnEvents.js +27 -0
- codex_autorunner/static/turnResume.js +33 -0
- codex_autorunner/static/utils.js +28 -0
- codex_autorunner/static/workspace.js +258 -44
- codex_autorunner/static/workspaceFileBrowser.js +6 -4
- codex_autorunner/surfaces/cli/cli.py +1465 -155
- codex_autorunner/surfaces/cli/pma_cli.py +817 -0
- codex_autorunner/surfaces/web/app.py +253 -49
- codex_autorunner/surfaces/web/routes/__init__.py +4 -0
- codex_autorunner/surfaces/web/routes/analytics.py +29 -22
- codex_autorunner/surfaces/web/routes/file_chat.py +317 -36
- codex_autorunner/surfaces/web/routes/filebox.py +227 -0
- codex_autorunner/surfaces/web/routes/flows.py +219 -29
- codex_autorunner/surfaces/web/routes/messages.py +70 -39
- codex_autorunner/surfaces/web/routes/pma.py +1652 -0
- codex_autorunner/surfaces/web/routes/repos.py +1 -1
- codex_autorunner/surfaces/web/routes/shared.py +0 -3
- codex_autorunner/surfaces/web/routes/templates.py +634 -0
- codex_autorunner/surfaces/web/runner_manager.py +2 -2
- codex_autorunner/surfaces/web/schemas.py +70 -18
- codex_autorunner/tickets/agent_pool.py +27 -0
- codex_autorunner/tickets/files.py +33 -16
- codex_autorunner/tickets/lint.py +50 -0
- codex_autorunner/tickets/models.py +3 -0
- codex_autorunner/tickets/outbox.py +41 -5
- codex_autorunner/tickets/runner.py +350 -69
- {codex_autorunner-1.1.0.dist-info → codex_autorunner-1.2.0.dist-info}/METADATA +15 -19
- {codex_autorunner-1.1.0.dist-info → codex_autorunner-1.2.0.dist-info}/RECORD +125 -94
- codex_autorunner/core/adapter_utils.py +0 -21
- codex_autorunner/core/engine.py +0 -3302
- {codex_autorunner-1.1.0.dist-info → codex_autorunner-1.2.0.dist-info}/WHEEL +0 -0
- {codex_autorunner-1.1.0.dist-info → codex_autorunner-1.2.0.dist-info}/entry_points.txt +0 -0
- {codex_autorunner-1.1.0.dist-info → codex_autorunner-1.2.0.dist-info}/licenses/LICENSE +0 -0
- {codex_autorunner-1.1.0.dist-info → codex_autorunner-1.2.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
// GENERATED FILE - do not edit directly. Source: static_src/
|
|
2
|
+
import { api, escapeHtml, openModal, resolvePath } from "./utils.js";
|
|
3
|
+
import { registerAutoRefresh } from "./autoRefresh.js";
|
|
4
|
+
let notificationsInitialized = false;
|
|
5
|
+
let notificationItems = [];
|
|
6
|
+
let activeRoot = null;
|
|
7
|
+
let closeModalFn = null;
|
|
8
|
+
let documentListenerInstalled = false;
|
|
9
|
+
let modalElements = null;
|
|
10
|
+
let isRefreshing = false;
|
|
11
|
+
const NOTIFICATIONS_REFRESH_ID = "notifications";
|
|
12
|
+
const NOTIFICATIONS_REFRESH_MS = 15000;
|
|
13
|
+
function getModalElements() {
|
|
14
|
+
if (modalElements)
|
|
15
|
+
return modalElements;
|
|
16
|
+
const overlay = document.getElementById("notifications-modal");
|
|
17
|
+
const body = document.getElementById("notifications-modal-body");
|
|
18
|
+
const closeBtn = document.getElementById("notifications-modal-close");
|
|
19
|
+
if (!overlay || !body || !closeBtn)
|
|
20
|
+
return null;
|
|
21
|
+
modalElements = { overlay, body, closeBtn };
|
|
22
|
+
return modalElements;
|
|
23
|
+
}
|
|
24
|
+
function getRootElements(root) {
|
|
25
|
+
const trigger = root.querySelector("[data-notifications-trigger]");
|
|
26
|
+
const badge = root.querySelector("[data-notifications-badge]");
|
|
27
|
+
const dropdown = root.querySelector("[data-notifications-dropdown]");
|
|
28
|
+
if (!trigger || !badge || !dropdown)
|
|
29
|
+
return null;
|
|
30
|
+
return { root, trigger, badge, dropdown };
|
|
31
|
+
}
|
|
32
|
+
function setBadgeCount(count) {
|
|
33
|
+
const roots = document.querySelectorAll("[data-notifications-root]");
|
|
34
|
+
roots.forEach((root) => {
|
|
35
|
+
const elements = getRootElements(root);
|
|
36
|
+
if (!elements)
|
|
37
|
+
return;
|
|
38
|
+
elements.badge.textContent = count > 0 ? String(count) : "";
|
|
39
|
+
elements.badge.classList.toggle("hidden", count <= 0);
|
|
40
|
+
elements.trigger.setAttribute("aria-label", count > 0 ? `Notifications (${count})` : "Notifications");
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function normalizeItem(item) {
|
|
44
|
+
const repoId = String(item.repo_id || "");
|
|
45
|
+
const repoDisplay = item.repo_display_name || repoId;
|
|
46
|
+
const mode = item.dispatch?.mode || "";
|
|
47
|
+
const title = (item.dispatch?.title || "").trim();
|
|
48
|
+
const fallbackTitle = title || mode || "Dispatch";
|
|
49
|
+
const body = item.dispatch?.body || "";
|
|
50
|
+
const isHandoff = Boolean(item.dispatch?.is_handoff) || mode === "pause";
|
|
51
|
+
const runId = String(item.run_id || "");
|
|
52
|
+
const openUrl = item.open_url || `/repos/${repoId}/?tab=inbox&run_id=${runId}`;
|
|
53
|
+
return {
|
|
54
|
+
repoId,
|
|
55
|
+
repoDisplay,
|
|
56
|
+
runId,
|
|
57
|
+
status: item.status || "paused",
|
|
58
|
+
seq: item.seq,
|
|
59
|
+
title: fallbackTitle,
|
|
60
|
+
mode,
|
|
61
|
+
body,
|
|
62
|
+
isHandoff,
|
|
63
|
+
openUrl,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function renderDropdown(root) {
|
|
67
|
+
if (!root)
|
|
68
|
+
return;
|
|
69
|
+
if (!notificationItems.length) {
|
|
70
|
+
root.dropdown.innerHTML = '<div class="notifications-empty muted small">No pending dispatches</div>';
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const html = notificationItems
|
|
74
|
+
.map((item, index) => {
|
|
75
|
+
const pill = item.isHandoff ? "handoff" : "paused";
|
|
76
|
+
return `
|
|
77
|
+
<button class="notifications-item" type="button" data-index="${index}">
|
|
78
|
+
<span class="notifications-item-repo">${escapeHtml(item.repoDisplay)}</span>
|
|
79
|
+
<span class="notifications-item-title">${escapeHtml(item.title)}</span>
|
|
80
|
+
<span class="pill pill-small pill-warn notifications-item-pill">${escapeHtml(pill)}</span>
|
|
81
|
+
</button>
|
|
82
|
+
`;
|
|
83
|
+
})
|
|
84
|
+
.join("");
|
|
85
|
+
root.dropdown.innerHTML = html;
|
|
86
|
+
}
|
|
87
|
+
function renderDropdownError(root) {
|
|
88
|
+
if (!root)
|
|
89
|
+
return;
|
|
90
|
+
root.dropdown.innerHTML = '<div class="notifications-empty muted small">Failed to load dispatches</div>';
|
|
91
|
+
}
|
|
92
|
+
function closeDropdown() {
|
|
93
|
+
if (!activeRoot)
|
|
94
|
+
return;
|
|
95
|
+
activeRoot.dropdown.classList.add("hidden");
|
|
96
|
+
activeRoot.trigger.setAttribute("aria-expanded", "false");
|
|
97
|
+
activeRoot = null;
|
|
98
|
+
removeDocumentListener();
|
|
99
|
+
}
|
|
100
|
+
function openDropdown(root) {
|
|
101
|
+
if (activeRoot && activeRoot !== root) {
|
|
102
|
+
activeRoot.dropdown.classList.add("hidden");
|
|
103
|
+
activeRoot.trigger.setAttribute("aria-expanded", "false");
|
|
104
|
+
}
|
|
105
|
+
activeRoot = root;
|
|
106
|
+
renderDropdown(root);
|
|
107
|
+
root.dropdown.classList.remove("hidden");
|
|
108
|
+
root.trigger.setAttribute("aria-expanded", "true");
|
|
109
|
+
installDocumentListener();
|
|
110
|
+
}
|
|
111
|
+
function toggleDropdown(root) {
|
|
112
|
+
if (activeRoot && activeRoot === root && !root.dropdown.classList.contains("hidden")) {
|
|
113
|
+
closeDropdown();
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
openDropdown(root);
|
|
117
|
+
}
|
|
118
|
+
function installDocumentListener() {
|
|
119
|
+
if (documentListenerInstalled)
|
|
120
|
+
return;
|
|
121
|
+
documentListenerInstalled = true;
|
|
122
|
+
document.addEventListener("pointerdown", handleDocumentPointerDown);
|
|
123
|
+
}
|
|
124
|
+
function removeDocumentListener() {
|
|
125
|
+
if (!documentListenerInstalled)
|
|
126
|
+
return;
|
|
127
|
+
documentListenerInstalled = false;
|
|
128
|
+
document.removeEventListener("pointerdown", handleDocumentPointerDown);
|
|
129
|
+
}
|
|
130
|
+
function handleDocumentPointerDown(event) {
|
|
131
|
+
if (!activeRoot)
|
|
132
|
+
return;
|
|
133
|
+
const target = event.target;
|
|
134
|
+
if (!target || !activeRoot.root.contains(target)) {
|
|
135
|
+
closeDropdown();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function closeNotificationsModal() {
|
|
139
|
+
if (!closeModalFn)
|
|
140
|
+
return;
|
|
141
|
+
closeModalFn();
|
|
142
|
+
closeModalFn = null;
|
|
143
|
+
}
|
|
144
|
+
function openNotificationsModal(item, returnFocusTo) {
|
|
145
|
+
const modal = getModalElements();
|
|
146
|
+
if (!modal)
|
|
147
|
+
return;
|
|
148
|
+
closeNotificationsModal();
|
|
149
|
+
const runLabel = item.seq ? `${item.runId.slice(0, 8)} (#${item.seq})` : item.runId.slice(0, 8);
|
|
150
|
+
const modeLabel = item.mode ? ` (${item.mode})` : "";
|
|
151
|
+
const body = item.body?.trim() ? escapeHtml(item.body) : '<span class="muted">No message body.</span>';
|
|
152
|
+
modal.body.innerHTML = `
|
|
153
|
+
<div class="notifications-modal-meta">
|
|
154
|
+
<div class="notifications-modal-row">
|
|
155
|
+
<span class="notifications-modal-label">Repo</span>
|
|
156
|
+
<span class="notifications-modal-value">${escapeHtml(item.repoDisplay)}</span>
|
|
157
|
+
</div>
|
|
158
|
+
<div class="notifications-modal-row">
|
|
159
|
+
<span class="notifications-modal-label">Run</span>
|
|
160
|
+
<span class="notifications-modal-value mono">${escapeHtml(runLabel)}</span>
|
|
161
|
+
</div>
|
|
162
|
+
<div class="notifications-modal-row">
|
|
163
|
+
<span class="notifications-modal-label">Dispatch</span>
|
|
164
|
+
<span class="notifications-modal-value">${escapeHtml(item.title)}${escapeHtml(modeLabel)}</span>
|
|
165
|
+
</div>
|
|
166
|
+
</div>
|
|
167
|
+
<div class="notifications-modal-body">${body}</div>
|
|
168
|
+
<div class="notifications-modal-actions">
|
|
169
|
+
<a class="primary sm notifications-open-run" href="${escapeHtml(resolvePath(item.openUrl))}">Open run</a>
|
|
170
|
+
</div>
|
|
171
|
+
<div class="notifications-modal-placeholder">Reply here (coming soon).</div>
|
|
172
|
+
`;
|
|
173
|
+
closeModalFn = openModal(modal.overlay, {
|
|
174
|
+
closeOnEscape: true,
|
|
175
|
+
closeOnOverlay: true,
|
|
176
|
+
initialFocus: modal.closeBtn,
|
|
177
|
+
returnFocusTo: returnFocusTo || null,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
async function refreshNotifications(_ctx) {
|
|
181
|
+
if (isRefreshing)
|
|
182
|
+
return;
|
|
183
|
+
isRefreshing = true;
|
|
184
|
+
try {
|
|
185
|
+
const payload = (await api("/hub/messages", { method: "GET" }));
|
|
186
|
+
const items = payload?.items || [];
|
|
187
|
+
notificationItems = items.map(normalizeItem);
|
|
188
|
+
setBadgeCount(notificationItems.length);
|
|
189
|
+
if (activeRoot) {
|
|
190
|
+
renderDropdown(activeRoot);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
catch (_err) {
|
|
194
|
+
if (activeRoot) {
|
|
195
|
+
renderDropdownError(activeRoot);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
finally {
|
|
199
|
+
isRefreshing = false;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function attachRoot(root) {
|
|
203
|
+
root.trigger.setAttribute("aria-haspopup", "menu");
|
|
204
|
+
root.trigger.setAttribute("aria-expanded", "false");
|
|
205
|
+
root.trigger.addEventListener("pointerdown", (event) => {
|
|
206
|
+
event.preventDefault();
|
|
207
|
+
event.stopPropagation();
|
|
208
|
+
toggleDropdown(root);
|
|
209
|
+
});
|
|
210
|
+
root.trigger.addEventListener("click", (event) => {
|
|
211
|
+
event.preventDefault();
|
|
212
|
+
event.stopPropagation();
|
|
213
|
+
});
|
|
214
|
+
root.dropdown.addEventListener("click", (event) => {
|
|
215
|
+
const target = event.target?.closest(".notifications-item");
|
|
216
|
+
if (!target)
|
|
217
|
+
return;
|
|
218
|
+
const index = Number(target.dataset.index || "-1");
|
|
219
|
+
const item = notificationItems[index];
|
|
220
|
+
if (!item)
|
|
221
|
+
return;
|
|
222
|
+
closeDropdown();
|
|
223
|
+
openNotificationsModal(item, root.trigger);
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
function attachModalHandlers() {
|
|
227
|
+
const modal = getModalElements();
|
|
228
|
+
if (!modal)
|
|
229
|
+
return;
|
|
230
|
+
modal.closeBtn.addEventListener("click", () => {
|
|
231
|
+
closeNotificationsModal();
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
export function initNotifications() {
|
|
235
|
+
if (notificationsInitialized)
|
|
236
|
+
return;
|
|
237
|
+
const roots = Array.from(document.querySelectorAll("[data-notifications-root]"));
|
|
238
|
+
if (!roots.length)
|
|
239
|
+
return;
|
|
240
|
+
roots.forEach((root) => {
|
|
241
|
+
const elements = getRootElements(root);
|
|
242
|
+
if (!elements)
|
|
243
|
+
return;
|
|
244
|
+
attachRoot(elements);
|
|
245
|
+
});
|
|
246
|
+
attachModalHandlers();
|
|
247
|
+
registerAutoRefresh(NOTIFICATIONS_REFRESH_ID, {
|
|
248
|
+
callback: refreshNotifications,
|
|
249
|
+
tabId: null,
|
|
250
|
+
interval: NOTIFICATIONS_REFRESH_MS,
|
|
251
|
+
refreshOnActivation: true,
|
|
252
|
+
immediate: true,
|
|
253
|
+
});
|
|
254
|
+
notificationsInitialized = true;
|
|
255
|
+
}
|