codex-autorunner 0.1.2__py3-none-any.whl → 1.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 +12 -1
- codex_autorunner/__main__.py +4 -0
- codex_autorunner/agents/codex/harness.py +1 -1
- codex_autorunner/agents/opencode/client.py +68 -35
- codex_autorunner/agents/opencode/constants.py +3 -0
- codex_autorunner/agents/opencode/harness.py +6 -1
- codex_autorunner/agents/opencode/logging.py +21 -5
- codex_autorunner/agents/opencode/run_prompt.py +1 -0
- codex_autorunner/agents/opencode/runtime.py +176 -47
- codex_autorunner/agents/opencode/supervisor.py +36 -48
- codex_autorunner/agents/registry.py +155 -8
- codex_autorunner/api.py +25 -0
- codex_autorunner/bootstrap.py +22 -37
- codex_autorunner/cli.py +5 -1156
- codex_autorunner/codex_cli.py +20 -84
- codex_autorunner/core/__init__.py +4 -0
- codex_autorunner/core/about_car.py +49 -32
- codex_autorunner/core/adapter_utils.py +21 -0
- codex_autorunner/core/app_server_ids.py +59 -0
- codex_autorunner/core/app_server_logging.py +7 -3
- codex_autorunner/core/app_server_prompts.py +27 -260
- codex_autorunner/core/app_server_threads.py +26 -28
- codex_autorunner/core/app_server_utils.py +165 -0
- codex_autorunner/core/archive.py +349 -0
- codex_autorunner/core/codex_runner.py +12 -2
- codex_autorunner/core/config.py +587 -103
- codex_autorunner/core/docs.py +10 -2
- codex_autorunner/core/drafts.py +136 -0
- codex_autorunner/core/engine.py +1531 -866
- codex_autorunner/core/exceptions.py +4 -0
- codex_autorunner/core/flows/__init__.py +25 -0
- codex_autorunner/core/flows/controller.py +202 -0
- codex_autorunner/core/flows/definition.py +82 -0
- codex_autorunner/core/flows/models.py +88 -0
- codex_autorunner/core/flows/reasons.py +52 -0
- codex_autorunner/core/flows/reconciler.py +131 -0
- codex_autorunner/core/flows/runtime.py +382 -0
- codex_autorunner/core/flows/store.py +568 -0
- codex_autorunner/core/flows/transition.py +138 -0
- codex_autorunner/core/flows/ux_helpers.py +257 -0
- codex_autorunner/core/flows/worker_process.py +242 -0
- codex_autorunner/core/git_utils.py +62 -0
- codex_autorunner/core/hub.py +136 -16
- codex_autorunner/core/locks.py +4 -0
- codex_autorunner/core/notifications.py +14 -2
- codex_autorunner/core/ports/__init__.py +28 -0
- codex_autorunner/core/ports/agent_backend.py +150 -0
- codex_autorunner/core/ports/backend_orchestrator.py +41 -0
- codex_autorunner/core/ports/run_event.py +91 -0
- codex_autorunner/core/prompt.py +15 -7
- codex_autorunner/core/redaction.py +29 -0
- codex_autorunner/core/review_context.py +5 -8
- codex_autorunner/core/run_index.py +6 -0
- codex_autorunner/core/runner_process.py +5 -2
- codex_autorunner/core/state.py +0 -88
- codex_autorunner/core/state_roots.py +57 -0
- codex_autorunner/core/supervisor_protocol.py +15 -0
- codex_autorunner/core/supervisor_utils.py +67 -0
- codex_autorunner/core/text_delta_coalescer.py +54 -0
- codex_autorunner/core/ticket_linter_cli.py +201 -0
- codex_autorunner/core/ticket_manager_cli.py +432 -0
- codex_autorunner/core/update.py +24 -16
- codex_autorunner/core/update_paths.py +28 -0
- codex_autorunner/core/update_runner.py +2 -0
- codex_autorunner/core/usage.py +164 -12
- codex_autorunner/core/utils.py +120 -11
- codex_autorunner/discovery.py +2 -4
- codex_autorunner/flows/review/__init__.py +17 -0
- codex_autorunner/{core/review.py → flows/review/service.py} +15 -10
- codex_autorunner/flows/ticket_flow/__init__.py +3 -0
- codex_autorunner/flows/ticket_flow/definition.py +98 -0
- codex_autorunner/integrations/agents/__init__.py +17 -0
- codex_autorunner/integrations/agents/backend_orchestrator.py +284 -0
- codex_autorunner/integrations/agents/codex_adapter.py +90 -0
- codex_autorunner/integrations/agents/codex_backend.py +448 -0
- codex_autorunner/integrations/agents/opencode_adapter.py +108 -0
- codex_autorunner/integrations/agents/opencode_backend.py +598 -0
- codex_autorunner/integrations/agents/runner.py +91 -0
- codex_autorunner/integrations/agents/wiring.py +271 -0
- codex_autorunner/integrations/app_server/client.py +583 -152
- codex_autorunner/integrations/app_server/env.py +2 -107
- codex_autorunner/{core/app_server_events.py → integrations/app_server/event_buffer.py} +15 -8
- codex_autorunner/integrations/app_server/supervisor.py +59 -33
- codex_autorunner/integrations/telegram/adapter.py +204 -165
- codex_autorunner/integrations/telegram/api_schemas.py +120 -0
- codex_autorunner/integrations/telegram/config.py +221 -0
- codex_autorunner/integrations/telegram/constants.py +17 -2
- codex_autorunner/integrations/telegram/dispatch.py +17 -0
- codex_autorunner/integrations/telegram/doctor.py +47 -0
- codex_autorunner/integrations/telegram/handlers/callbacks.py +7 -4
- codex_autorunner/integrations/telegram/handlers/commands/__init__.py +2 -0
- codex_autorunner/integrations/telegram/handlers/commands/execution.py +53 -57
- codex_autorunner/integrations/telegram/handlers/commands/files.py +2 -6
- codex_autorunner/integrations/telegram/handlers/commands/flows.py +1364 -0
- codex_autorunner/integrations/telegram/handlers/commands/formatting.py +1 -1
- codex_autorunner/integrations/telegram/handlers/commands/github.py +41 -582
- codex_autorunner/integrations/telegram/handlers/commands/workspace.py +8 -8
- codex_autorunner/integrations/telegram/handlers/commands_runtime.py +137 -478
- codex_autorunner/integrations/telegram/handlers/commands_spec.py +17 -4
- codex_autorunner/integrations/telegram/handlers/messages.py +121 -9
- codex_autorunner/integrations/telegram/handlers/selections.py +61 -1
- codex_autorunner/integrations/telegram/helpers.py +111 -16
- codex_autorunner/integrations/telegram/outbox.py +208 -37
- codex_autorunner/integrations/telegram/progress_stream.py +3 -10
- codex_autorunner/integrations/telegram/service.py +221 -42
- codex_autorunner/integrations/telegram/state.py +100 -2
- codex_autorunner/integrations/telegram/ticket_flow_bridge.py +611 -0
- codex_autorunner/integrations/telegram/transport.py +39 -4
- codex_autorunner/integrations/telegram/trigger_mode.py +53 -0
- codex_autorunner/manifest.py +2 -0
- codex_autorunner/plugin_api.py +22 -0
- codex_autorunner/routes/__init__.py +37 -67
- codex_autorunner/routes/agents.py +2 -137
- codex_autorunner/routes/analytics.py +3 -0
- codex_autorunner/routes/app_server.py +2 -131
- codex_autorunner/routes/base.py +2 -624
- codex_autorunner/routes/file_chat.py +7 -0
- codex_autorunner/routes/flows.py +7 -0
- codex_autorunner/routes/messages.py +7 -0
- codex_autorunner/routes/repos.py +2 -196
- codex_autorunner/routes/review.py +2 -147
- codex_autorunner/routes/sessions.py +2 -175
- codex_autorunner/routes/settings.py +2 -168
- codex_autorunner/routes/shared.py +2 -275
- codex_autorunner/routes/system.py +4 -188
- codex_autorunner/routes/usage.py +3 -0
- codex_autorunner/routes/voice.py +2 -119
- codex_autorunner/routes/workspace.py +3 -0
- codex_autorunner/server.py +3 -2
- codex_autorunner/static/agentControls.js +41 -11
- codex_autorunner/static/agentEvents.js +248 -0
- codex_autorunner/static/app.js +35 -24
- codex_autorunner/static/archive.js +826 -0
- codex_autorunner/static/archiveApi.js +37 -0
- codex_autorunner/static/autoRefresh.js +36 -8
- codex_autorunner/static/bootstrap.js +1 -0
- codex_autorunner/static/bus.js +1 -0
- codex_autorunner/static/cache.js +1 -0
- codex_autorunner/static/constants.js +20 -4
- codex_autorunner/static/dashboard.js +344 -325
- codex_autorunner/static/diffRenderer.js +37 -0
- codex_autorunner/static/docChatCore.js +324 -0
- codex_autorunner/static/docChatStorage.js +65 -0
- codex_autorunner/static/docChatVoice.js +65 -0
- codex_autorunner/static/docEditor.js +133 -0
- codex_autorunner/static/env.js +1 -0
- codex_autorunner/static/eventSummarizer.js +166 -0
- codex_autorunner/static/fileChat.js +182 -0
- codex_autorunner/static/health.js +155 -0
- codex_autorunner/static/hub.js +126 -185
- codex_autorunner/static/index.html +839 -863
- codex_autorunner/static/liveUpdates.js +1 -0
- codex_autorunner/static/loader.js +1 -0
- codex_autorunner/static/messages.js +873 -0
- codex_autorunner/static/mobileCompact.js +2 -1
- codex_autorunner/static/preserve.js +17 -0
- codex_autorunner/static/settings.js +149 -217
- codex_autorunner/static/smartRefresh.js +52 -0
- codex_autorunner/static/styles.css +8850 -3876
- codex_autorunner/static/tabs.js +175 -11
- codex_autorunner/static/terminal.js +32 -0
- codex_autorunner/static/terminalManager.js +34 -59
- codex_autorunner/static/ticketChatActions.js +333 -0
- codex_autorunner/static/ticketChatEvents.js +16 -0
- codex_autorunner/static/ticketChatStorage.js +16 -0
- codex_autorunner/static/ticketChatStream.js +264 -0
- codex_autorunner/static/ticketEditor.js +844 -0
- codex_autorunner/static/ticketVoice.js +9 -0
- codex_autorunner/static/tickets.js +1988 -0
- codex_autorunner/static/utils.js +43 -3
- codex_autorunner/static/voice.js +1 -0
- codex_autorunner/static/workspace.js +765 -0
- codex_autorunner/static/workspaceApi.js +53 -0
- codex_autorunner/static/workspaceFileBrowser.js +504 -0
- codex_autorunner/surfaces/__init__.py +5 -0
- codex_autorunner/surfaces/cli/__init__.py +6 -0
- codex_autorunner/surfaces/cli/cli.py +1224 -0
- codex_autorunner/surfaces/cli/codex_cli.py +20 -0
- codex_autorunner/surfaces/telegram/__init__.py +3 -0
- codex_autorunner/surfaces/web/__init__.py +1 -0
- codex_autorunner/surfaces/web/app.py +2019 -0
- codex_autorunner/surfaces/web/hub_jobs.py +192 -0
- codex_autorunner/surfaces/web/middleware.py +587 -0
- codex_autorunner/surfaces/web/pty_session.py +370 -0
- codex_autorunner/surfaces/web/review.py +6 -0
- codex_autorunner/surfaces/web/routes/__init__.py +78 -0
- codex_autorunner/surfaces/web/routes/agents.py +138 -0
- codex_autorunner/surfaces/web/routes/analytics.py +277 -0
- codex_autorunner/surfaces/web/routes/app_server.py +132 -0
- codex_autorunner/surfaces/web/routes/archive.py +357 -0
- codex_autorunner/surfaces/web/routes/base.py +615 -0
- codex_autorunner/surfaces/web/routes/file_chat.py +836 -0
- codex_autorunner/surfaces/web/routes/flows.py +1164 -0
- codex_autorunner/surfaces/web/routes/messages.py +459 -0
- codex_autorunner/surfaces/web/routes/repos.py +197 -0
- codex_autorunner/surfaces/web/routes/review.py +148 -0
- codex_autorunner/surfaces/web/routes/sessions.py +176 -0
- codex_autorunner/surfaces/web/routes/settings.py +169 -0
- codex_autorunner/surfaces/web/routes/shared.py +280 -0
- codex_autorunner/surfaces/web/routes/system.py +196 -0
- codex_autorunner/surfaces/web/routes/usage.py +89 -0
- codex_autorunner/surfaces/web/routes/voice.py +120 -0
- codex_autorunner/surfaces/web/routes/workspace.py +271 -0
- codex_autorunner/surfaces/web/runner_manager.py +25 -0
- codex_autorunner/surfaces/web/schemas.py +417 -0
- codex_autorunner/surfaces/web/static_assets.py +490 -0
- codex_autorunner/surfaces/web/static_refresh.py +86 -0
- codex_autorunner/surfaces/web/terminal_sessions.py +78 -0
- codex_autorunner/tickets/__init__.py +27 -0
- codex_autorunner/tickets/agent_pool.py +399 -0
- codex_autorunner/tickets/files.py +89 -0
- codex_autorunner/tickets/frontmatter.py +55 -0
- codex_autorunner/tickets/lint.py +102 -0
- codex_autorunner/tickets/models.py +97 -0
- codex_autorunner/tickets/outbox.py +244 -0
- codex_autorunner/tickets/replies.py +179 -0
- codex_autorunner/tickets/runner.py +881 -0
- codex_autorunner/tickets/spec_ingest.py +77 -0
- codex_autorunner/web/__init__.py +5 -1
- codex_autorunner/web/app.py +2 -1771
- codex_autorunner/web/hub_jobs.py +2 -191
- codex_autorunner/web/middleware.py +2 -587
- codex_autorunner/web/pty_session.py +2 -369
- codex_autorunner/web/runner_manager.py +2 -24
- codex_autorunner/web/schemas.py +2 -396
- codex_autorunner/web/static_assets.py +4 -484
- codex_autorunner/web/static_refresh.py +2 -85
- codex_autorunner/web/terminal_sessions.py +2 -77
- codex_autorunner/workspace/__init__.py +40 -0
- codex_autorunner/workspace/paths.py +335 -0
- codex_autorunner-1.1.0.dist-info/METADATA +154 -0
- codex_autorunner-1.1.0.dist-info/RECORD +308 -0
- {codex_autorunner-0.1.2.dist-info → codex_autorunner-1.1.0.dist-info}/WHEEL +1 -1
- codex_autorunner/agents/execution/policy.py +0 -292
- codex_autorunner/agents/factory.py +0 -52
- codex_autorunner/agents/orchestrator.py +0 -358
- codex_autorunner/core/doc_chat.py +0 -1446
- codex_autorunner/core/snapshot.py +0 -580
- codex_autorunner/integrations/github/chatops.py +0 -268
- codex_autorunner/integrations/github/pr_flow.py +0 -1314
- codex_autorunner/routes/docs.py +0 -381
- codex_autorunner/routes/github.py +0 -327
- codex_autorunner/routes/runs.py +0 -250
- codex_autorunner/spec_ingest.py +0 -812
- codex_autorunner/static/docChatActions.js +0 -287
- codex_autorunner/static/docChatEvents.js +0 -300
- codex_autorunner/static/docChatRender.js +0 -205
- codex_autorunner/static/docChatStream.js +0 -361
- codex_autorunner/static/docs.js +0 -20
- codex_autorunner/static/docsClipboard.js +0 -69
- codex_autorunner/static/docsCrud.js +0 -257
- codex_autorunner/static/docsDocUpdates.js +0 -62
- codex_autorunner/static/docsDrafts.js +0 -16
- codex_autorunner/static/docsElements.js +0 -69
- codex_autorunner/static/docsInit.js +0 -285
- codex_autorunner/static/docsParse.js +0 -160
- codex_autorunner/static/docsSnapshot.js +0 -87
- codex_autorunner/static/docsSpecIngest.js +0 -263
- codex_autorunner/static/docsState.js +0 -127
- codex_autorunner/static/docsThreadRegistry.js +0 -44
- codex_autorunner/static/docsUi.js +0 -153
- codex_autorunner/static/docsVoice.js +0 -56
- codex_autorunner/static/github.js +0 -504
- codex_autorunner/static/logs.js +0 -678
- codex_autorunner/static/review.js +0 -157
- codex_autorunner/static/runs.js +0 -418
- codex_autorunner/static/snapshot.js +0 -124
- codex_autorunner/static/state.js +0 -94
- codex_autorunner/static/todoPreview.js +0 -27
- codex_autorunner/workspace.py +0 -16
- codex_autorunner-0.1.2.dist-info/METADATA +0 -249
- codex_autorunner-0.1.2.dist-info/RECORD +0 -222
- /codex_autorunner/{routes → surfaces/web/routes}/terminal_images.py +0 -0
- {codex_autorunner-0.1.2.dist-info → codex_autorunner-1.1.0.dist-info}/entry_points.txt +0 -0
- {codex_autorunner-0.1.2.dist-info → codex_autorunner-1.1.0.dist-info}/licenses/LICENSE +0 -0
- {codex_autorunner-0.1.2.dist-info → codex_autorunner-1.1.0.dist-info}/top_level.txt +0 -0
codex_autorunner/static/tabs.js
CHANGED
|
@@ -1,41 +1,205 @@
|
|
|
1
|
+
// GENERATED FILE - do not edit directly. Source: static_src/
|
|
1
2
|
import { publish } from "./bus.js";
|
|
2
|
-
import { getUrlParams, updateUrlParams } from "./utils.js";
|
|
3
|
+
import { escapeHtml, getUrlParams, updateUrlParams } from "./utils.js";
|
|
3
4
|
const tabs = [];
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
const hamburgerActions = [];
|
|
6
|
+
let hamburgerMenuOpen = false;
|
|
7
|
+
let hamburgerMenuEl = null;
|
|
8
|
+
let hamburgerBtnEl = null;
|
|
9
|
+
let hamburgerBackdropEl = null;
|
|
10
|
+
export function registerTab(id, label, opts = {}) {
|
|
11
|
+
tabs.push({ id, label, hidden: Boolean(opts.hidden), menuTab: Boolean(opts.menuTab), icon: opts.icon });
|
|
6
12
|
}
|
|
7
|
-
export function
|
|
13
|
+
export function registerHamburgerAction(id, label, icon, onClick) {
|
|
14
|
+
hamburgerActions.push({ id, label, icon, onClick });
|
|
15
|
+
}
|
|
16
|
+
let setActivePanelFn = null;
|
|
17
|
+
let pendingActivate = null;
|
|
18
|
+
export function activateTab(id) {
|
|
19
|
+
if (setActivePanelFn) {
|
|
20
|
+
setActivePanelFn(id);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
pendingActivate = id;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function closeHamburgerMenu() {
|
|
27
|
+
if (!hamburgerMenuOpen)
|
|
28
|
+
return;
|
|
29
|
+
hamburgerMenuOpen = false;
|
|
30
|
+
hamburgerMenuEl?.classList.remove("open");
|
|
31
|
+
hamburgerBtnEl?.classList.remove("active");
|
|
32
|
+
hamburgerBackdropEl?.classList.remove("open");
|
|
33
|
+
}
|
|
34
|
+
function toggleHamburgerMenu() {
|
|
35
|
+
hamburgerMenuOpen = !hamburgerMenuOpen;
|
|
36
|
+
hamburgerMenuEl?.classList.toggle("open", hamburgerMenuOpen);
|
|
37
|
+
hamburgerBtnEl?.classList.toggle("active", hamburgerMenuOpen);
|
|
38
|
+
hamburgerBackdropEl?.classList.toggle("open", hamburgerMenuOpen);
|
|
39
|
+
}
|
|
40
|
+
function updateHamburgerActiveState(activeTabId) {
|
|
41
|
+
if (!hamburgerMenuEl)
|
|
42
|
+
return;
|
|
43
|
+
const items = hamburgerMenuEl.querySelectorAll(".hamburger-item[data-target]");
|
|
44
|
+
items.forEach((item) => {
|
|
45
|
+
const target = item.dataset.target;
|
|
46
|
+
item.classList.toggle("active", target === activeTabId);
|
|
47
|
+
});
|
|
48
|
+
// Also update hamburger button active state if a menu tab is active
|
|
49
|
+
const isMenuTabActive = tabs.some((t) => t.menuTab && t.id === activeTabId);
|
|
50
|
+
hamburgerBtnEl?.classList.toggle("has-active", isMenuTabActive);
|
|
51
|
+
}
|
|
52
|
+
export function initTabs(defaultTab = "analytics") {
|
|
8
53
|
const container = document.querySelector(".tabs");
|
|
54
|
+
const navBar = document.querySelector(".nav-bar");
|
|
9
55
|
if (!container)
|
|
10
56
|
return;
|
|
11
57
|
container.innerHTML = "";
|
|
12
58
|
const panels = document.querySelectorAll(".panel");
|
|
13
59
|
const setActivePanel = (id) => {
|
|
14
60
|
panels.forEach((p) => p.classList.toggle("active", p.id === id));
|
|
61
|
+
// Update primary tab buttons
|
|
15
62
|
const buttons = container.querySelectorAll(".tab");
|
|
16
63
|
buttons.forEach((btn) => btn.classList.toggle("active", btn.dataset.target === id));
|
|
64
|
+
// Update hamburger menu items
|
|
65
|
+
updateHamburgerActiveState(id);
|
|
17
66
|
updateUrlParams({ tab: id });
|
|
18
67
|
publish("tab:change", id);
|
|
19
68
|
};
|
|
20
|
-
|
|
69
|
+
setActivePanelFn = setActivePanel;
|
|
70
|
+
// Separate primary tabs from menu tabs
|
|
71
|
+
const primaryTabs = tabs.filter((t) => !t.hidden && !t.menuTab);
|
|
72
|
+
const menuTabs = tabs.filter((t) => !t.hidden && t.menuTab);
|
|
73
|
+
// Render primary tabs
|
|
74
|
+
primaryTabs.forEach(tab => {
|
|
21
75
|
const btn = document.createElement("button");
|
|
22
76
|
btn.className = "tab";
|
|
23
77
|
btn.dataset.target = tab.id;
|
|
24
|
-
btn.
|
|
78
|
+
btn.innerHTML = `
|
|
79
|
+
<span class="tab-label">${escapeHtml(tab.label)}</span>
|
|
80
|
+
<span class="badge hidden" id="tab-badge-${tab.id}"></span>
|
|
81
|
+
`;
|
|
25
82
|
btn.addEventListener("click", () => setActivePanel(tab.id));
|
|
26
83
|
container.appendChild(btn);
|
|
27
84
|
});
|
|
85
|
+
// Create hamburger menu if there are menu tabs or actions
|
|
86
|
+
if (menuTabs.length > 0 || hamburgerActions.length > 0) {
|
|
87
|
+
const wrapper = document.createElement("div");
|
|
88
|
+
wrapper.className = "hamburger-wrapper";
|
|
89
|
+
// Hamburger button
|
|
90
|
+
const btn = document.createElement("button");
|
|
91
|
+
btn.className = "hamburger-btn";
|
|
92
|
+
btn.setAttribute("aria-label", "More options");
|
|
93
|
+
btn.setAttribute("aria-expanded", "false");
|
|
94
|
+
btn.innerHTML = `
|
|
95
|
+
<span class="hamburger-icon">
|
|
96
|
+
<span></span>
|
|
97
|
+
<span></span>
|
|
98
|
+
<span></span>
|
|
99
|
+
</span>
|
|
100
|
+
`;
|
|
101
|
+
hamburgerBtnEl = btn;
|
|
102
|
+
// Hamburger menu dropdown
|
|
103
|
+
const menu = document.createElement("div");
|
|
104
|
+
menu.className = "hamburger-menu";
|
|
105
|
+
menu.setAttribute("role", "menu");
|
|
106
|
+
hamburgerMenuEl = menu;
|
|
107
|
+
// Add menu tab items
|
|
108
|
+
menuTabs.forEach((tab) => {
|
|
109
|
+
const item = document.createElement("button");
|
|
110
|
+
item.className = "hamburger-item";
|
|
111
|
+
item.dataset.target = tab.id;
|
|
112
|
+
item.setAttribute("role", "menuitem");
|
|
113
|
+
const iconHtml = tab.icon ? `<span class="hamburger-item-icon">${tab.icon}</span>` : "";
|
|
114
|
+
item.innerHTML = `${iconHtml}<span>${escapeHtml(tab.label)}</span>`;
|
|
115
|
+
item.addEventListener("click", () => {
|
|
116
|
+
setActivePanel(tab.id);
|
|
117
|
+
closeHamburgerMenu();
|
|
118
|
+
});
|
|
119
|
+
menu.appendChild(item);
|
|
120
|
+
});
|
|
121
|
+
// Add divider if there are both tabs and actions
|
|
122
|
+
if (menuTabs.length > 0 && hamburgerActions.length > 0) {
|
|
123
|
+
const divider = document.createElement("div");
|
|
124
|
+
divider.className = "hamburger-divider";
|
|
125
|
+
menu.appendChild(divider);
|
|
126
|
+
}
|
|
127
|
+
// Add action items (like Settings)
|
|
128
|
+
hamburgerActions.forEach((action) => {
|
|
129
|
+
const item = document.createElement("button");
|
|
130
|
+
item.className = "hamburger-item";
|
|
131
|
+
item.dataset.action = action.id;
|
|
132
|
+
item.setAttribute("role", "menuitem");
|
|
133
|
+
const iconHtml = action.icon ? `<span class="hamburger-item-icon">${action.icon}</span>` : "";
|
|
134
|
+
item.innerHTML = `${iconHtml}<span>${escapeHtml(action.label)}</span>`;
|
|
135
|
+
item.addEventListener("click", () => {
|
|
136
|
+
action.onClick();
|
|
137
|
+
closeHamburgerMenu();
|
|
138
|
+
});
|
|
139
|
+
menu.appendChild(item);
|
|
140
|
+
});
|
|
141
|
+
// Mobile backdrop - appended to body for proper z-index stacking
|
|
142
|
+
const backdrop = document.createElement("div");
|
|
143
|
+
backdrop.className = "hamburger-backdrop";
|
|
144
|
+
backdrop.addEventListener("click", closeHamburgerMenu);
|
|
145
|
+
hamburgerBackdropEl = backdrop;
|
|
146
|
+
document.body.appendChild(backdrop);
|
|
147
|
+
// Append menu to body for mobile z-index stacking (above backdrop)
|
|
148
|
+
// On mobile, the nav-bar has z-index:100 which creates a stacking context
|
|
149
|
+
// that would trap the menu below the backdrop (z-index:1999)
|
|
150
|
+
document.body.appendChild(menu);
|
|
151
|
+
// Toggle menu on button click
|
|
152
|
+
const toggleHandler = (e) => {
|
|
153
|
+
e.stopPropagation();
|
|
154
|
+
// Prevent ghost clicks on touch devices
|
|
155
|
+
if (e.type === "touchend") {
|
|
156
|
+
e.preventDefault();
|
|
157
|
+
}
|
|
158
|
+
toggleHamburgerMenu();
|
|
159
|
+
btn.setAttribute("aria-expanded", String(hamburgerMenuOpen));
|
|
160
|
+
};
|
|
161
|
+
btn.addEventListener("click", toggleHandler);
|
|
162
|
+
btn.addEventListener("touchend", toggleHandler);
|
|
163
|
+
// Close menu on outside click (check both wrapper and menu since menu is in body)
|
|
164
|
+
document.addEventListener("click", (e) => {
|
|
165
|
+
if (hamburgerMenuOpen && !wrapper.contains(e.target) && !menu.contains(e.target)) {
|
|
166
|
+
closeHamburgerMenu();
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
// Close menu on Escape
|
|
170
|
+
document.addEventListener("keydown", (e) => {
|
|
171
|
+
if (e.key === "Escape" && hamburgerMenuOpen) {
|
|
172
|
+
closeHamburgerMenu();
|
|
173
|
+
hamburgerBtnEl?.focus();
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
wrapper.appendChild(btn);
|
|
177
|
+
// Insert hamburger after tabs or at the end of nav bar
|
|
178
|
+
const navActions = navBar?.querySelector(".nav-actions");
|
|
179
|
+
if (navActions) {
|
|
180
|
+
navBar?.insertBefore(wrapper, navActions);
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
navBar?.appendChild(wrapper);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
28
186
|
const params = getUrlParams();
|
|
29
187
|
const requested = params.get("tab");
|
|
30
|
-
const
|
|
188
|
+
const allVisibleTabs = tabs.filter((t) => !t.hidden);
|
|
189
|
+
const initialTab = allVisibleTabs.some((t) => t.id === requested)
|
|
31
190
|
? requested
|
|
32
|
-
:
|
|
191
|
+
: allVisibleTabs.some((t) => t.id === defaultTab)
|
|
33
192
|
? defaultTab
|
|
34
|
-
:
|
|
193
|
+
: allVisibleTabs[0]?.id;
|
|
35
194
|
if (initialTab) {
|
|
36
195
|
setActivePanel(initialTab);
|
|
37
196
|
}
|
|
38
|
-
else if (
|
|
39
|
-
setActivePanel(
|
|
197
|
+
else if (allVisibleTabs.length > 0) {
|
|
198
|
+
setActivePanel(allVisibleTabs[0].id);
|
|
199
|
+
}
|
|
200
|
+
if (pendingActivate && allVisibleTabs.some((t) => t.id === pendingActivate)) {
|
|
201
|
+
const id = pendingActivate;
|
|
202
|
+
pendingActivate = null;
|
|
203
|
+
setActivePanel(id);
|
|
40
204
|
}
|
|
41
205
|
}
|
|
@@ -1,12 +1,44 @@
|
|
|
1
|
+
// GENERATED FILE - do not edit directly. Source: static_src/
|
|
1
2
|
import { TerminalManager } from "./terminalManager.js";
|
|
3
|
+
import { refreshAgentControls } from "./agentControls.js";
|
|
4
|
+
import { subscribe } from "./bus.js";
|
|
5
|
+
import { isRepoHealthy } from "./health.js";
|
|
2
6
|
let terminalManager = null;
|
|
7
|
+
let terminalHealthRefreshInitialized = false;
|
|
3
8
|
export function getTerminalManager() {
|
|
4
9
|
return terminalManager;
|
|
5
10
|
}
|
|
6
11
|
export function initTerminal() {
|
|
7
12
|
if (terminalManager) {
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
14
|
+
if (typeof terminalManager.fit === "function") {
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
16
|
+
terminalManager.fit();
|
|
17
|
+
}
|
|
8
18
|
return;
|
|
9
19
|
}
|
|
10
20
|
terminalManager = new TerminalManager();
|
|
11
21
|
terminalManager.init();
|
|
22
|
+
initTerminalHealthRefresh();
|
|
23
|
+
// Ensure terminal is resized to fit container after initialization
|
|
24
|
+
if (terminalManager) {
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
26
|
+
if (typeof terminalManager.fit === "function") {
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
28
|
+
terminalManager.fit();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function initTerminalHealthRefresh() {
|
|
33
|
+
if (terminalHealthRefreshInitialized)
|
|
34
|
+
return;
|
|
35
|
+
terminalHealthRefreshInitialized = true;
|
|
36
|
+
subscribe("repo:health", (payload) => {
|
|
37
|
+
const status = payload?.status || "";
|
|
38
|
+
if (status !== "ok" && status !== "degraded")
|
|
39
|
+
return;
|
|
40
|
+
if (!isRepoHealthy())
|
|
41
|
+
return;
|
|
42
|
+
void refreshAgentControls({ reason: "background" });
|
|
43
|
+
});
|
|
12
44
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// GENERATED FILE - do not edit directly. Source: static_src/
|
|
1
2
|
import { api, flash, buildWsUrl, getAuthToken, isMobileViewport } from "./utils.js";
|
|
2
3
|
import { getSelectedAgent, getSelectedModel, getSelectedReasoning, initAgentControls, } from "./agentControls.js";
|
|
3
4
|
function base64UrlEncode(value) {
|
|
@@ -44,21 +45,7 @@ const XTERM_COLOR_MODE_PALETTE_16 = 0x01000000;
|
|
|
44
45
|
const XTERM_COLOR_MODE_PALETTE_256 = 0x02000000;
|
|
45
46
|
const XTERM_COLOR_MODE_RGB = 0x03000000;
|
|
46
47
|
const CAR_CONTEXT_HOOK_ID = "car_context";
|
|
47
|
-
const
|
|
48
|
-
const CAR_CONTEXT_KEYWORDS = [
|
|
49
|
-
"car",
|
|
50
|
-
"codex",
|
|
51
|
-
"todo",
|
|
52
|
-
"progress",
|
|
53
|
-
"opinions",
|
|
54
|
-
"spec",
|
|
55
|
-
"summary",
|
|
56
|
-
"autorunner",
|
|
57
|
-
"work docs",
|
|
58
|
-
];
|
|
59
|
-
const GITHUB_LINK_RE = /https?:\/\/github\.com\/[^/\s]+\/[^/\s]+\/(?:issues|pull)\/\d+(?:[/?#][^\s]*)?/i;
|
|
60
|
-
const CAR_CONTEXT_HINT_TEXT = "Context: read .codex-autorunner/ABOUT_CAR.md for repo-specific rules.";
|
|
61
|
-
const CAR_CONTEXT_HINT = wrapInjectedContext(CAR_CONTEXT_HINT_TEXT);
|
|
48
|
+
const CAR_CONTEXT_HINT = wrapInjectedContext(CONSTANTS.PROMPTS.CAR_CONTEXT_HINT);
|
|
62
49
|
const VOICE_TRANSCRIPT_DISCLAIMER_TEXT = CONSTANTS.PROMPTS?.VOICE_TRANSCRIPT_DISCLAIMER ||
|
|
63
50
|
"Note: transcribed from user voice. If confusing or possibly inaccurate and you cannot infer the intention please clarify before proceeding.";
|
|
64
51
|
const INJECTED_CONTEXT_TAG_RE = /<injected context>/i;
|
|
@@ -360,7 +347,6 @@ export class TerminalManager {
|
|
|
360
347
|
this.lastAltScrollbackSize = 0;
|
|
361
348
|
this.transcriptResetForConnect = false;
|
|
362
349
|
this._registerTextInputHook(this._buildCarContextHook());
|
|
363
|
-
this._registerTextInputHook(this._buildGithubContextHook());
|
|
364
350
|
// Bind methods that are used as callbacks
|
|
365
351
|
this._handleResize = this._handleResize.bind(this);
|
|
366
352
|
this._handleVoiceHotkeyDown = this._handleVoiceHotkeyDown.bind(this);
|
|
@@ -444,6 +430,20 @@ export class TerminalManager {
|
|
|
444
430
|
this.connect({ mode: "attach" });
|
|
445
431
|
}
|
|
446
432
|
}
|
|
433
|
+
/**
|
|
434
|
+
* Force resize terminal to fit container
|
|
435
|
+
*/
|
|
436
|
+
fit() {
|
|
437
|
+
if (this.fitAddon && this.term) {
|
|
438
|
+
try {
|
|
439
|
+
this.fitAddon.fit();
|
|
440
|
+
this._handleResize(); // Send resize to server
|
|
441
|
+
}
|
|
442
|
+
catch (e) {
|
|
443
|
+
// ignore
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
447
|
/**
|
|
448
448
|
* Set terminal status message
|
|
449
449
|
*/
|
|
@@ -621,12 +621,12 @@ export class TerminalManager {
|
|
|
621
621
|
if (manager._hasTextInputHookFired(CAR_CONTEXT_HOOK_ID))
|
|
622
622
|
return null;
|
|
623
623
|
const lowered = text.toLowerCase();
|
|
624
|
-
const hit =
|
|
624
|
+
const hit = CONSTANTS.KEYWORDS.CAR_CONTEXT.some((kw) => lowered.includes(kw));
|
|
625
625
|
if (!hit)
|
|
626
626
|
return null;
|
|
627
627
|
if (lowered.includes("about_car.md"))
|
|
628
628
|
return null;
|
|
629
|
-
if (text.includes(
|
|
629
|
+
if (text.includes(CONSTANTS.PROMPTS.CAR_CONTEXT_HINT) ||
|
|
630
630
|
text.includes(CAR_CONTEXT_HINT)) {
|
|
631
631
|
return null;
|
|
632
632
|
}
|
|
@@ -637,43 +637,8 @@ export class TerminalManager {
|
|
|
637
637
|
},
|
|
638
638
|
};
|
|
639
639
|
}
|
|
640
|
-
_buildGithubContextHook() {
|
|
641
|
-
return {
|
|
642
|
-
id: GITHUB_CONTEXT_HOOK_ID,
|
|
643
|
-
apply: async ({ text }) => {
|
|
644
|
-
if (!text || !text.trim())
|
|
645
|
-
return null;
|
|
646
|
-
const match = text.match(GITHUB_LINK_RE);
|
|
647
|
-
if (!match)
|
|
648
|
-
return null;
|
|
649
|
-
try {
|
|
650
|
-
const res = await api("/api/github/context", {
|
|
651
|
-
method: "POST",
|
|
652
|
-
body: { url: match[0] },
|
|
653
|
-
});
|
|
654
|
-
if (!res || typeof res !== "object")
|
|
655
|
-
return null;
|
|
656
|
-
const injection = wrapInjectedContextIfNeeded(res.hint);
|
|
657
|
-
const separator = text.endsWith("\n") ? "\n" : "\n\n";
|
|
658
|
-
return { text: `${text}${separator}${injection}` };
|
|
659
|
-
}
|
|
660
|
-
catch (_err) {
|
|
661
|
-
return null;
|
|
662
|
-
}
|
|
663
|
-
},
|
|
664
|
-
};
|
|
665
|
-
}
|
|
666
640
|
async _loadTerminalIdleTimeout() {
|
|
667
|
-
|
|
668
|
-
const data = await api(CONSTANTS.API.STATE_ENDPOINT);
|
|
669
|
-
if (data &&
|
|
670
|
-
typeof data === "object" && data !== null && "terminal_idle_timeout_seconds" in data) {
|
|
671
|
-
this.terminalIdleTimeoutSeconds = data.terminal_idle_timeout_seconds;
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
catch (_err) {
|
|
675
|
-
// ignore
|
|
676
|
-
}
|
|
641
|
+
// State endpoint removed - terminal idle timeout no longer loaded from /api/state
|
|
677
642
|
}
|
|
678
643
|
_getSessionStorageKey() {
|
|
679
644
|
return `${SESSION_STORAGE_PREFIX}${this._getRepoStorageKey()}`;
|
|
@@ -1880,7 +1845,8 @@ export class TerminalManager {
|
|
|
1880
1845
|
* Ensure xterm terminal is initialized
|
|
1881
1846
|
*/
|
|
1882
1847
|
_ensureTerminal() {
|
|
1883
|
-
|
|
1848
|
+
const win = window;
|
|
1849
|
+
if (!win.Terminal || !win.FitAddon) {
|
|
1884
1850
|
this._setStatus("xterm assets missing; reload or check /static/vendor");
|
|
1885
1851
|
flash("xterm assets missing; reload the page", "error");
|
|
1886
1852
|
return false;
|
|
@@ -1899,7 +1865,7 @@ export class TerminalManager {
|
|
|
1899
1865
|
const container = document.getElementById("terminal-container");
|
|
1900
1866
|
if (!container)
|
|
1901
1867
|
return false;
|
|
1902
|
-
this.term = new
|
|
1868
|
+
this.term = new win.Terminal({
|
|
1903
1869
|
convertEol: true,
|
|
1904
1870
|
fontFamily: '"JetBrains Mono", "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace',
|
|
1905
1871
|
fontSize: this._getFontSize(),
|
|
@@ -1911,7 +1877,7 @@ export class TerminalManager {
|
|
|
1911
1877
|
scrollback: this.transcriptMaxLines,
|
|
1912
1878
|
theme: CONSTANTS.THEME.XTERM,
|
|
1913
1879
|
});
|
|
1914
|
-
this.fitAddon = new
|
|
1880
|
+
this.fitAddon = new win.FitAddon.FitAddon();
|
|
1915
1881
|
this.term.loadAddon(this.fitAddon);
|
|
1916
1882
|
this.term.open(container);
|
|
1917
1883
|
this.term.write('Press "New" or "Resume" to launch Codex TUI...\r\n');
|
|
@@ -1920,6 +1886,13 @@ export class TerminalManager {
|
|
|
1920
1886
|
this.term.onScroll(() => this._updateJumpBottomVisibility());
|
|
1921
1887
|
this.term.onRender(() => this._scheduleMobileViewRender());
|
|
1922
1888
|
this._updateJumpBottomVisibility();
|
|
1889
|
+
// Initial fit
|
|
1890
|
+
try {
|
|
1891
|
+
this.fitAddon.fit();
|
|
1892
|
+
}
|
|
1893
|
+
catch (e) {
|
|
1894
|
+
// ignore fit errors when not visible
|
|
1895
|
+
}
|
|
1923
1896
|
if (!this.inputDisposable) {
|
|
1924
1897
|
this.inputDisposable = this.term.onData((data) => {
|
|
1925
1898
|
if (!this.socket || this.socket.readyState !== WebSocket.OPEN)
|
|
@@ -2004,7 +1977,8 @@ export class TerminalManager {
|
|
|
2004
1977
|
if (!viewport)
|
|
2005
1978
|
return;
|
|
2006
1979
|
const getLineHeight = () => {
|
|
2007
|
-
const
|
|
1980
|
+
const core = this.term?._core;
|
|
1981
|
+
const dims = core?._renderService?.dimensions;
|
|
2008
1982
|
if (dims && Number.isFinite(dims.actualCellHeight) && dims.actualCellHeight > 0) {
|
|
2009
1983
|
return dims.actualCellHeight;
|
|
2010
1984
|
}
|
|
@@ -3100,7 +3074,8 @@ export class TerminalManager {
|
|
|
3100
3074
|
method: "POST",
|
|
3101
3075
|
body: formData,
|
|
3102
3076
|
});
|
|
3103
|
-
const
|
|
3077
|
+
const p = response;
|
|
3078
|
+
const imagePath = p.path || p.abs_path;
|
|
3104
3079
|
if (!imagePath) {
|
|
3105
3080
|
throw new Error("Upload returned no path");
|
|
3106
3081
|
}
|