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
|
@@ -23,10 +23,25 @@
|
|
|
23
23
|
</div>
|
|
24
24
|
<div class="hub-hero-actions">
|
|
25
25
|
<button class="primary sm" id="hub-new-repo">+ New</button>
|
|
26
|
-
<
|
|
27
|
-
|
|
26
|
+
<div class="notifications-bell" data-notifications-root="hub">
|
|
27
|
+
<button class="ghost sm icon-btn notifications-bell-btn" data-notifications-trigger title="Notifications"
|
|
28
|
+
aria-label="Notifications">
|
|
29
|
+
<span aria-hidden="true">🔔</span>
|
|
30
|
+
<span class="notifications-bell-badge hidden" data-notifications-badge></span>
|
|
31
|
+
</button>
|
|
32
|
+
<div class="notifications-dropdown hidden" data-notifications-dropdown role="menu"
|
|
33
|
+
aria-label="Pending dispatches"></div>
|
|
34
|
+
</div>
|
|
28
35
|
<button class="ghost sm icon-btn" id="hub-settings" title="Settings">⚙</button>
|
|
29
36
|
</div>
|
|
37
|
+
<div class="hub-mode-toggle" role="tablist" aria-label="Hub mode">
|
|
38
|
+
<button class="hub-mode-btn active" id="hub-mode-manual" data-hub-mode="manual" role="tab"
|
|
39
|
+
aria-selected="true">Manual</button>
|
|
40
|
+
<button class="hub-mode-btn" id="hub-mode-pma" data-hub-mode="pma" role="tab" aria-selected="false">
|
|
41
|
+
<span class="hub-mode-long">PM Agent</span>
|
|
42
|
+
<span class="hub-mode-short">PMA</span>
|
|
43
|
+
</button>
|
|
44
|
+
</div>
|
|
30
45
|
</header>
|
|
31
46
|
<section class="hub-stats">
|
|
32
47
|
<div class="hub-stat">
|
|
@@ -42,15 +57,6 @@
|
|
|
42
57
|
<p class="muted small">missing</p>
|
|
43
58
|
</div>
|
|
44
59
|
</section>
|
|
45
|
-
<section class="hub-inbox">
|
|
46
|
-
<div class="hub-panel-header">
|
|
47
|
-
<span class="label">Inbox</span>
|
|
48
|
-
<div class="hub-panel-actions">
|
|
49
|
-
<button class="ghost sm" id="hub-inbox-refresh">Refresh</button>
|
|
50
|
-
</div>
|
|
51
|
-
</div>
|
|
52
|
-
<div class="hub-inbox-list" id="hub-inbox-list">Loading…</div>
|
|
53
|
-
</section>
|
|
54
60
|
<section class="hub-usage-chart">
|
|
55
61
|
<div class="hub-usage-chart-header">
|
|
56
62
|
<span class="label">Usage Trend</span>
|
|
@@ -83,6 +89,136 @@
|
|
|
83
89
|
</div>
|
|
84
90
|
</section>
|
|
85
91
|
</div>
|
|
92
|
+
<div class="hub-shell hidden" id="pma-shell">
|
|
93
|
+
<header class="hub-hero pma-hero">
|
|
94
|
+
<div class="hub-hero-text pma-hero-text">
|
|
95
|
+
<h1>Project Manager</h1>
|
|
96
|
+
<span class="pill pill-small pill-idle" id="pma-last-scan">–</span>
|
|
97
|
+
<span class="hub-version" id="pma-version">v–</span>
|
|
98
|
+
</div>
|
|
99
|
+
<div class="hub-hero-actions pma-hero-actions">
|
|
100
|
+
<div class="notifications-bell" data-notifications-root="pma">
|
|
101
|
+
<button class="ghost sm icon-btn notifications-bell-btn" data-notifications-trigger title="Notifications"
|
|
102
|
+
aria-label="Notifications">
|
|
103
|
+
<span aria-hidden="true">🔔</span>
|
|
104
|
+
<span class="notifications-bell-badge hidden" data-notifications-badge></span>
|
|
105
|
+
</button>
|
|
106
|
+
<div class="notifications-dropdown hidden" data-notifications-dropdown role="menu"
|
|
107
|
+
aria-label="Pending dispatches"></div>
|
|
108
|
+
</div>
|
|
109
|
+
<button class="ghost sm icon-btn" id="pma-settings" title="Settings">⚙</button>
|
|
110
|
+
</div>
|
|
111
|
+
<div class="hub-mode-toggle" role="tablist" aria-label="Hub mode">
|
|
112
|
+
<button class="hub-mode-btn" id="pma-mode-manual" data-hub-mode="manual" role="tab"
|
|
113
|
+
aria-selected="false">Manual</button>
|
|
114
|
+
<button class="hub-mode-btn active" id="pma-mode-pma" data-hub-mode="pma" role="tab" aria-selected="true">
|
|
115
|
+
<span class="hub-mode-long">PM Agent</span>
|
|
116
|
+
<span class="hub-mode-short">PMA</span>
|
|
117
|
+
</button>
|
|
118
|
+
</div>
|
|
119
|
+
</header>
|
|
120
|
+
<section class="pma-top-bar">
|
|
121
|
+
<div class="pma-chat-controls-row">
|
|
122
|
+
<div class="pma-chat-agent-controls">
|
|
123
|
+
<select id="pma-chat-agent-select" title="Agent"></select>
|
|
124
|
+
<select id="pma-chat-model-select" title="Model"></select>
|
|
125
|
+
<select id="pma-chat-reasoning-select" title="Reasoning"></select>
|
|
126
|
+
</div>
|
|
127
|
+
<div class="pma-chat-actions">
|
|
128
|
+
<button class="ghost sm hidden" id="pma-chat-cancel" title="Cancel">✕</button>
|
|
129
|
+
<button class="pma-new-thread-btn" id="pma-chat-new-thread" title="Start a new chat thread">New
|
|
130
|
+
thread</button>
|
|
131
|
+
<span class="pma-status-pill" id="pma-chat-status">idle</span>
|
|
132
|
+
</div>
|
|
133
|
+
</div>
|
|
134
|
+
<div class="pma-thread-info hidden" id="pma-thread-info">
|
|
135
|
+
<div class="pma-thread-info-header">
|
|
136
|
+
<span class="pma-thread-info-label">Thread</span>
|
|
137
|
+
<span class="pill pill-small pill-idle" id="pma-thread-info-status">idle</span>
|
|
138
|
+
</div>
|
|
139
|
+
<div class="pma-thread-info-details">
|
|
140
|
+
<div class="pma-thread-info-row">
|
|
141
|
+
<span class="pma-thread-info-key muted">Agent</span>
|
|
142
|
+
<span class="pma-thread-info-value" id="pma-thread-info-agent">–</span>
|
|
143
|
+
</div>
|
|
144
|
+
<div class="pma-thread-info-row">
|
|
145
|
+
<span class="pma-thread-info-key muted">Thread ID</span>
|
|
146
|
+
<span class="pma-thread-info-value" id="pma-thread-info-thread-id" title="Click to copy">–</span>
|
|
147
|
+
</div>
|
|
148
|
+
<div class="pma-thread-info-row">
|
|
149
|
+
<span class="pma-thread-info-key muted">Turn ID</span>
|
|
150
|
+
<span class="pma-thread-info-value" id="pma-thread-info-turn-id" title="Click to copy">–</span>
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
<div class="pma-repo-actions" id="pma-repo-actions">
|
|
155
|
+
<button class="ghost sm" id="pma-scan-repos-btn">Scan repos</button>
|
|
156
|
+
</div>
|
|
157
|
+
</section>
|
|
158
|
+
<section class="pma-chat-section">
|
|
159
|
+
<div class="pma-chat-main">
|
|
160
|
+
<div class="pma-chat-stream" id="pma-chat-stream">
|
|
161
|
+
<div class="pma-chat-error hidden" id="pma-chat-error"></div>
|
|
162
|
+
<div class="pma-history-header" id="pma-chat-history-header">
|
|
163
|
+
<span class="pma-history-label">History</span>
|
|
164
|
+
</div>
|
|
165
|
+
<div class="pma-chat-messages" id="pma-chat-messages"></div>
|
|
166
|
+
<div class="pma-chat-events hidden" id="pma-chat-events">
|
|
167
|
+
<div class="pma-events-header">
|
|
168
|
+
<span class="pma-events-label">Agent</span>
|
|
169
|
+
<span class="pma-events-count" id="pma-chat-events-count">0</span>
|
|
170
|
+
<button class="ghost sm hidden" id="pma-chat-events-toggle">more</button>
|
|
171
|
+
</div>
|
|
172
|
+
<div class="pma-chat-events-list" id="pma-chat-events-list"></div>
|
|
173
|
+
</div>
|
|
174
|
+
</div>
|
|
175
|
+
<div class="pma-chat-compose">
|
|
176
|
+
<div class="pma-attachments-area" id="pma-attachments-area">
|
|
177
|
+
<div class="pma-files-row">
|
|
178
|
+
<span class="pma-files-label">In</span>
|
|
179
|
+
<div class="pma-file-list filebox-list" id="pma-inbox-files"></div>
|
|
180
|
+
</div>
|
|
181
|
+
<div class="pma-files-row">
|
|
182
|
+
<span class="pma-files-label">Out</span>
|
|
183
|
+
<div class="pma-file-list filebox-list" id="pma-outbox-files"></div>
|
|
184
|
+
<button class="pma-icon-btn-small" id="pma-outbox-refresh" title="Refresh files">↻</button>
|
|
185
|
+
</div>
|
|
186
|
+
</div>
|
|
187
|
+
<div class="pma-chat-input-row">
|
|
188
|
+
<textarea id="pma-chat-input" class="pma-chat-input" enterkeyhint="enter"
|
|
189
|
+
placeholder="Ask PMA to help coordinate work..." rows="1" spellcheck="false"></textarea>
|
|
190
|
+
<input type="file" id="pma-chat-upload-input" multiple hidden />
|
|
191
|
+
<button class="ghost sm icon-btn pma-upload-btn" id="pma-chat-upload-btn" title="Upload file">📎</button>
|
|
192
|
+
<button class="pma-send-btn" id="pma-chat-send" title="Send (Cmd+Enter)">↑</button>
|
|
193
|
+
</div>
|
|
194
|
+
<div class="pma-chat-hint">
|
|
195
|
+
<span class="muted small">⌘↵ send · ↵ newline</span>
|
|
196
|
+
</div>
|
|
197
|
+
</div>
|
|
198
|
+
</div>
|
|
199
|
+
</section>
|
|
200
|
+
<section class="pma-docs-section hidden" id="pma-docs-section">
|
|
201
|
+
<div class="pma-docs-header">
|
|
202
|
+
<h2>PMA Docs</h2>
|
|
203
|
+
<div class="pma-docs-tabs">
|
|
204
|
+
<button class="pma-docs-tab active" data-doc="AGENTS.md">AGENTS</button>
|
|
205
|
+
<button class="pma-docs-tab" data-doc="active_context.md">Active Context</button>
|
|
206
|
+
<button class="pma-docs-tab" data-doc="context_log.md">Context Log</button>
|
|
207
|
+
</div>
|
|
208
|
+
</div>
|
|
209
|
+
<div class="pma-docs-content">
|
|
210
|
+
<div class="pma-docs-meta" id="pma-docs-meta"></div>
|
|
211
|
+
<div class="pma-docs-editor-wrapper">
|
|
212
|
+
<textarea id="pma-docs-editor" class="pma-docs-editor" spellcheck="false"></textarea>
|
|
213
|
+
</div>
|
|
214
|
+
<div class="pma-docs-actions">
|
|
215
|
+
<button class="ghost sm" id="pma-docs-reset" title="Reset to default">Reset</button>
|
|
216
|
+
<button class="ghost sm" id="pma-docs-snapshot" title="Snapshot active context to log">Snapshot to log</button>
|
|
217
|
+
<button class="primary sm" id="pma-docs-save">Save</button>
|
|
218
|
+
</div>
|
|
219
|
+
</div>
|
|
220
|
+
</section>
|
|
221
|
+
</div>
|
|
86
222
|
<div class="app-shell" id="repo-shell">
|
|
87
223
|
<nav class="nav-bar">
|
|
88
224
|
<span class="nav-brand">CAR</span>
|
|
@@ -262,12 +398,33 @@
|
|
|
262
398
|
</div>
|
|
263
399
|
</div>
|
|
264
400
|
</div>
|
|
265
|
-
<div class="messages-
|
|
266
|
-
<
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
401
|
+
<div class="messages-compose">
|
|
402
|
+
<div class="messages-attachments">
|
|
403
|
+
<input type="file" id="messages-filebox-upload" multiple hidden />
|
|
404
|
+
<div class="chat-files-row">
|
|
405
|
+
<span class="chat-files-label">In</span>
|
|
406
|
+
<div class="filebox-list" id="messages-filebox-inbox"></div>
|
|
407
|
+
<div class="chat-filebox-actions">
|
|
408
|
+
<button class="ghost sm icon-btn chat-icon-btn" id="messages-filebox-upload-btn"
|
|
409
|
+
title="Upload to inbox">⭱</button>
|
|
410
|
+
<button class="ghost sm icon-btn chat-icon-btn" id="messages-filebox-refresh"
|
|
411
|
+
title="Refresh FileBox">↻</button>
|
|
412
|
+
</div>
|
|
413
|
+
</div>
|
|
414
|
+
<div class="chat-files-row">
|
|
415
|
+
<span class="chat-files-label">Out</span>
|
|
416
|
+
<div class="filebox-list" id="messages-filebox-outbox"></div>
|
|
417
|
+
</div>
|
|
418
|
+
</div>
|
|
419
|
+
<div class="messages-input-row">
|
|
420
|
+
<textarea class="messages-reply-body" id="messages-reply-body" enterkeyhint="enter"
|
|
421
|
+
placeholder="Write a reply…" rows="2" spellcheck="false"></textarea>
|
|
422
|
+
<div class="messages-input-actions">
|
|
423
|
+
<input type="file" id="messages-reply-files" multiple hidden />
|
|
424
|
+
<button class="ghost sm icon-btn messages-attach-btn" id="messages-reply-attach"
|
|
425
|
+
title="Attach files">📎</button>
|
|
426
|
+
<span class="muted small messages-attach-summary hidden" id="messages-reply-attach-summary">No
|
|
427
|
+
files</span>
|
|
271
428
|
<button class="primary sm" id="messages-reply-send">Send</button>
|
|
272
429
|
</div>
|
|
273
430
|
</div>
|
|
@@ -358,6 +515,18 @@
|
|
|
358
515
|
</button>
|
|
359
516
|
<div class="workspace-mobile-actions">
|
|
360
517
|
<span class="muted small" id="workspace-status-mobile"></span>
|
|
518
|
+
<div class="workspace-mobile-menu">
|
|
519
|
+
<button class="ghost sm icon-btn" id="workspace-mobile-menu-toggle"
|
|
520
|
+
title="Workspace actions">⋯</button>
|
|
521
|
+
<div class="workspace-mobile-dropdown hidden" id="workspace-mobile-dropdown">
|
|
522
|
+
<button class="workspace-mobile-item" id="workspace-mobile-upload">Upload files</button>
|
|
523
|
+
<button class="workspace-mobile-item" id="workspace-mobile-new-folder">New folder</button>
|
|
524
|
+
<button class="workspace-mobile-item" id="workspace-mobile-new-file">New file</button>
|
|
525
|
+
<button class="workspace-mobile-item" id="workspace-mobile-download">Download ZIP</button>
|
|
526
|
+
<button class="workspace-mobile-item hidden" id="workspace-mobile-generate">Generate
|
|
527
|
+
tickets</button>
|
|
528
|
+
</div>
|
|
529
|
+
</div>
|
|
361
530
|
<button class="ghost sm" id="workspace-reload-mobile" title="Reload">↻</button>
|
|
362
531
|
<button class="primary sm" id="workspace-save-mobile">Save</button>
|
|
363
532
|
</div>
|
|
@@ -434,13 +603,21 @@
|
|
|
434
603
|
<button class="ghost sm icon-btn" id="ticket-overflow-toggle" title="More actions">⋯</button>
|
|
435
604
|
<div class="ticket-overflow-dropdown hidden" id="ticket-overflow-dropdown">
|
|
436
605
|
<button class="ticket-overflow-item" id="ticket-overflow-new">+ New Ticket</button>
|
|
606
|
+
<button class="ticket-overflow-item hidden" id="ticket-overflow-template">From Template</button>
|
|
437
607
|
<button class="ticket-overflow-item" id="ticket-overflow-restart" style="display:none;">Restart</button>
|
|
438
608
|
<button class="ticket-overflow-item" id="ticket-overflow-archive" style="display:none;">Archive
|
|
439
609
|
Flow</button>
|
|
440
610
|
</div>
|
|
441
611
|
</div>
|
|
442
|
-
|
|
443
|
-
|
|
612
|
+
<!-- Split button: New Ticket + Template dropdown -->
|
|
613
|
+
<div class="ticket-new-split ticket-desktop-only">
|
|
614
|
+
<button class="ghost sm" id="ticket-new-btn" title="Create new ticket">+ New Ticket</button>
|
|
615
|
+
<button class="ghost sm icon-btn ticket-new-dropdown-toggle hidden" id="ticket-new-dropdown-toggle"
|
|
616
|
+
title="Create from template">▾</button>
|
|
617
|
+
<div class="ticket-new-dropdown hidden" id="ticket-new-dropdown">
|
|
618
|
+
<button class="ticket-new-dropdown-item" id="ticket-new-from-template">From Template</button>
|
|
619
|
+
</div>
|
|
620
|
+
</div>
|
|
444
621
|
</div>
|
|
445
622
|
<div class="ticket-flow-meta" id="ticket-flow-meta">
|
|
446
623
|
<div class="ticket-meta-details" id="ticket-meta-details">
|
|
@@ -547,10 +724,10 @@
|
|
|
547
724
|
<input class="ticket-fm-input" id="ticket-fm-title" placeholder="Title (optional)" spellcheck="false"
|
|
548
725
|
type="text">
|
|
549
726
|
<div class="ticket-header-actions">
|
|
550
|
-
<button class="ghost sm icon-btn ticket-nav-btn" id="ticket-nav-prev" title="Previous ticket (
|
|
551
|
-
aria-label="Previous ticket" aria-keyshortcuts="
|
|
552
|
-
<button class="ghost sm icon-btn ticket-nav-btn" id="ticket-nav-next" title="Next ticket (
|
|
553
|
-
aria-label="Next ticket" aria-keyshortcuts="
|
|
727
|
+
<button class="ghost sm icon-btn ticket-nav-btn" id="ticket-nav-prev" title="Previous ticket (Alt+←)"
|
|
728
|
+
aria-label="Previous ticket" aria-keyshortcuts="Alt+ArrowLeft">←</button>
|
|
729
|
+
<button class="ghost sm icon-btn ticket-nav-btn" id="ticket-nav-next" title="Next ticket (Alt+→)"
|
|
730
|
+
aria-label="Next ticket" aria-keyshortcuts="Alt+ArrowRight">→</button>
|
|
554
731
|
<label class="ticket-fm-toggle" title="Mark as done">
|
|
555
732
|
<input id="ticket-fm-done" type="checkbox">
|
|
556
733
|
<span class="ticket-fm-toggle-label">Done</span>
|
|
@@ -636,6 +813,60 @@
|
|
|
636
813
|
</div>
|
|
637
814
|
</div>
|
|
638
815
|
</div>
|
|
816
|
+
<!-- Template Picker Modal -->
|
|
817
|
+
<div class="modal-overlay hidden" id="ticket-template-modal">
|
|
818
|
+
<div class="modal-content ticket-template-modal-content">
|
|
819
|
+
<div class="modal-header ticket-template-header">
|
|
820
|
+
<span class="ticket-template-title">New Ticket from Template</span>
|
|
821
|
+
<button class="ghost sm icon-btn" id="ticket-template-close" title="Close">×</button>
|
|
822
|
+
</div>
|
|
823
|
+
<div class="ticket-template-body">
|
|
824
|
+
<!-- Recent templates (shown if history exists) -->
|
|
825
|
+
<div class="ticket-template-recent hidden" id="ticket-template-recent"></div>
|
|
826
|
+
|
|
827
|
+
<!-- Main input section -->
|
|
828
|
+
<div class="ticket-template-input-section">
|
|
829
|
+
<div class="ticket-template-input-wrapper">
|
|
830
|
+
<input class="ticket-template-input" id="ticket-template-ref" type="text"
|
|
831
|
+
placeholder="repo:path/to/template.md" spellcheck="false" autocomplete="off">
|
|
832
|
+
<button class="ticket-template-clear hidden" id="ticket-template-clear" type="button"
|
|
833
|
+
title="Clear">×</button>
|
|
834
|
+
<span class="ticket-template-input-hint" id="ticket-template-hint">or paste GitHub URL</span>
|
|
835
|
+
</div>
|
|
836
|
+
<div class="ticket-template-repos" id="ticket-template-repos"></div>
|
|
837
|
+
</div>
|
|
838
|
+
|
|
839
|
+
<!-- Preview -->
|
|
840
|
+
<div class="ticket-template-preview-section">
|
|
841
|
+
<div class="ticket-template-preview-header">
|
|
842
|
+
<span class="ticket-template-preview-label">Preview</span>
|
|
843
|
+
<span class="ticket-template-preview-status" id="ticket-template-preview-status"></span>
|
|
844
|
+
</div>
|
|
845
|
+
<pre class="ticket-template-preview" id="ticket-template-preview"></pre>
|
|
846
|
+
</div>
|
|
847
|
+
|
|
848
|
+
<!-- Error -->
|
|
849
|
+
<div class="ticket-template-error hidden" id="ticket-template-error"></div>
|
|
850
|
+
|
|
851
|
+
<!-- Footer -->
|
|
852
|
+
<div class="ticket-template-footer">
|
|
853
|
+
<div class="ticket-template-options">
|
|
854
|
+
<label class="ticket-template-option-label">Agent:</label>
|
|
855
|
+
<select class="ticket-template-agent-select" id="ticket-template-agent">
|
|
856
|
+
<option value="">default</option>
|
|
857
|
+
<option value="codex">codex</option>
|
|
858
|
+
<option value="opencode">opencode</option>
|
|
859
|
+
<option value="user">user</option>
|
|
860
|
+
</select>
|
|
861
|
+
</div>
|
|
862
|
+
<div class="ticket-template-actions">
|
|
863
|
+
<button class="ghost sm" id="ticket-template-cancel">Cancel</button>
|
|
864
|
+
<button class="primary sm" id="ticket-template-apply" disabled>Create</button>
|
|
865
|
+
</div>
|
|
866
|
+
</div>
|
|
867
|
+
</div>
|
|
868
|
+
</div>
|
|
869
|
+
</div>
|
|
639
870
|
</section>
|
|
640
871
|
<section class="panel" id="terminal">
|
|
641
872
|
<div class="terminal-toolbar">
|
|
@@ -879,12 +1110,60 @@
|
|
|
879
1110
|
</div>
|
|
880
1111
|
<span class="form-hint">Resetting conversations clears stored thread IDs and restarts chats.</span>
|
|
881
1112
|
</div>
|
|
1113
|
+
<div class="form-group">
|
|
1114
|
+
<label>Template Repositories</label>
|
|
1115
|
+
<div class="template-repos-list" id="template-repos-list"></div>
|
|
1116
|
+
<div class="settings-actions">
|
|
1117
|
+
<button class="ghost sm" id="template-repos-add">+ Add repository</button>
|
|
1118
|
+
</div>
|
|
1119
|
+
<div class="template-repo-form hidden" id="template-repo-form">
|
|
1120
|
+
<div class="settings-grid">
|
|
1121
|
+
<div>
|
|
1122
|
+
<label class="muted small" for="repo-id">ID</label>
|
|
1123
|
+
<input autocomplete="off" id="repo-id" placeholder="my-team" spellcheck="false" type="text" />
|
|
1124
|
+
<span class="form-hint">Used in refs like <span class="mono">id:path/to/file.md</span></span>
|
|
1125
|
+
</div>
|
|
1126
|
+
<div>
|
|
1127
|
+
<label class="muted small" for="repo-url">Git URL</label>
|
|
1128
|
+
<input autocomplete="off" id="repo-url" placeholder="https://github.com/org/repo.git" spellcheck="false"
|
|
1129
|
+
type="text" />
|
|
1130
|
+
</div>
|
|
1131
|
+
<div>
|
|
1132
|
+
<label class="muted small" for="repo-ref">Default ref</label>
|
|
1133
|
+
<input autocomplete="off" id="repo-ref" placeholder="main" spellcheck="false" type="text"
|
|
1134
|
+
value="main" />
|
|
1135
|
+
</div>
|
|
1136
|
+
<div class="settings-toggle-row">
|
|
1137
|
+
<label class="form-checkbox">
|
|
1138
|
+
<input id="repo-trusted" type="checkbox" />
|
|
1139
|
+
<span>Trusted (skip scanning)</span>
|
|
1140
|
+
</label>
|
|
1141
|
+
</div>
|
|
1142
|
+
</div>
|
|
1143
|
+
<div class="settings-actions">
|
|
1144
|
+
<button class="primary sm" id="repo-save">Save</button>
|
|
1145
|
+
<button class="ghost sm" id="repo-cancel">Cancel</button>
|
|
1146
|
+
</div>
|
|
1147
|
+
</div>
|
|
1148
|
+
<span class="form-hint">Edits are written to <span class="mono">codex-autorunner.override.yml</span>.</span>
|
|
1149
|
+
</div>
|
|
882
1150
|
</div>
|
|
883
1151
|
<div class="modal-actions">
|
|
884
1152
|
<button class="ghost" id="repo-settings-close">Close</button>
|
|
885
1153
|
</div>
|
|
886
1154
|
</div>
|
|
887
1155
|
</div>
|
|
1156
|
+
<!-- Notifications Modal -->
|
|
1157
|
+
<div class="modal-overlay hidden" id="notifications-modal">
|
|
1158
|
+
<div aria-labelledby="notifications-modal-title" aria-modal="true" class="modal-dialog notifications-modal-dialog"
|
|
1159
|
+
role="dialog" tabindex="-1">
|
|
1160
|
+
<div class="notifications-modal-header">
|
|
1161
|
+
<span class="label" id="notifications-modal-title">Pending dispatch</span>
|
|
1162
|
+
<button class="ghost sm icon-btn" id="notifications-modal-close" title="Close">×</button>
|
|
1163
|
+
</div>
|
|
1164
|
+
<div class="notifications-modal-body-wrapper" id="notifications-modal-body"></div>
|
|
1165
|
+
</div>
|
|
1166
|
+
</div>
|
|
888
1167
|
<!-- Reason Details Modal -->
|
|
889
1168
|
<div class="modal-overlay" hidden="" id="reason-modal">
|
|
890
1169
|
<div aria-describedby="reason-modal-content" aria-labelledby="reason-modal-title" aria-modal="true"
|
|
@@ -953,4 +1232,4 @@
|
|
|
953
1232
|
<script data-car-loader="" src="static/loader.js?v=__CAR_ASSET_VERSION__"></script>
|
|
954
1233
|
</body>
|
|
955
1234
|
|
|
956
|
-
</html>
|
|
1235
|
+
</html>
|
|
@@ -4,6 +4,7 @@ import { subscribe } from "./bus.js";
|
|
|
4
4
|
import { isRepoHealthy } from "./health.js";
|
|
5
5
|
import { preserveScroll } from "./preserve.js";
|
|
6
6
|
import { createSmartRefresh } from "./smartRefresh.js";
|
|
7
|
+
import { createFileBoxWidget } from "./fileboxUi.js";
|
|
7
8
|
let bellInitialized = false;
|
|
8
9
|
let messagesInitialized = false;
|
|
9
10
|
let activeRunId = null;
|
|
@@ -17,8 +18,16 @@ const refreshEl = document.getElementById("messages-refresh");
|
|
|
17
18
|
const replyBodyEl = document.getElementById("messages-reply-body");
|
|
18
19
|
const replyFilesEl = document.getElementById("messages-reply-files");
|
|
19
20
|
const replySendEl = document.getElementById("messages-reply-send");
|
|
21
|
+
const replyAttachBtn = document.getElementById("messages-reply-attach");
|
|
22
|
+
const replyAttachSummary = document.getElementById("messages-reply-attach-summary");
|
|
23
|
+
const fileBoxInboxEl = document.getElementById("messages-filebox-inbox");
|
|
24
|
+
const fileBoxOutboxEl = document.getElementById("messages-filebox-outbox");
|
|
25
|
+
const fileBoxUploadEl = document.getElementById("messages-filebox-upload");
|
|
26
|
+
const fileBoxUploadBtn = document.getElementById("messages-filebox-upload-btn");
|
|
27
|
+
const fileBoxRefreshBtn = document.getElementById("messages-filebox-refresh");
|
|
20
28
|
let threadListRefreshCount = 0;
|
|
21
29
|
let threadDetailRefreshCount = 0;
|
|
30
|
+
let fileBoxCtrl = null;
|
|
22
31
|
function isMobileViewport() {
|
|
23
32
|
return window.innerWidth <= 640;
|
|
24
33
|
}
|
|
@@ -30,6 +39,21 @@ function showThreadDetail() {
|
|
|
30
39
|
layoutEl?.classList.add("viewing-detail");
|
|
31
40
|
}
|
|
32
41
|
}
|
|
42
|
+
function initFileBox() {
|
|
43
|
+
if (fileBoxCtrl || (!fileBoxInboxEl && !fileBoxOutboxEl))
|
|
44
|
+
return;
|
|
45
|
+
fileBoxCtrl = createFileBoxWidget({
|
|
46
|
+
scope: "repo",
|
|
47
|
+
inboxEl: fileBoxInboxEl,
|
|
48
|
+
outboxEl: fileBoxOutboxEl,
|
|
49
|
+
uploadInput: fileBoxUploadEl,
|
|
50
|
+
uploadBtn: fileBoxUploadBtn,
|
|
51
|
+
refreshBtn: fileBoxRefreshBtn,
|
|
52
|
+
uploadBox: "inbox",
|
|
53
|
+
emptyMessage: "No files",
|
|
54
|
+
});
|
|
55
|
+
void fileBoxCtrl.refresh();
|
|
56
|
+
}
|
|
33
57
|
function setThreadListRefreshing(active) {
|
|
34
58
|
if (!threadsEl)
|
|
35
59
|
return;
|
|
@@ -342,6 +366,27 @@ function formatBytes(size) {
|
|
|
342
366
|
return `${(size / 1000).toFixed(0)} KB`;
|
|
343
367
|
return `${size} B`;
|
|
344
368
|
}
|
|
369
|
+
function isSafeHref(url) {
|
|
370
|
+
const trimmed = (url || "").trim();
|
|
371
|
+
if (!trimmed)
|
|
372
|
+
return false;
|
|
373
|
+
const lower = trimmed.toLowerCase();
|
|
374
|
+
if (lower.startsWith("javascript:"))
|
|
375
|
+
return false;
|
|
376
|
+
if (lower.startsWith("data:"))
|
|
377
|
+
return false;
|
|
378
|
+
if (lower.startsWith("vbscript:"))
|
|
379
|
+
return false;
|
|
380
|
+
if (lower.startsWith("file:"))
|
|
381
|
+
return false;
|
|
382
|
+
return (lower.startsWith("http://") ||
|
|
383
|
+
lower.startsWith("https://") ||
|
|
384
|
+
trimmed.startsWith("/") ||
|
|
385
|
+
trimmed.startsWith("./") ||
|
|
386
|
+
trimmed.startsWith("../") ||
|
|
387
|
+
trimmed.startsWith("#") ||
|
|
388
|
+
lower.startsWith("mailto:"));
|
|
389
|
+
}
|
|
345
390
|
export function renderMarkdown(body) {
|
|
346
391
|
if (!body)
|
|
347
392
|
return "";
|
|
@@ -365,7 +410,11 @@ export function renderMarkdown(body) {
|
|
|
365
410
|
text = text.replace(/\*([^*]+)\*/g, "<em>$1</em>");
|
|
366
411
|
// Extract markdown links [text](url) to avoid double-linking
|
|
367
412
|
const links = [];
|
|
368
|
-
text = text.replace(/\[([^\]]+)\]\((
|
|
413
|
+
text = text.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (match, label, rawUrl) => {
|
|
414
|
+
const url = (rawUrl || "").trim();
|
|
415
|
+
if (!isSafeHref(url)) {
|
|
416
|
+
return match;
|
|
417
|
+
}
|
|
369
418
|
const placeholder = `@@LINK_${links.length}@@`;
|
|
370
419
|
// Note: label and url are already escaped because text is escaped.
|
|
371
420
|
links.push(`<a href="${url}" target="_blank" rel="noopener">${label}</a>`);
|
|
@@ -433,7 +482,8 @@ export function renderMarkdown(body) {
|
|
|
433
482
|
const idx = Number(match[1]);
|
|
434
483
|
return codeBlocks[idx] ?? "";
|
|
435
484
|
}
|
|
436
|
-
|
|
485
|
+
const content = block.replace(/\n/g, "<br>").replace(/@@CODEBLOCK_(\d+)@@/g, (_m, id) => codeBlocks[Number(id)] ?? "");
|
|
486
|
+
return `<p>${content}</p>`;
|
|
437
487
|
})
|
|
438
488
|
.join("");
|
|
439
489
|
}
|
|
@@ -444,9 +494,12 @@ function renderFiles(files) {
|
|
|
444
494
|
.map((f) => {
|
|
445
495
|
const size = formatBytes(f.size);
|
|
446
496
|
const href = resolvePath(f.url || "");
|
|
497
|
+
const isHttp = /^https?:\/\//.test(href);
|
|
498
|
+
const targetAttrs = isHttp ? ' target="_blank" rel="noopener"' : "";
|
|
499
|
+
const downloadAttr = isHttp ? "" : " download";
|
|
447
500
|
return `<li class="messages-file">
|
|
448
501
|
<span class="messages-file-icon">📎</span>
|
|
449
|
-
<a href="${escapeHtml(href)}"
|
|
502
|
+
<a href="${escapeHtml(href)}"${downloadAttr}${targetAttrs}>${escapeHtml(f.name)}</a>
|
|
450
503
|
${size ? `<span class="messages-file-size muted small">${escapeHtml(size)}</span>` : ""}
|
|
451
504
|
</li>`;
|
|
452
505
|
})
|
|
@@ -758,7 +811,7 @@ function renderThreadDetail(detail, runId, ctx) {
|
|
|
758
811
|
attachCollapseHandlers();
|
|
759
812
|
}
|
|
760
813
|
// Only show reply box for paused runs - replies to other states won't be seen
|
|
761
|
-
const replyBoxEl = document.querySelector(".messages-
|
|
814
|
+
const replyBoxEl = document.querySelector(".messages-compose");
|
|
762
815
|
if (replyBoxEl) {
|
|
763
816
|
replyBoxEl.classList.toggle("hidden", !isPaused);
|
|
764
817
|
}
|
|
@@ -770,6 +823,19 @@ function renderThreadDetail(detail, runId, ctx) {
|
|
|
770
823
|
});
|
|
771
824
|
}
|
|
772
825
|
}
|
|
826
|
+
function refreshAttachSummary() {
|
|
827
|
+
if (!replyAttachSummary || !replyFilesEl)
|
|
828
|
+
return;
|
|
829
|
+
const files = Array.from(replyFilesEl.files || []);
|
|
830
|
+
if (!files.length) {
|
|
831
|
+
replyAttachSummary.textContent = "";
|
|
832
|
+
replyAttachSummary.classList.add("hidden");
|
|
833
|
+
return;
|
|
834
|
+
}
|
|
835
|
+
const label = files.length > 2 ? `${files.length} files` : files.map((f) => f.name).join(", ");
|
|
836
|
+
replyAttachSummary.textContent = label;
|
|
837
|
+
replyAttachSummary.classList.remove("hidden");
|
|
838
|
+
}
|
|
773
839
|
async function sendReply() {
|
|
774
840
|
const runId = selectedRunId;
|
|
775
841
|
if (!runId) {
|
|
@@ -795,6 +861,7 @@ async function sendReply() {
|
|
|
795
861
|
replyBodyEl.value = "";
|
|
796
862
|
if (replyFilesEl)
|
|
797
863
|
replyFilesEl.value = "";
|
|
864
|
+
refreshAttachSummary();
|
|
798
865
|
flash("Reply sent", "success");
|
|
799
866
|
// Always resume after sending
|
|
800
867
|
await api(`/api/flows/${encodeURIComponent(runId)}/resume`, { method: "POST" });
|
|
@@ -812,6 +879,7 @@ export function initMessages() {
|
|
|
812
879
|
if (!threadsEl || !detailEl)
|
|
813
880
|
return;
|
|
814
881
|
messagesInitialized = true;
|
|
882
|
+
initFileBox();
|
|
815
883
|
backBtn?.addEventListener("click", showThreadList);
|
|
816
884
|
window.addEventListener("resize", () => {
|
|
817
885
|
if (!isMobileViewport()) {
|
|
@@ -827,6 +895,13 @@ export function initMessages() {
|
|
|
827
895
|
replySendEl?.addEventListener("click", () => {
|
|
828
896
|
void sendReply();
|
|
829
897
|
});
|
|
898
|
+
replyAttachBtn?.addEventListener("click", () => {
|
|
899
|
+
replyFilesEl?.click();
|
|
900
|
+
});
|
|
901
|
+
replyFilesEl?.addEventListener("change", () => {
|
|
902
|
+
refreshAttachSummary();
|
|
903
|
+
});
|
|
904
|
+
refreshAttachSummary();
|
|
830
905
|
// Load threads immediately, and try to open run_id from URL if present.
|
|
831
906
|
void loadThreads("initial").then(() => {
|
|
832
907
|
const params = getUrlParams();
|
|
@@ -868,6 +943,9 @@ export function initMessages() {
|
|
|
868
943
|
if (selectedRunId) {
|
|
869
944
|
void loadThread(selectedRunId, "background");
|
|
870
945
|
}
|
|
946
|
+
if (status === "ok" || status === "degraded") {
|
|
947
|
+
void fileBoxCtrl?.refresh();
|
|
948
|
+
}
|
|
871
949
|
}
|
|
872
950
|
});
|
|
873
951
|
}
|