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,980 +1,909 @@
1
- <!doctype html>
1
+ <!DOCTYPE html>
2
+
2
3
  <html lang="en">
3
- <head>
4
- <script src="static/bootstrap.js?v=__CAR_ASSET_VERSION__" data-car-bootstrap></script>
5
- <meta charset="utf-8" />
6
- <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover" />
7
- <meta name="apple-mobile-web-app-capable" content="yes" />
8
- <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
9
- <meta name="theme-color" content="#0a0c12" />
10
- <title>Codex Autorunner</title>
11
- </head>
12
- <body>
13
- <div id="hub-shell" class="hub-shell hidden">
14
- <header class="hub-hero">
15
- <div class="hub-hero-text">
16
- <h1>CAR Hub</h1>
17
- <span id="hub-last-scan" class="pill pill-small pill-idle">–</span>
18
- <span id="hub-version" class="hub-version">v–</span>
19
- </div>
20
- <div class="hub-hero-actions">
21
- <button id="hub-new-repo" class="primary sm">+ New</button>
22
- <button id="hub-scan" class="sm">Scan</button>
23
- <button id="hub-refresh" class="ghost sm">Refresh</button>
24
- <button id="hub-settings" class="ghost sm icon-btn" title="Settings">⚙</button>
25
- </div>
26
- </header>
27
4
 
28
- <section class="hub-stats">
29
- <div class="hub-stat">
30
- <div id="hub-count-total" class="hub-stat-value">–</div>
31
- <p class="muted small">repos</p>
32
- </div>
33
- <div class="hub-stat">
34
- <div id="hub-count-running" class="hub-stat-value">–</div>
35
- <p class="muted small">running</p>
36
- </div>
37
- <div class="hub-stat">
38
- <div id="hub-count-missing" class="hub-stat-value">–</div>
39
- <p class="muted small">missing</p>
40
- </div>
41
- </section>
5
+ <head>
6
+ <script data-car-bootstrap="" src="static/bootstrap.js?v=__CAR_ASSET_VERSION__"></script>
7
+ <meta charset="utf-8" />
8
+ <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover"
9
+ name="viewport" />
10
+ <meta content="yes" name="apple-mobile-web-app-capable" />
11
+ <meta content="black-translucent" name="apple-mobile-web-app-status-bar-style" />
12
+ <meta content="#0a0c12" name="theme-color" />
13
+ <title>Codex Autorunner</title>
14
+ </head>
42
15
 
43
- <section class="hub-usage-compact">
44
- <div class="hub-usage-header">
45
- <span class="label">Usage</span>
46
- <span id="hub-usage-meta" class="hub-usage-path">–</span>
47
- <button id="hub-usage-refresh" class="ghost sm icon-btn" title="Refresh usage">↻</button>
48
- </div>
49
- <div id="hub-usage-list" class="hub-usage-grid">Loading…</div>
50
- </section>
51
-
52
- <section class="hub-usage-chart">
53
- <div class="hub-usage-chart-header">
54
- <span class="label">Usage Trend</span>
55
- <div class="usage-chart-controls">
56
- <select id="hub-usage-chart-range" class="usage-chart-select" title="Range" aria-label="Range">
57
- <option value="7">1w</option>
58
- <option value="30" selected>1m</option>
59
- <option value="90">3m</option>
60
- <option value="180">6m</option>
61
- <option value="365">1y</option>
62
- </select>
63
- <select id="hub-usage-chart-segment" class="usage-chart-select" title="Group" aria-label="Group">
64
- <option value="none">Total</option>
65
- <option value="repo">By repo</option>
66
- <option value="agent">By agent</option>
67
- </select>
68
- </div>
16
+ <body>
17
+ <div class="hub-shell hidden" id="hub-shell">
18
+ <header class="hub-hero">
19
+ <div class="hub-hero-text">
20
+ <h1>CAR Hub</h1>
21
+ <span class="pill pill-small pill-idle" id="hub-last-scan">–</span>
22
+ <span class="hub-version" id="hub-version">v–</span>
23
+ </div>
24
+ <div class="hub-hero-actions">
25
+ <button class="primary sm" id="hub-new-repo">+ New</button>
26
+ <button class="sm" id="hub-scan">Scan</button>
27
+ <button class="ghost sm" id="hub-refresh">Refresh</button>
28
+ <button class="ghost sm icon-btn" id="hub-settings" title="Settings">⚙</button>
29
+ </div>
30
+ </header>
31
+ <section class="hub-stats">
32
+ <div class="hub-stat">
33
+ <div class="hub-stat-value" id="hub-count-total">–</div>
34
+ <p class="muted small">repos</p>
35
+ </div>
36
+ <div class="hub-stat">
37
+ <div class="hub-stat-value" id="hub-count-running">–</div>
38
+ <p class="muted small">running</p>
39
+ </div>
40
+ <div class="hub-stat">
41
+ <div class="hub-stat-value" id="hub-count-missing">–</div>
42
+ <p class="muted small">missing</p>
43
+ </div>
44
+ </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>
69
50
  </div>
70
- <div id="hub-usage-chart-canvas" class="usage-chart-canvas hub-usage-chart-canvas"></div>
71
- </section>
72
-
73
- <section class="hub-repo-panel">
74
- <div class="hub-panel-header">
75
- <span class="label">Repositories</span>
76
- <div class="hub-panel-actions">
77
- <button id="hub-quick-scan" class="ghost sm">Rescan</button>
78
- </div>
51
+ </div>
52
+ <div class="hub-inbox-list" id="hub-inbox-list">Loading…</div>
53
+ </section>
54
+ <section class="hub-usage-compact">
55
+ <div class="hub-usage-header">
56
+ <span class="label">Usage</span>
57
+ <span class="hub-usage-path" id="hub-usage-meta">–</span>
58
+ <button class="ghost sm icon-btn" id="hub-usage-refresh" title="Refresh usage">↻</button>
59
+ </div>
60
+ <div class="hub-usage-grid" id="hub-usage-list">Loading…</div>
61
+ </section>
62
+ <section class="hub-usage-chart">
63
+ <div class="hub-usage-chart-header">
64
+ <span class="label">Usage Trend</span>
65
+ <div class="usage-chart-controls">
66
+ <select aria-label="Range" class="usage-chart-select" id="hub-usage-chart-range" title="Range">
67
+ <option value="7">1w</option>
68
+ <option selected="" value="30">1m</option>
69
+ <option value="90">3m</option>
70
+ <option value="180">6m</option>
71
+ <option value="365">1y</option>
72
+ </select>
73
+ <select aria-label="Group" class="usage-chart-select" id="hub-usage-chart-segment" title="Group">
74
+ <option value="none">Total</option>
75
+ <option value="repo">By repo</option>
76
+ <option value="agent">By agent</option>
77
+ </select>
79
78
  </div>
80
- <div id="hub-repo-list" class="hub-repo-list">
81
- <div class="muted small">Loading…</div>
79
+ </div>
80
+ <div class="usage-chart-canvas hub-usage-chart-canvas" id="hub-usage-chart-canvas"></div>
81
+ </section>
82
+ <section class="hub-repo-panel">
83
+ <div class="hub-panel-header">
84
+ <span class="label">Repositories</span>
85
+ <div class="hub-panel-actions">
86
+ <button class="ghost sm" id="hub-quick-scan">Rescan</button>
82
87
  </div>
83
- </section>
84
- </div>
85
-
86
- <div id="repo-shell" class="app-shell">
87
- <nav class="nav-bar">
88
- <span class="nav-brand">CAR</span>
89
- <div class="tabs">
90
- <!-- Tabs will be injected here by tabs.js -->
88
+ </div>
89
+ <div class="hub-repo-list" id="hub-repo-list">
90
+ <div class="muted small">Loading…</div>
91
+ </div>
92
+ </section>
93
+ </div>
94
+ <div class="app-shell" id="repo-shell">
95
+ <nav class="nav-bar">
96
+ <span class="nav-brand">CAR</span>
97
+ <div class="tabs">
98
+ <!-- Tabs will be injected here by tabs.js -->
99
+ </div>
100
+ <div class="nav-actions">
101
+ <button class="ghost sm icon-btn" id="repo-settings" title="Settings">⚙</button>
102
+ </div>
103
+ </nav>
104
+ <main>
105
+ <div class="doc-banner hidden" id="repo-health-banner">
106
+ <div class="doc-banner-text">
107
+ <div class="doc-banner-title" id="repo-health-title">Repo server offline</div>
108
+ <div class="doc-banner-detail muted small" id="repo-health-detail"></div>
91
109
  </div>
92
- <div class="nav-actions">
93
- <button id="repo-settings" class="ghost sm icon-btn" title="Settings">⚙</button>
110
+ <div class="doc-banner-actions">
111
+ <button class="ghost sm" id="repo-health-retry">Retry</button>
94
112
  </div>
95
- </nav>
96
-
97
- <main>
98
- <section id="dashboard" class="panel active">
99
- <div class="cards">
100
- <div class="card status-card">
101
- <div class="card-header">
102
- <div class="card-header-left">
103
- <span class="label">Runner Status</span>
104
- <span id="repo-version" class="version-label">v–</span>
105
- </div>
106
- <span id="runner-status" class="pill pill-idle">idle</span>
113
+ </div>
114
+ <section class="panel" id="analytics">
115
+ <div class="cards">
116
+ <div class="card status-card">
117
+ <div class="card-header">
118
+ <div class="card-header-left">
119
+ <span class="label">Ticket Analytics</span>
120
+ <span class="version-label" id="repo-version">v–</span>
107
121
  </div>
108
- <div class="grid-two">
109
- <div>
110
- <p class="muted">Run ID</p>
111
- <p id="last-run-id" class="metric">–</p>
112
- </div>
113
- <div>
114
- <p class="muted">Exit</p>
115
- <p id="last-exit-code" class="metric">–</p>
116
- </div>
117
- <div>
118
- <p class="muted">Started</p>
119
- <p id="last-start" class="metric">–</p>
120
- </div>
121
- <div>
122
- <p class="muted">Finished</p>
123
- <p id="last-finish" class="metric">–</p>
124
- </div>
125
- <div>
126
- <p class="muted">TODO</p>
127
- <p id="todo-count" class="metric">–</p>
128
- </div>
129
- <div>
130
- <p class="muted">Done</p>
131
- <p id="done-count" class="metric">–</p>
132
- </div>
122
+ <span class="pill pill-idle" id="runner-status">idle</span>
123
+ </div>
124
+ <div class="grid-two">
125
+ <div>
126
+ <p class="muted">Started</p>
127
+ <p class="metric" id="last-start">–</p>
133
128
  </div>
134
- <div class="doc-agent-controls dashboard-agent-controls">
135
- <select id="dashboard-agent-select" title="Agent"></select>
136
- <select id="dashboard-model-select" title="Model"></select>
137
- <select id="dashboard-reasoning-select" title="Reasoning"></select>
129
+ <div>
130
+ <p class="muted">Finished</p>
131
+ <p class="metric" id="last-finish">–</p>
138
132
  </div>
139
- <div class="actions">
140
- <button id="start-run" class="primary" title="Run a full autorunner iteration through all tasks">Start</button>
141
- <button id="stop-run" class="ghost" title="Gracefully stop the current run (safe shutdown)">Stop</button>
142
- <button id="kill-run" class="danger" title="Immediately terminate the run (force stop - may cause data loss)">Kill</button>
143
- <button id="clear-lock" class="ghost hidden" title="Clear a stale autorunner lock">Clear lock</button>
144
- <button id="reset-runner" class="ghost" title="Clear run state and restart fresh (destructive)">Reset</button>
145
- <button id="refresh-state" class="ghost icon-btn" title="Refresh state">↻</button>
133
+ <div>
134
+ <p class="muted">Duration</p>
135
+ <p class="metric" id="last-duration">–</p>
146
136
  </div>
147
- <p class="muted small" id="runner-pid">PID: –</p>
148
- </div>
149
-
150
- <div class="card usage-card-compact">
151
- <div class="usage-header">
152
- <span class="label">Usage</span>
153
- <span class="usage-total-badge" id="usage-total">–</span>
154
- <span class="usage-events-badge" id="usage-events">–</span>
155
- <button id="usage-refresh" class="ghost sm icon-btn" title="Refresh usage">↻</button>
156
- </div>
157
- <div class="usage-breakdown">
158
- <div class="usage-stat">
159
- <span class="usage-stat-val" id="usage-input">–</span>
160
- <span class="usage-stat-lbl">in</span>
161
- </div>
162
- <div class="usage-stat usage-stat-cached">
163
- <span class="usage-stat-val" id="usage-cached">–</span>
164
- <span class="usage-stat-lbl">cached</span>
165
- </div>
166
- <div class="usage-stat">
167
- <span class="usage-stat-val" id="usage-output">–</span>
168
- <span class="usage-stat-lbl">out</span>
169
- </div>
170
- <div class="usage-stat">
171
- <span class="usage-stat-val" id="usage-reasoning">–</span>
172
- <span class="usage-stat-lbl">reason</span>
173
- </div>
137
+ <div>
138
+ <p class="muted">TODO</p>
139
+ <p class="metric" id="todo-count">–</p>
174
140
  </div>
175
- <div class="usage-chart">
176
- <div class="usage-chart-header">
177
- <span class="usage-chart-title">Trend</span>
178
- <div class="usage-chart-controls">
179
- <select id="usage-chart-range" class="usage-chart-select" title="Range" aria-label="Range">
180
- <option value="7">1w</option>
181
- <option value="30" selected>1m</option>
182
- <option value="90">3m</option>
183
- <option value="180">6m</option>
184
- <option value="365">1y</option>
185
- </select>
186
- <select id="usage-chart-segment" class="usage-chart-select" title="Group" aria-label="Group">
187
- <option value="none">Total</option>
188
- <option value="agent">Agent</option>
189
- <option value="model">Model</option>
190
- <option value="token_type">Token type</option>
191
- <option value="model_token">Model + type</option>
192
- </select>
193
- </div>
194
- </div>
195
- <div id="usage-chart-canvas" class="usage-chart-canvas"></div>
141
+ <div>
142
+ <p class="muted">Done</p>
143
+ <p class="metric" id="done-count">–</p>
196
144
  </div>
197
- <div class="usage-rates-visual">
198
- <div class="usage-rate-row">
199
- <span class="usage-rate-label">Primary</span>
200
- <div id="usage-rate-primary" class="usage-rate-bar-container"></div>
201
- </div>
202
- <div class="usage-rate-row">
203
- <span class="usage-rate-label">Secondary</span>
204
- <div id="usage-rate-secondary" class="usage-rate-bar-container"></div>
205
- </div>
145
+ <div>
146
+ <p class="muted">Active ticket</p>
147
+ <p class="metric" id="ticket-active">–</p>
206
148
  </div>
207
- <div class="usage-footer">
208
- <span id="usage-rates" class="hidden">–</span>
209
- <span id="usage-meta">–</span>
149
+ <div>
150
+ <p class="muted">Ticket Turns</p>
151
+ <p class="metric" id="ticket-turns">–</p>
152
+ </div>
153
+ <div>
154
+ <p class="muted">Total Turns</p>
155
+ <p class="metric" id="total-turns">–</p>
156
+ </div>
157
+ <div>
158
+ <p class="muted">Dispatches</p>
159
+ <p class="metric" id="message-dispatches">–</p>
160
+ </div>
161
+ <div>
162
+ <p class="muted">Replies</p>
163
+ <p class="metric" id="message-replies">–</p>
164
+ </div>
165
+ <div>
166
+ <p class="muted">Run ID</p>
167
+ <p class="metric" id="last-run-id">–</p>
210
168
  </div>
211
169
  </div>
212
-
213
- <div class="card todo-preview">
214
- <div class="card-header">
215
- <span class="label">TODO</span>
216
- <button id="open-summary" class="primary sm hidden" title="Open final report (SUMMARY)">Summary</button>
217
- <button id="refresh-preview" class="ghost sm icon-btn" title="Refresh TODO preview">↻</button>
170
+ </div>
171
+ <details class="card" id="run-history">
172
+ <summary class="card-header">
173
+ <div class="card-header-left">
174
+ <span class="label">Run History</span>
175
+ <span class="muted small">Last 10 runs</span>
218
176
  </div>
219
- <ul id="todo-preview-list" class="checklist"></ul>
177
+ <button class="ghost sm icon-btn" id="analytics-refresh" title="Refresh analytics">↻</button>
178
+ </summary>
179
+ <div class="run-history-list" id="run-history-list">
180
+ <div class="muted">Loading…</div>
220
181
  </div>
221
-
222
- <div class="card github-card" id="github-card">
223
- <div class="card-header">
224
- <span class="label">GitHub</span>
225
- <span id="github-status-pill" class="pill pill-idle">–</span>
226
- </div>
227
- <div class="github-grid">
228
- <div class="github-row">
229
- <span class="muted">Repo</span>
230
- <a id="github-repo-link" class="github-link muted">–</a>
231
- </div>
232
- <div class="github-row">
233
- <span class="muted">Branch</span>
234
- <span id="github-branch" class="github-mono">–</span>
235
- </div>
236
- <div class="github-row">
237
- <span class="muted">Issue</span>
238
- <a id="github-issue-link" class="github-link muted">–</a>
239
- </div>
240
- <div class="github-row">
241
- <span class="muted">PR</span>
242
- <span class="github-pr-group">
243
- <a id="github-pr-link" class="github-link muted">–</a>
244
- <button id="github-open-pr-files" class="ghost icon-btn-inline" disabled title="View changed files">📄</button>
245
- <button id="github-copy-pr" class="ghost icon-btn-inline" disabled title="Copy PR link">📋</button>
246
- </span>
247
- </div>
182
+ </details>
183
+ <div class="card usage-card-compact">
184
+ <div class="usage-header">
185
+ <span class="label">Usage</span>
186
+ <span class="usage-total-badge" id="usage-total">–</span>
187
+ <span class="usage-events-badge" id="usage-events">–</span>
188
+ <button class="ghost sm icon-btn" id="usage-refresh" title="Refresh usage">↻</button>
189
+ </div>
190
+ <div class="usage-breakdown">
191
+ <div class="usage-stat">
192
+ <span class="usage-stat-val" id="usage-input">–</span>
193
+ <span class="usage-stat-lbl">in</span>
248
194
  </div>
249
- <div class="actions github-actions">
250
- <button id="github-sync-pr" class="primary sm">Sync PR</button>
195
+ <div class="usage-stat usage-stat-cached">
196
+ <span class="usage-stat-val" id="usage-cached">–</span>
197
+ <span class="usage-stat-lbl">cached</span>
251
198
  </div>
252
- <div class="github-flow">
253
- <div class="github-flow-header">
254
- <span class="muted">PR Flow</span>
255
- <span id="pr-flow-status" class="pill pill-idle">–</span>
256
- </div>
257
- <div class="github-flow-grid">
258
- <label class="muted" for="pr-flow-mode">Mode</label>
259
- <select id="pr-flow-mode">
260
- <option value="issue">Implement Issue → PR</option>
261
- <option value="pr">Fix Existing PR</option>
199
+ <div class="usage-stat">
200
+ <span class="usage-stat-val" id="usage-output">–</span>
201
+ <span class="usage-stat-lbl">out</span>
202
+ </div>
203
+ <div class="usage-stat">
204
+ <span class="usage-stat-val" id="usage-reasoning">–</span>
205
+ <span class="usage-stat-lbl">reason</span>
206
+ </div>
207
+ </div>
208
+ <div class="usage-chart">
209
+ <div class="usage-chart-header">
210
+ <span class="usage-chart-title">Trend</span>
211
+ <div class="usage-chart-controls">
212
+ <select aria-label="Range" class="usage-chart-select" id="usage-chart-range" title="Range">
213
+ <option value="7">1w</option>
214
+ <option selected="" value="30">1m</option>
215
+ <option value="90">3m</option>
216
+ <option value="180">6m</option>
217
+ <option value="365">1y</option>
262
218
  </select>
263
- <label class="muted" for="pr-flow-ref">Issue / PR</label>
264
- <input
265
- id="pr-flow-ref"
266
- type="text"
267
- spellcheck="false"
268
- autocomplete="off"
269
- placeholder="#123 or https://github.com/org/repo/issues/123"
270
- />
271
- <label class="muted" for="pr-flow-base">Base</label>
272
- <input
273
- id="pr-flow-base"
274
- type="text"
275
- spellcheck="false"
276
- autocomplete="off"
277
- placeholder="default"
278
- />
279
- <label class="muted" for="pr-flow-until">Until</label>
280
- <select id="pr-flow-until">
281
- <option value="no_issues">No issues</option>
282
- <option value="minor_only">Minor only</option>
219
+ <select aria-label="Group" class="usage-chart-select" id="usage-chart-segment" title="Group">
220
+ <option value="none">Total</option>
221
+ <option value="agent">Agent</option>
222
+ <option value="model">Model</option>
223
+ <option value="token_type">Token type</option>
224
+ <option value="model_token">Model + type</option>
283
225
  </select>
284
- <label class="muted" for="pr-flow-cycles">Max cycles</label>
285
- <input id="pr-flow-cycles" type="number" min="1" placeholder="3" />
286
- <label class="muted" for="pr-flow-runs">Impl runs</label>
287
- <input id="pr-flow-runs" type="number" min="1" placeholder="auto" />
288
- <label class="muted" for="pr-flow-timeout">Timeout (s)</label>
289
- <input id="pr-flow-timeout" type="number" min="0" placeholder="auto" />
290
- <label class="muted" for="pr-flow-draft">Draft</label>
291
- <input id="pr-flow-draft" type="checkbox" checked />
292
- </div>
293
- <div class="actions github-flow-actions">
294
- <button id="pr-flow-start" class="primary sm">Start</button>
295
- <button id="pr-flow-stop" class="ghost sm">Stop</button>
296
- <button id="pr-flow-resume" class="ghost sm">Resume</button>
297
- <button id="pr-flow-collect" class="ghost sm">Collect reviews</button>
298
- </div>
299
- <div class="github-flow-status">
300
- <div class="github-flow-row">
301
- <span class="muted">Step</span>
302
- <span id="pr-flow-step" class="github-mono">–</span>
303
- </div>
304
- <div class="github-flow-row">
305
- <span class="muted">Cycle</span>
306
- <span id="pr-flow-cycle" class="github-mono">–</span>
307
- </div>
308
- <div class="github-flow-row">
309
- <span class="muted">Review</span>
310
- <span id="pr-flow-review" class="github-mono">–</span>
311
- </div>
312
- </div>
313
- <div class="github-flow-artifacts">
314
- <a id="pr-flow-review-link" class="github-link muted">Review bundle</a>
315
- <a id="pr-flow-log-link" class="github-link muted">Workflow log</a>
316
- <a id="pr-flow-final-link" class="github-link muted">Final report</a>
317
226
  </div>
318
- </div>
319
- <p id="github-note" class="muted small">–</p>
320
- </div>
321
- </div>
322
-
323
- <div class="card review-card" id="review-card">
324
- <div class="card-header">
325
- <span class="label">Review</span>
326
- <span id="review-status-pill" class="pill pill-idle">–</span>
327
- </div>
328
- <div class="review-grid">
329
- <div class="review-row">
330
- <span class="muted">Run ID</span>
331
- <span id="review-run-id" class="review-mono">–</span>
332
- </div>
333
- <div class="review-row">
334
- <span class="muted">Started</span>
335
- <span id="review-started" class="review-mono">–</span>
336
- </div>
337
- <div class="review-row">
338
- <span class="muted">Finished</span>
339
- <span id="review-finished" class="review-mono">–</span>
340
- </div>
341
- </div>
342
- <div class="review-controls">
343
- <div class="review-inputs">
344
- <div class="review-input-row">
345
- <label class="muted" for="review-agent">Agent</label>
346
- <input id="review-agent" type="text" value="opencode" spellcheck="false" />
347
- </div>
348
- <div class="review-input-row">
349
- <label class="muted" for="review-model">Model</label>
350
- <input id="review-model" type="text" value="zai-coding-plan/glm-4.7" spellcheck="false" />
351
- </div>
352
- <div class="review-input-row">
353
- <label class="muted" for="review-reasoning">Reasoning</label>
354
- <input id="review-reasoning" type="text" placeholder="auto" spellcheck="false" />
355
- </div>
356
- <div class="review-input-row">
357
- <label class="muted" for="review-timeout">Timeout (s)</label>
358
- <input id="review-timeout" type="number" min="60" placeholder="auto" spellcheck="false" />
359
- </div>
360
- </div>
361
- <div class="review-buttons">
362
- <button id="review-start" class="primary sm">Start</button>
363
- <button id="review-stop" class="ghost sm">Stop</button>
364
- <button id="review-reset" class="ghost sm">Reset</button>
365
- </div>
366
- </div>
367
- <div class="review-artifacts">
368
- <a id="review-final-link" class="review-link muted">Final report</a>
369
- <a id="review-log-link" class="review-link muted">Log</a>
370
- <a id="review-scratchpad-link" class="review-link muted">Scratchpad</a>
371
- </div>
372
- </div>
373
- </section>
374
-
375
- <section id="docs" class="panel">
376
- <div class="doc-nav">
377
- <button class="chip active" data-doc="todo">TODO</button>
378
- <button class="chip" data-doc="progress">PROGRESS</button>
379
- <button class="chip" data-doc="opinions">OPINIONS</button>
380
- <button class="chip" data-doc="spec">SPEC</button>
381
- <button class="chip" data-doc="summary">SUMMARY</button>
382
- <button class="chip" data-doc="snapshot">SNAPSHOT</button>
383
- <span class="muted" id="doc-status"></span>
384
- </div>
385
- <div id="doc-thread-registry-banner" class="doc-banner hidden">
386
- <div class="doc-banner-text">
387
- <div class="doc-banner-title">
388
- Conversation state reset due to corrupted registry.
389
227
  </div>
390
- <div id="doc-thread-registry-detail" class="doc-banner-detail muted small"></div>
228
+ <div class="usage-chart-canvas" id="usage-chart-canvas"></div>
391
229
  </div>
392
- <div class="doc-banner-actions">
393
- <button id="doc-thread-registry-reset" class="ghost sm">Reset conversations</button>
394
- <button id="doc-thread-registry-download" class="ghost sm">Download backup</button>
230
+ <div class="usage-rates-visual">
231
+ <div class="usage-rate-row">
232
+ <span class="usage-rate-label">Primary</span>
233
+ <div class="usage-rate-bar-container" id="usage-rate-primary"></div>
234
+ </div>
235
+ <div class="usage-rate-row">
236
+ <span class="usage-rate-label">Secondary</span>
237
+ <div class="usage-rate-bar-container" id="usage-rate-secondary"></div>
238
+ </div>
395
239
  </div>
396
- </div>
397
- <div id="spec-issue-import" class="spec-issue-import hidden">
398
- <button id="spec-issue-import-toggle" class="ghost sm">Import Issue → SPEC</button>
399
- <div id="spec-issue-input-row" class="spec-issue-input-row hidden">
400
- <input
401
- id="spec-issue-input"
402
- type="text"
403
- spellcheck="false"
404
- autocomplete="off"
405
- placeholder="Issue number or URL (e.g. 123 or https://github.com/org/repo/issues/123)"
406
- />
407
- <button id="spec-issue-import-btn" class="primary sm">Import</button>
240
+ <div class="usage-footer">
241
+ <span class="hidden" id="usage-rates">–</span>
242
+ <span id="usage-meta">–</span>
408
243
  </div>
409
244
  </div>
410
- <div class="doc-editor">
411
- <div id="spec-ingest-patch-main" class="doc-patch-main hidden">
412
- <div class="doc-patch-header">
413
- <div class="doc-patch-info">
414
- <div class="muted small">Spec ingest patch</div>
415
- <div id="spec-ingest-patch-summary" class="doc-patch-summary"></div>
416
- <div class="doc-patch-legend">
417
- <span class="doc-patch-legend-item doc-patch-legend-add">Added</span>
418
- <span class="doc-patch-legend-item doc-patch-legend-del">Removed</span>
245
+ </div>
246
+
247
+ <!-- Legacy analytics section removed -->
248
+ </section>
249
+ <section class="panel" id="inbox">
250
+ <div class="cards">
251
+ <div class="card">
252
+ <div class="messages-layout">
253
+ <div class="messages-sidebar">
254
+ <div class="messages-thread-list" id="messages-thread-list"></div>
255
+ </div>
256
+ <div class="messages-main">
257
+ <div class="messages-thread-detail" id="messages-thread-detail">
258
+ <div class="messages-empty-state">
259
+ <div class="messages-empty-icon">💬</div>
260
+ <div class="messages-empty-title">Select a conversation</div>
261
+ <div class="messages-empty-hint">Choose a session from the left to view dispatches and replies.
262
+ </div>
419
263
  </div>
420
264
  </div>
421
- <div class="doc-patch-actions">
422
- <button id="spec-ingest-patch-apply" class="primary sm">Apply Patch</button>
423
- <button id="spec-ingest-patch-reload" class="ghost sm">Reload</button>
424
- <button id="spec-ingest-patch-discard" class="danger sm">Discard</button>
265
+ <div class="messages-reply-box">
266
+ <textarea class="messages-reply-body" id="messages-reply-body"
267
+ placeholder="Write a reply…"></textarea>
268
+ <div class="messages-reply-row">
269
+ <input type="file" id="messages-reply-files" multiple />
270
+ <div class="messages-reply-actions">
271
+ <button class="primary sm" id="messages-reply-send">Send</button>
272
+ </div>
273
+ </div>
425
274
  </div>
426
275
  </div>
427
- <div id="spec-ingest-patch-body" class="doc-patch-body">(no patch)</div>
428
276
  </div>
429
- <div id="doc-patch-main" class="doc-patch-main hidden">
277
+ </div>
278
+ </div>
279
+ </section>
280
+ <section class="panel" id="workspace">
281
+ <div class="workspace-header workspace-header-desktop">
282
+ <div class="workspace-header-left">
283
+ <h3 class="workspace-title">Workspace</h3>
284
+ <span class="muted small" id="workspace-status"></span>
285
+ </div>
286
+ <div class="workspace-header-actions">
287
+ <input type="file" id="workspace-upload-input" multiple hidden />
288
+ <button class="ghost sm" id="workspace-upload" title="Upload to current folder">Upload</button>
289
+ <button class="ghost sm" id="workspace-new-folder" title="Create folder">New Folder</button>
290
+ <button class="ghost sm" id="workspace-new-file" title="Create markdown file">New File</button>
291
+ <button class="ghost sm hidden" id="workspace-generate-tickets" title="Generate tickets from spec">Generate tickets</button>
292
+ <button class="ghost sm" id="workspace-reload">Reload</button>
293
+ <button class="primary sm" id="workspace-save">Save</button>
294
+ </div>
295
+ </div>
296
+ <div class="workspace-path-row">
297
+ <nav class="workspace-breadcrumbs" id="workspace-breadcrumbs"></nav>
298
+ <button class="ghost sm workspace-download-all-btn" id="workspace-download-all" title="Download all as ZIP">⬇</button>
299
+ </div>
300
+ <div class="workspace-grid">
301
+ <aside class="workspace-file-browser">
302
+ <div class="workspace-file-mobile">
303
+ <select id="workspace-file-select"></select>
304
+ </div>
305
+ <div class="workspace-file-list" id="workspace-file-list"></div>
306
+ </aside>
307
+ <div class="workspace-main">
308
+ <div class="doc-patch-main hidden" id="workspace-patch-main">
430
309
  <div class="doc-patch-header">
431
310
  <div class="doc-patch-info">
432
311
  <div class="muted small">Pending draft</div>
433
- <div id="doc-patch-summary" class="doc-patch-summary"></div>
434
- <div id="doc-patch-meta" class="doc-patch-meta"></div>
312
+ <div class="doc-patch-summary" id="workspace-patch-summary"></div>
313
+ <div class="doc-patch-meta" id="workspace-patch-meta"></div>
435
314
  <div class="doc-patch-legend">
436
315
  <span class="doc-patch-legend-item doc-patch-legend-add">Added</span>
437
316
  <span class="doc-patch-legend-item doc-patch-legend-del">Removed</span>
438
317
  </div>
439
318
  </div>
440
319
  <div class="doc-patch-actions">
441
- <button id="doc-patch-apply" class="primary sm">Apply Draft</button>
442
- <button id="doc-patch-preview" class="ghost sm" aria-pressed="false">Preview draft</button>
443
- <button id="doc-patch-reload" class="ghost sm">Reload</button>
444
- <button id="doc-patch-discard" class="danger sm">Discard</button>
320
+ <button class="primary sm" id="workspace-patch-apply">Apply</button>
321
+ <button class="ghost sm" id="workspace-patch-reload">Reload</button>
322
+ <button class="danger sm" id="workspace-patch-discard">Discard</button>
445
323
  </div>
446
324
  </div>
447
- <div id="doc-patch-body" class="doc-patch-body">(no draft)</div>
448
- </div>
449
- <textarea id="doc-content" spellcheck="false"></textarea>
450
- <div class="doc-actions" id="doc-actions-standard">
451
- <button id="save-doc" class="primary" data-short="Save">Save</button>
452
- <button id="reload-doc" class="ghost" data-short="Reload">Reload</button>
453
- <button id="doc-copy" class="ghost hidden" data-short="Copy">Copy</button>
454
- <button id="spec-paste" class="ghost hidden" data-short="Paste">Paste</button>
455
- <button id="ingest-spec" class="ghost hidden" data-short="Ingest">Ingest SPEC → Docs</button>
456
- <button id="clear-docs" class="danger hidden" data-short="Clear">Clear TODO/PROGRESS/OPINIONS</button>
325
+ <div class="doc-patch-body" id="workspace-patch-body">(no draft)</div>
457
326
  </div>
458
- <div class="doc-actions hidden" id="doc-actions-snapshot">
459
- <button id="snapshot-generate" class="primary" data-short="Run">Run snapshot</button>
460
- <button id="snapshot-copy" class="ghost" data-short="Copy">Copy</button>
461
- <button id="snapshot-refresh" class="ghost" data-short="Reload">Reload</button>
327
+ <textarea id="workspace-content" spellcheck="false"></textarea>
328
+ <!-- Mobile toolbar: file selector + actions, positioned above compose -->
329
+ <div class="workspace-mobile-toolbar">
330
+ <button class="workspace-file-btn" id="workspace-file-pill" type="button">
331
+ <span class="workspace-file-btn-name" id="workspace-file-pill-name">active_context.md</span>
332
+ </button>
333
+ <div class="workspace-mobile-actions">
334
+ <span class="muted small" id="workspace-status-mobile"></span>
335
+ <button class="ghost sm" id="workspace-reload-mobile" title="Reload">↻</button>
336
+ <button class="primary sm" id="workspace-save-mobile">Save</button>
337
+ </div>
462
338
  </div>
463
339
  <div class="doc-chat-panel compose-panel">
464
340
  <div class="doc-chat-compose">
465
341
  <div class="doc-agent-controls">
466
- <select id="doc-agent-select" title="Agent"></select>
467
- <select id="doc-model-select" title="Model"></select>
468
- <select id="doc-reasoning-select" title="Reasoning"></select>
342
+ <select id="workspace-chat-agent-select" title="Agent"></select>
343
+ <select id="workspace-chat-model-select" title="Model"></select>
344
+ <select id="workspace-chat-reasoning-select" title="Reasoning"></select>
469
345
  </div>
470
346
  <div class="doc-chat-input-row compose-row">
471
- <textarea
472
- id="doc-chat-input"
473
- rows="1"
474
- placeholder="Chat about the work docs..."
475
- spellcheck="false"
476
- enterkeyhint="enter"
477
- ></textarea>
347
+ <textarea enterkeyhint="enter" id="workspace-chat-input"
348
+ placeholder="Ask AI to edit this workspace doc..." rows="1" spellcheck="false"></textarea>
478
349
  <div class="doc-chat-input-buttons compose-buttons">
479
- <button id="doc-chat-voice" class="ghost sm voice-button" title="Hold to talk"></button>
480
- <button id="doc-chat-send" class="primary sm" title="Send">↑</button>
350
+ <button class="ghost sm voice-button" id="workspace-chat-voice" title="Hold to talk"></button>
351
+ <button class="primary sm" id="workspace-chat-send" title="Send">↑</button>
481
352
  </div>
482
353
  </div>
483
354
  <div class="doc-chat-meta">
484
355
  <div class="doc-chat-meta-left">
485
- <span class="muted small" id="doc-chat-hint">Cmd+Enter/Ctrl+Enter to send · Enter for newline</span>
486
- <span class="muted small hidden voice-status" id="doc-chat-voice-status"></span>
356
+ <span class="muted small" id="workspace-chat-hint">Cmd+Enter/Ctrl+Enter to send · Enter for
357
+ newline</span>
487
358
  </div>
488
359
  <div class="doc-chat-meta-right">
489
- <button id="doc-chat-cancel" class="ghost sm hidden doc-chat-cancel-inline" title="Cancel">✕</button>
490
- <button id="doc-chat-new-thread" class="ghost sm" title="Start a new chat thread">New thread</button>
491
- <span id="doc-chat-status" class="pill pill-idle">idle</span>
360
+ <button class="ghost sm hidden doc-chat-cancel-inline" id="workspace-chat-cancel"
361
+ title="Cancel">✕</button>
362
+ <button class="ghost sm" id="workspace-chat-new-thread" title="Start a new chat thread">New
363
+ thread</button>
364
+ <span class="pill pill-idle" id="workspace-chat-status">idle</span>
492
365
  </div>
493
366
  </div>
494
367
  </div>
495
- <div class="doc-chat-stream" id="doc-chat-stream">
496
- <div id="doc-chat-error" class="doc-chat-error hidden"></div>
497
- <div id="doc-chat-events" class="doc-chat-events hidden">
368
+ <div class="doc-chat-stream" id="workspace-chat-stream">
369
+ <div class="doc-chat-error hidden" id="workspace-chat-error"></div>
370
+ <div class="doc-chat-events hidden" id="workspace-chat-events">
498
371
  <div class="doc-chat-section-header">
499
372
  <div class="doc-chat-section-title">
500
373
  Agent updates
501
- <span id="doc-chat-events-count" class="doc-chat-count">0</span>
374
+ <span class="doc-chat-count" id="workspace-chat-events-count">0</span>
502
375
  </div>
503
- <button id="doc-chat-events-toggle" class="ghost sm hidden">
504
- Show more
505
- </button>
376
+ <button class="ghost sm hidden" id="workspace-chat-events-toggle">Show more</button>
506
377
  </div>
507
- <div id="doc-chat-events-list" class="doc-chat-events-list"></div>
378
+ <div class="doc-chat-events-list" id="workspace-chat-events-list"></div>
508
379
  </div>
509
- <div class="doc-chat-section-header">
510
- <div class="doc-chat-section-title">
511
- History
512
- <span id="doc-chat-history-count" class="doc-chat-count">0</span>
513
- </div>
380
+ <div class="doc-chat-section-header" id="workspace-chat-history-header">
381
+ <div class="doc-chat-section-title">History</div>
514
382
  </div>
515
- <div id="doc-chat-history" class="doc-chat-history"></div>
383
+ <div class="doc-chat-history" id="workspace-chat-history"></div>
516
384
  </div>
517
385
  </div>
518
386
  </div>
519
- </section>
520
-
521
- <section id="logs" class="panel">
522
- <div class="inline-toolbar">
523
- <label class="chip" data-short="Sum">
524
- <input id="log-show-summary" type="checkbox" checked />
525
- <span>Summary</span>
526
- </label>
527
- <label>Run <input id="log-run-id" type="number" min="1" placeholder="latest" /></label>
528
- <label>Tail <input id="log-tail" type="number" min="10" value="200" /></label>
529
- <button id="load-logs" class="primary sm">Load</button>
530
- <button id="toggle-log-stream" class="ghost sm">Stream</button>
531
- <span id="log-stream-status" class="log-stream-status"></span>
532
- <label class="chip" data-short="TS">
533
- <input id="log-show-timestamp" type="checkbox" checked />
534
- <span>Timestamp</span>
535
- </label>
536
- <label class="chip" data-short="Run">
537
- <input id="log-show-run" type="checkbox" />
538
- <span>Run</span>
539
- </label>
540
- </div>
541
- <div class="log-legend">
542
- <span class="log-legend-item"><span class="log-legend-dot thinking"></span>Thinking</span>
543
- <span class="log-legend-item"><span class="log-legend-dot exec"></span>Tool calls</span>
544
- <span class="log-legend-item"><span class="log-legend-dot file"></span>File updates</span>
545
- <span class="log-legend-item"><span class="log-legend-dot diff-add"></span>Added</span>
546
- <span class="log-legend-item"><span class="log-legend-dot diff-del"></span>Removed</span>
547
- <span class="log-legend-item"><span class="log-legend-dot output"></span>Agent output</span>
548
- <span class="log-legend-item"><span class="log-legend-dot context"></span>Context</span>
387
+ </div>
388
+ </section>
389
+ <section class="panel active" id="tickets">
390
+ <div class="card ticket-card" id="ticket-card">
391
+ <div class="card-header">
392
+ <div class="card-header-left ticket-header-left">
393
+ <span class="label">Ticket Flow</span>
394
+ <span class="muted small ticket-mono" id="ticket-flow-run">–</span>
395
+ </div>
396
+ <span class="pill pill-idle" id="ticket-flow-status">idle</span>
549
397
  </div>
550
- <div class="log-container">
551
- <button id="log-load-older" class="log-load-btn hidden" title="Load older logs">Load older</button>
552
- <pre id="log-output" class="log-viewer">(no log loaded)</pre>
553
- <button id="log-jump-bottom" class="log-jump-btn hidden" title="Jump to latest">↓ Latest</button>
398
+ <div class="ticket-flow-actions">
399
+ <button class="primary sm" id="ticket-flow-bootstrap">Start Ticket Flow</button>
400
+ <button class="ghost sm" id="ticket-flow-stop">Stop</button>
401
+ <button class="ghost sm" id="ticket-flow-resume">Resume</button>
402
+ <button class="ghost sm ticket-desktop-only" id="ticket-flow-restart" style="display:none;">Restart</button>
403
+ <button class="ghost sm ticket-desktop-only" id="ticket-flow-archive" style="display:none;">Archive Flow</button>
404
+ <button class="ghost sm icon-btn" id="ticket-flow-refresh" title="Refresh ticket flow">↻</button>
405
+ <!-- Overflow menu for mobile -->
406
+ <div class="ticket-overflow-menu">
407
+ <button class="ghost sm icon-btn" id="ticket-overflow-toggle" title="More actions">⋯</button>
408
+ <div class="ticket-overflow-dropdown hidden" id="ticket-overflow-dropdown">
409
+ <button class="ticket-overflow-item" id="ticket-overflow-new">+ New Ticket</button>
410
+ <button class="ticket-overflow-item" id="ticket-overflow-restart" style="display:none;">Restart</button>
411
+ <button class="ticket-overflow-item" id="ticket-overflow-archive" style="display:none;">Archive Flow</button>
412
+ </div>
413
+ </div>
414
+ <button class="ghost sm ticket-desktop-only" id="ticket-new-btn" title="Create new ticket">+ New Ticket</button>
554
415
  </div>
555
- </section>
556
-
557
- <section id="runs" class="panel">
558
- <div class="inline-toolbar runs-toolbar">
559
- <button id="runs-refresh" class="primary sm">Refresh</button>
560
- <label>
561
- Attribution
562
- <select id="runs-attribution-mode">
563
- <option value="split">Split (default)</option>
564
- <option value="full">Full (upper bound)</option>
565
- </select>
566
- </label>
567
- <label>
568
- TODO filter
569
- <input id="runs-todo-search" type="text" placeholder="Search TODOs" />
570
- </label>
416
+ <div class="ticket-flow-meta" id="ticket-flow-meta">
417
+ <button class="ticket-meta-toggle" id="ticket-meta-toggle" title="Toggle details">
418
+ <span class="ticket-meta-summary" id="ticket-meta-summary">–</span>
419
+ <span class="ticket-meta-arrow">▾</span>
420
+ </button>
421
+ <div class="ticket-meta-details" id="ticket-meta-details">
422
+ <div>
423
+ <span class="muted">Current ticket</span>
424
+ <span class="ticket-mono" id="ticket-flow-current">–</span>
425
+ </div>
426
+ <div>
427
+ <span class="muted">Turn</span>
428
+ <span class="ticket-mono" id="ticket-flow-turn">–</span>
429
+ </div>
430
+ <div>
431
+ <span class="muted">Elapsed</span>
432
+ <span class="ticket-mono" id="ticket-flow-elapsed">–</span>
433
+ </div>
434
+ <div>
435
+ <span class="muted">Progress</span>
436
+ <span class="ticket-mono" id="ticket-flow-progress">–</span>
437
+ </div>
438
+ <div>
439
+ <span class="muted">Reason</span>
440
+ <span class="ticket-mono ticket-flow-reason" id="ticket-flow-reason">–</span>
441
+ </div>
442
+ <div>
443
+ <span class="muted">Last activity</span>
444
+ <span class="ticket-mono" id="ticket-flow-last-activity">–</span>
445
+ </div>
446
+ </div>
571
447
  </div>
572
- <div class="runs-layout">
573
- <div class="runs-card">
574
- <div class="runs-card-header">
575
- <span class="label">Runs</span>
576
- </div>
577
- <table class="runs-table">
578
- <thead>
579
- <tr>
580
- <th>Run</th>
581
- <th>Status</th>
582
- <th>Started</th>
583
- <th>Model</th>
584
- <th>Tokens</th>
585
- <th>Completed TODOs</th>
586
- </tr>
587
- </thead>
588
- <tbody id="runs-table-body"></tbody>
589
- </table>
448
+ <!-- Live Agent Output Panel -->
449
+ <div class="ticket-live-output-panel" id="ticket-live-output-panel">
450
+ <div class="ticket-live-output-header">
451
+ <span class="ticket-live-output-title">Agent</span>
452
+ <span class="ticket-live-output-status" id="ticket-live-output-status">Disconnected</span>
453
+ <span class="ticket-live-output-spacer"></span>
454
+ <button class="ticket-live-output-view-toggle" id="ticket-live-output-view-toggle"
455
+ title="Show full output">⋯</button>
590
456
  </div>
591
- <div class="runs-card">
592
- <div class="runs-card-header runs-card-header-inline">
593
- <span class="label">Tokens per TODO</span>
594
- <span id="runs-todo-summary" class="muted small">–</span>
457
+ <pre class="ticket-live-output-compact" id="ticket-live-output-compact"></pre>
458
+ <div class="ticket-live-output-detail hidden" id="ticket-live-output-detail">
459
+ <div class="ticket-live-output-events hidden" id="ticket-live-output-events">
460
+ <div class="ticket-live-output-events-header">
461
+ <span class="muted">Events</span>
462
+ <span class="ticket-live-output-events-count" id="ticket-live-output-events-count">0</span>
463
+ </div>
464
+ <div class="ticket-chat-events-list" id="ticket-live-output-events-list"></div>
595
465
  </div>
596
- <div id="runs-todo-list" class="runs-todo-list">No TODOs yet.</div>
466
+ <pre class="ticket-live-output-text" id="ticket-live-output-text"></pre>
597
467
  </div>
598
468
  </div>
599
- </section>
600
-
601
- <section id="terminal" class="panel">
602
- <div class="terminal-toolbar">
603
- <div class="terminal-toolbar-row terminal-toolbar-main">
604
- <span id="terminal-status" class="terminal-status muted">Disconnected</span>
605
- <div class="terminal-actions">
606
- <button id="terminal-connect" class="primary sm">New</button>
607
- <button id="terminal-resume" class="ghost sm">Resume</button>
608
- <button id="terminal-disconnect" class="ghost sm">Disconnect</button>
469
+ <div class="ticket-flow-grid">
470
+ <div class="ticket-panel">
471
+ <div class="ticket-panel-header">
472
+ <span class="muted">Tickets</span>
473
+ <span class="muted small" id="ticket-flow-dir">–</span>
609
474
  </div>
475
+ <div class="ticket-list" id="ticket-flow-tickets">Loading tickets…</div>
610
476
  </div>
611
- <div class="terminal-toolbar-row terminal-toolbar-config">
612
- <div class="terminal-agent-controls">
613
- <select id="terminal-agent-select" title="Agent"></select>
614
- <select id="terminal-model-select" title="Model"></select>
615
- <select id="terminal-reasoning-select" title="Reasoning"></select>
616
- </div>
617
- <div class="terminal-toolbar-extras">
618
- <button
619
- id="terminal-text-input-toggle"
620
- class="ghost sm terminal-text-toggle"
621
- type="button"
622
- aria-controls="terminal-text-input"
623
- aria-expanded="false"
624
- title="Text input"
625
- >
626
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><line x1="7" y1="12" x2="17" y2="12"/><line x1="7" y1="8" x2="13" y2="8"/><line x1="7" y1="16" x2="15" y2="16"/></svg>
627
- <span class="terminal-text-toggle-label">Text</span>
477
+ <div class="ticket-panel" id="dispatch-panel">
478
+ <div class="ticket-panel-header">
479
+ <span class="muted">Dispatch history</span>
480
+ <span class="muted small" id="ticket-dispatch-note">–</span>
481
+ <button class="ticket-panel-toggle" id="dispatch-panel-toggle" aria-label="Toggle dispatch panel" title="Collapse/expand panel">
482
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
483
+ <path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7" />
484
+ </svg>
628
485
  </button>
629
- <div class="terminal-voice">
630
- <button id="terminal-voice" class="ghost sm voice-button" title="Hold to talk"></button>
631
- <span class="muted small hidden voice-status" id="terminal-voice-status"></span>
632
- </div>
633
486
  </div>
487
+ <div class="dispatch-mini-list" id="dispatch-mini-list"></div>
488
+ <div class="ticket-list" id="ticket-dispatch-history">No dispatches yet. Agent messages will appear here.</div>
634
489
  </div>
635
490
  </div>
636
- <div id="terminal-container" class="terminal-container">
637
- <div class="terminal-overlay" id="terminal-overlay">
638
- <p class="muted">Press New or Resume to launch the agent TUI</p>
491
+ </div>
492
+ <!-- Ticket Editor Modal (Full Screen) -->
493
+ <div class="modal-overlay hidden" id="ticket-editor-modal">
494
+ <div class="modal-content ticket-editor-modal">
495
+ <div class="modal-header ticket-editor-header">
496
+ <div class="ticket-header-row">
497
+ <select class="ticket-fm-select" id="ticket-fm-agent" title="Agent">
498
+ <option value="codex">codex</option>
499
+ <option value="opencode">opencode</option>
500
+ <option value="user">user</option>
501
+ </select>
502
+ <select class="ticket-fm-select" id="ticket-fm-model" title="Model"></select>
503
+ <select class="ticket-fm-select" id="ticket-fm-reasoning" title="Reasoning"></select>
504
+ <input class="ticket-fm-input" id="ticket-fm-title" placeholder="Title (optional)" spellcheck="false"
505
+ type="text">
506
+ <div class="ticket-header-actions">
507
+ <label class="ticket-fm-toggle" title="Mark as done">
508
+ <input id="ticket-fm-done" type="checkbox">
509
+ <span class="ticket-fm-toggle-label">Done</span>
510
+ </label>
511
+ <button class="ghost sm icon-btn" id="ticket-editor-close" title="Close">×</button>
512
+ </div>
513
+ </div>
639
514
  </div>
640
- <button id="terminal-jump-bottom" class="terminal-jump-btn hidden" title="Jump to latest">
641
- Latest
642
- </button>
643
- </div>
644
- <!-- Mobile control bar - touch-friendly special keys (above text input) -->
645
- <div id="terminal-mobile-controls" class="terminal-mobile-controls">
646
- <div class="tmb-row">
647
- <button class="tmb-key tmb-mod" data-key="ctrl" id="tmb-ctrl">Ctrl</button>
648
- <button class="tmb-key tmb-mod" data-key="alt" id="tmb-alt">Alt</button>
649
- <button class="tmb-key" data-seq="&#x1b;">Esc</button>
650
- <button class="tmb-key" data-seq="&#x09;">Tab</button>
651
- <button class="tmb-key tmb-primary" data-seq="&#x0d;">Enter</button>
515
+ <div class="ticket-editor-error hidden" id="ticket-editor-error"></div>
516
+ <div class="ticket-editor-main">
517
+ <!--
518
+ MUTUALLY EXCLUSIVE VIEWS:
519
+ The toolbar + textarea (content editor) and the patch-main (pending changes preview)
520
+ should NEVER be shown at the same time. When there's a pending draft from AI chat,
521
+ only show the patch preview. When there's no pending draft, only show the content editor.
522
+ See renderTicketChat() in ticketChatActions.ts for the toggle logic.
523
+ -->
524
+ <!-- Body Editor (hidden when patch preview is visible) -->
525
+ <div class="ticket-editor-toolbar" id="ticket-editor-toolbar">
526
+ <button class="ghost sm" id="ticket-insert-checkbox" title="Insert checkbox">+ Checkbox</button>
527
+ <button class="ghost sm" id="ticket-undo-btn" title="Undo changes" disabled>Undo</button>
528
+ <button class="danger sm hidden" id="ticket-editor-delete" title="Delete ticket">Delete</button>
529
+ <span class="ticket-autosave-status muted small" id="ticket-autosave-status"></span>
530
+ </div>
531
+ <textarea id="ticket-editor-content" class="ticket-editor-textarea" spellcheck="false"
532
+ placeholder="Describe the task details here..."></textarea>
533
+ <!-- Patch Preview (hidden when content editor is visible) -->
534
+ <div class="ticket-patch-main hidden" id="ticket-patch-main">
535
+ <div class="ticket-patch-header">
536
+ <span class="ticket-patch-title">Pending Changes</span>
537
+ <span class="ticket-patch-status muted" id="ticket-patch-status"></span>
538
+ </div>
539
+ <div class="ticket-patch-body" id="ticket-patch-body"></div>
540
+ <div class="ticket-patch-actions">
541
+ <button class="primary sm" id="ticket-patch-apply">Apply</button>
542
+ <button class="ghost sm" id="ticket-patch-discard">Discard</button>
543
+ </div>
544
+ </div>
545
+ <!-- Chat Panel (matches Docs chat) -->
546
+ <div class="ticket-chat-panel">
547
+ <div class="ticket-chat-compose">
548
+ <div class="ticket-chat-agent-controls">
549
+ <select id="ticket-chat-agent-select" title="Agent"></select>
550
+ <select id="ticket-chat-model-select" title="Model"></select>
551
+ <select id="ticket-chat-reasoning-select" title="Reasoning"></select>
552
+ </div>
553
+ <div class="ticket-chat-input-row">
554
+ <textarea id="ticket-chat-input" class="ticket-chat-input" enterkeyhint="enter"
555
+ placeholder="Ask AI to edit this ticket..." rows="1" spellcheck="false"></textarea>
556
+ <div class="ticket-chat-input-buttons">
557
+ <button class="ghost sm voice-button" id="ticket-chat-voice" title="Hold to talk"></button>
558
+ <button class="primary sm" id="ticket-chat-send" title="Send">↑</button>
559
+ </div>
560
+ </div>
561
+ <div class="ticket-chat-meta">
562
+ <div class="ticket-chat-meta-left">
563
+ <span class="muted small ticket-chat-hint" id="ticket-chat-hint">Cmd+Enter to send · Enter for
564
+ newline</span>
565
+ <span class="muted small hidden ticket-chat-voice-status" id="ticket-chat-voice-status"></span>
566
+ </div>
567
+ <div class="ticket-chat-meta-right">
568
+ <button class="ghost sm hidden ticket-chat-cancel-inline" id="ticket-chat-cancel"
569
+ title="Cancel">✕</button>
570
+ <button class="ghost sm" id="ticket-chat-new-thread" title="Start a new chat thread">New
571
+ thread</button>
572
+ <span class="ticket-chat-status" id="ticket-chat-status">idle</span>
573
+ </div>
574
+ </div>
575
+ </div>
576
+ <!-- Rich Chat Stream: shows message history and agent events -->
577
+ <div class="ticket-chat-stream" id="ticket-chat-stream">
578
+ <!-- Messages History (user prompts and assistant responses) -->
579
+ <div class="ticket-chat-messages" id="ticket-chat-messages"></div>
580
+ <!-- Agent Activity Events (thinking, tool calls, etc.) - shown during processing -->
581
+ <div class="ticket-chat-events hidden" id="ticket-chat-events">
582
+ <div class="ticket-chat-events-list" id="ticket-chat-events-list"></div>
583
+ </div>
584
+ <!-- Hidden elements for event tracking -->
585
+ <span class="hidden" id="ticket-chat-events-count">0</span>
586
+ <button class="ghost sm hidden" id="ticket-chat-events-toggle">Show more</button>
587
+ </div>
588
+ </div>
652
589
  </div>
653
- <div class="tmb-row">
654
- <button class="tmb-key tmb-ctrl-combo" data-ctrl="c">^C</button>
655
- <button class="tmb-key tmb-ctrl-combo" data-ctrl="d">^D</button>
656
- <button class="tmb-key tmb-ctrl-combo" data-ctrl="z">^Z</button>
657
- <button class="tmb-key tmb-bksp" data-seq="&#x7f;">Bksp</button>
658
- <button class="tmb-key tmb-arrow" data-seq="&#x1b;[D">←</button>
659
- <button class="tmb-key tmb-arrow" data-seq="&#x1b;[A">↑</button>
660
- <button class="tmb-key tmb-arrow" data-seq="&#x1b;[B">↓</button>
661
- <button class="tmb-key tmb-arrow" data-seq="&#x1b;[C">→</button>
590
+ </div>
591
+ </div>
592
+ </section>
593
+ <section class="panel" id="terminal">
594
+ <div class="terminal-toolbar">
595
+ <div class="terminal-toolbar-row terminal-toolbar-main">
596
+ <span class="terminal-status muted" id="terminal-status">Disconnected</span>
597
+ <div class="terminal-actions">
598
+ <button class="primary sm" id="terminal-connect">New</button>
599
+ <button class="ghost sm" id="terminal-resume">Resume</button>
600
+ <button class="ghost sm" id="terminal-disconnect">Disconnect</button>
662
601
  </div>
663
602
  </div>
664
- <div id="terminal-text-input" class="terminal-text-input compose-panel hidden" aria-hidden="true">
665
- <label class="terminal-text-input-title" for="terminal-textarea">Text input</label>
666
- <div class="terminal-text-input-row compose-row">
667
- <textarea
668
- id="terminal-textarea"
669
- rows="2"
670
- autocomplete="off"
671
- autocapitalize="off"
672
- spellcheck="false"
673
- enterkeyhint="enter"
674
- placeholder="Type or paste text/images to send to the terminal…"
675
- ></textarea>
676
- <div class="terminal-text-input-buttons compose-buttons">
677
- <button
678
- id="terminal-text-image"
679
- class="ghost sm terminal-text-image"
680
- type="button"
681
- title="Attach image"
682
- aria-label="Attach image"
683
- >Img</button>
684
- <input
685
- id="terminal-text-image-input"
686
- class="hidden"
687
- type="file"
688
- accept="image/*"
689
- />
690
- <button
691
- id="terminal-text-voice"
692
- class="ghost sm voice-button terminal-text-voice"
693
- type="button"
694
- title="Hold to talk"
695
- data-voice-mode="waveform"
696
- ></button>
697
- <button
698
- id="terminal-text-send"
699
- class="primary terminal-text-send-icon"
700
- type="button"
701
- aria-label="Send"
702
- >→</button>
603
+ <div class="terminal-toolbar-row terminal-toolbar-config">
604
+ <div class="terminal-agent-controls">
605
+ <select id="terminal-agent-select" title="Agent"></select>
606
+ <select id="terminal-model-select" title="Model"></select>
607
+ <select id="terminal-reasoning-select" title="Reasoning"></select>
608
+ </div>
609
+ <div class="terminal-toolbar-extras">
610
+ <button aria-controls="terminal-text-input" aria-expanded="false" class="ghost sm terminal-text-toggle"
611
+ id="terminal-text-input-toggle" title="Text input" type="button">
612
+ <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
613
+ viewbox="0 0 24 24">
614
+ <rect height="18" rx="2" width="18" x="3" y="3"></rect>
615
+ <line x1="7" x2="17" y1="12" y2="12"></line>
616
+ <line x1="7" x2="13" y1="8" y2="8"></line>
617
+ <line x1="7" x2="15" y1="16" y2="16"></line>
618
+ </svg>
619
+ <span class="terminal-text-toggle-label">Text</span>
620
+ </button>
621
+ <div class="terminal-voice">
622
+ <button class="ghost sm voice-button" id="terminal-voice" title="Hold to talk"></button>
623
+ <span class="muted small hidden voice-status" id="terminal-voice-status"></span>
703
624
  </div>
704
625
  </div>
705
626
  </div>
706
- </section>
707
- </main>
708
- </div>
709
- <div id="toast" class="toast"></div>
710
-
711
- <!-- Confirmation Modal -->
712
- <div id="confirm-modal" class="modal-overlay" hidden>
713
- <div
714
- class="modal-dialog"
715
- role="dialog"
716
- aria-modal="true"
717
- aria-labelledby="confirm-modal-title"
718
- aria-describedby="confirm-modal-message"
719
- tabindex="-1"
720
- >
721
- <span id="confirm-modal-title" class="sr-only">Confirmation</span>
722
- <p id="confirm-modal-message"></p>
723
- <div class="modal-actions">
724
- <button id="confirm-modal-cancel" class="ghost">Cancel</button>
725
- <button id="confirm-modal-ok" class="danger">Confirm</button>
726
627
  </div>
727
- </div>
728
- </div>
729
-
730
- <!-- Input Modal -->
731
- <div id="input-modal" class="modal-overlay" hidden>
732
- <div
733
- class="modal-dialog modal-input"
734
- role="dialog"
735
- aria-modal="true"
736
- aria-labelledby="input-modal-title"
737
- aria-describedby="input-modal-message"
738
- tabindex="-1"
739
- >
740
- <span id="input-modal-title" class="sr-only">Input</span>
741
- <p id="input-modal-message"></p>
742
- <input type="text" id="input-modal-input" autocomplete="off" spellcheck="false" />
743
- <div class="modal-actions">
744
- <button id="input-modal-cancel" class="ghost">Cancel</button>
745
- <button id="input-modal-ok" class="primary">OK</button>
628
+ <div class="terminal-container" id="terminal-container">
629
+ <div class="terminal-overlay" id="terminal-overlay">
630
+ <p>Click <strong>New</strong> to start a fresh agent session, or <strong>Resume</strong> to continue an
631
+ existing one.</p>
632
+ <p class="terminal-overlay-hint">Use the agent dropdown above to switch between different agents.</p>
633
+ </div>
634
+ <button class="terminal-jump-btn hidden" id="terminal-jump-bottom" title="Jump to latest">
635
+ ↓ Latest
636
+ </button>
746
637
  </div>
747
- </div>
748
- </div>
749
-
750
- <!-- Ingest Spec Modal -->
751
- <div id="ingest-modal" class="modal-overlay" hidden>
752
- <div
753
- class="modal-dialog modal-ingest"
754
- role="dialog"
755
- aria-modal="true"
756
- aria-labelledby="ingest-modal-title"
757
- aria-describedby="ingest-modal-message"
758
- tabindex="-1"
759
- >
760
- <span id="ingest-modal-title" class="sr-only">Ingest Spec</span>
761
- <div id="ingest-modal-content">
762
- <p id="ingest-modal-message">Ready to ingest SPEC into TODO, PROGRESS, and OPINIONS?</p>
763
- <div id="ingest-modal-refinement" class="ingest-modal-refinement hidden">
764
- <textarea
765
- id="ingest-modal-input"
766
- rows="3"
767
- placeholder="Refine the ingest (optional)..."
768
- spellcheck="false"
769
- ></textarea>
638
+ <!-- Mobile control bar - touch-friendly special keys (above text input) -->
639
+ <div class="terminal-mobile-controls" id="terminal-mobile-controls">
640
+ <div class="tmb-row">
641
+ <button class="tmb-key tmb-mod" data-key="ctrl" id="tmb-ctrl">Ctrl</button>
642
+ <button class="tmb-key tmb-mod" data-key="alt" id="tmb-alt">Alt</button>
643
+ <button class="tmb-key" data-seq="">Esc</button>
644
+ <button class="tmb-key" data-seq=" ">Tab</button>
645
+ <button class="tmb-key tmb-primary" data-seq="
646
+ ">Enter</button>
647
+ </div>
648
+ <div class="tmb-row">
649
+ <button class="tmb-key tmb-ctrl-combo" data-ctrl="c">^C</button>
650
+ <button class="tmb-key tmb-ctrl-combo" data-ctrl="d">^D</button>
651
+ <button class="tmb-key tmb-ctrl-combo" data-ctrl="z">^Z</button>
652
+ <button class="tmb-key tmb-bksp" data-seq="">Bksp</button>
653
+ <button class="tmb-key tmb-arrow" data-seq="[D">←</button>
654
+ <button class="tmb-key tmb-arrow" data-seq="[A">↑</button>
655
+ <button class="tmb-key tmb-arrow" data-seq="[B">↓</button>
656
+ <button class="tmb-key tmb-arrow" data-seq="[C">→</button>
770
657
  </div>
771
658
  </div>
772
- <div class="modal-actions">
773
- <button id="ingest-modal-cancel" class="ghost">Cancel</button>
774
- <button id="ingest-modal-ok" class="primary">Ingest</button>
659
+ <div aria-hidden="true" class="terminal-text-input compose-panel hidden" id="terminal-text-input">
660
+ <label class="terminal-text-input-title" for="terminal-textarea">Text input</label>
661
+ <div class="terminal-text-input-row compose-row">
662
+ <textarea autocapitalize="off" autocomplete="off" enterkeyhint="enter" id="terminal-textarea"
663
+ placeholder="Type or paste text/images to send to the terminal…" rows="2" spellcheck="false"></textarea>
664
+ <div class="terminal-text-input-buttons compose-buttons">
665
+ <button aria-label="Attach image" class="ghost sm terminal-text-image" id="terminal-text-image"
666
+ title="Attach image" type="button">Img</button>
667
+ <input accept="image/*" class="hidden" id="terminal-text-image-input" type="file" />
668
+ <button class="ghost sm voice-button terminal-text-voice" data-voice-mode="waveform"
669
+ id="terminal-text-voice" title="Hold to talk" type="button"></button>
670
+ <button aria-label="Send" class="primary terminal-text-send-icon" id="terminal-text-send"
671
+ type="button">→</button>
672
+ </div>
673
+ </div>
775
674
  </div>
675
+ </section>
676
+ </main>
677
+ </div>
678
+ <div class="toast" id="toast"></div>
679
+ <!-- Confirmation Modal -->
680
+ <div class="modal-overlay" hidden="" id="confirm-modal">
681
+ <div aria-describedby="confirm-modal-message" aria-labelledby="confirm-modal-title" aria-modal="true"
682
+ class="modal-dialog" role="dialog" tabindex="-1">
683
+ <span class="sr-only" id="confirm-modal-title">Confirmation</span>
684
+ <p id="confirm-modal-message"></p>
685
+ <div class="modal-actions">
686
+ <button class="ghost" id="confirm-modal-cancel">Cancel</button>
687
+ <button class="danger" id="confirm-modal-ok">Confirm</button>
688
+ </div>
689
+ </div>
690
+ </div>
691
+ <!-- Input Modal -->
692
+ <div class="modal-overlay" hidden="" id="input-modal">
693
+ <div aria-describedby="input-modal-message" aria-labelledby="input-modal-title" aria-modal="true"
694
+ class="modal-dialog modal-input" role="dialog" tabindex="-1">
695
+ <span class="sr-only" id="input-modal-title">Input</span>
696
+ <p id="input-modal-message"></p>
697
+ <input autocomplete="off" id="input-modal-input" spellcheck="false" type="text" />
698
+ <div class="modal-actions">
699
+ <button class="ghost" id="input-modal-cancel">Cancel</button>
700
+ <button class="primary" id="input-modal-ok">OK</button>
776
701
  </div>
777
702
  </div>
778
-
779
- <!-- Create Repo Modal -->
780
- <div id="create-repo-modal" class="modal-overlay" hidden>
781
- <div
782
- class="modal-dialog modal-create-repo"
783
- role="dialog"
784
- aria-modal="true"
785
- aria-labelledby="create-repo-modal-title"
786
- aria-describedby="create-repo-modal-body"
787
- tabindex="-1"
788
- >
789
- <div class="modal-header">
790
- <span class="label" id="create-repo-modal-title">Create New Repository</span>
703
+ </div>
704
+ <!-- Create Repo Modal -->
705
+ <div class="modal-overlay" hidden="" id="create-repo-modal">
706
+ <div aria-describedby="create-repo-modal-body" aria-labelledby="create-repo-modal-title" aria-modal="true"
707
+ class="modal-dialog modal-create-repo" role="dialog" tabindex="-1">
708
+ <div class="modal-header">
709
+ <span class="label" id="create-repo-modal-title">Create New Repository</span>
710
+ </div>
711
+ <div class="modal-body" id="create-repo-modal-body">
712
+ <div class="form-group">
713
+ <label for="create-repo-id">Repo ID <span class="required">*</span></label>
714
+ <input autocomplete="off" id="create-repo-id" placeholder="my-project" spellcheck="false" type="text" />
715
+ <span class="form-hint">Used as directory name if path not specified</span>
791
716
  </div>
792
- <div class="modal-body" id="create-repo-modal-body">
793
- <div class="form-group">
794
- <label for="create-repo-id">Repo ID <span class="required">*</span></label>
795
- <input type="text" id="create-repo-id" placeholder="my-project" autocomplete="off" spellcheck="false" />
796
- <span class="form-hint">Used as directory name if path not specified</span>
797
- </div>
798
- <div class="form-group">
799
- <label for="create-repo-path">Path <span class="optional">(optional)</span></label>
800
- <input type="text" id="create-repo-path" placeholder="relative/path/to/repo" autocomplete="off" spellcheck="false" />
801
- <span class="form-hint">Leave empty to use repo ID as path</span>
802
- </div>
803
- <div class="form-group">
804
- <label for="create-repo-url">Git URL <span class="optional">(optional)</span></label>
805
- <input type="text" id="create-repo-url" placeholder="https://github.com/org/repo.git" autocomplete="off" spellcheck="false" />
806
- <span class="form-hint">If provided, the repo will be cloned automatically</span>
807
- </div>
808
- <div class="form-group form-checkbox">
809
- <label>
810
- <input type="checkbox" id="create-repo-git" checked />
811
- <span>Initialize git repository</span>
812
- </label>
813
- </div>
717
+ <div class="form-group">
718
+ <label for="create-repo-path">Path <span class="optional">(optional)</span></label>
719
+ <input autocomplete="off" id="create-repo-path" placeholder="relative/path/to/repo" spellcheck="false"
720
+ type="text" />
721
+ <span class="form-hint">Leave empty to use repo ID as path</span>
722
+ </div>
723
+ <div class="form-group">
724
+ <label for="create-repo-url">Git URL <span class="optional">(optional)</span></label>
725
+ <input autocomplete="off" id="create-repo-url" placeholder="https://github.com/org/repo.git"
726
+ spellcheck="false" type="text" />
727
+ <span class="form-hint">If provided, the repo will be cloned automatically</span>
814
728
  </div>
815
- <div class="modal-actions">
816
- <button id="create-repo-cancel" class="ghost">Cancel</button>
817
- <button id="create-repo-submit" class="primary">Create</button>
729
+ <div class="form-group form-checkbox">
730
+ <label>
731
+ <input checked="" id="create-repo-git" type="checkbox" />
732
+ <span>Initialize git repository</span>
733
+ </label>
818
734
  </div>
819
735
  </div>
736
+ <div class="modal-actions">
737
+ <button class="ghost" id="create-repo-cancel">Cancel</button>
738
+ <button class="primary" id="create-repo-submit">Create</button>
739
+ </div>
820
740
  </div>
821
-
822
- <!-- Hub Settings Modal -->
823
- <div id="hub-settings-modal" class="modal-overlay" hidden>
824
- <div
825
- class="modal-dialog"
826
- role="dialog"
827
- aria-modal="true"
828
- aria-labelledby="hub-settings-modal-title"
829
- aria-describedby="hub-settings-modal-body"
830
- tabindex="-1"
831
- >
832
- <div class="modal-header">
833
- <span class="label" id="hub-settings-modal-title">Hub Settings</span>
834
- </div>
835
- <div class="modal-body" id="hub-settings-modal-body">
836
- <p class="muted small">System-wide settings for Codex Autorunner.</p>
837
- <div class="form-group">
838
- <label>System Update</label>
839
- <select id="hub-update-target">
840
- <option value="both">Web + Telegram</option>
841
- <option value="web">Web only</option>
842
- <option value="telegram">Telegram only</option>
843
- </select>
844
- <button id="hub-update-btn" class="primary sm">Update CAR</button>
845
- <span class="form-hint">Pull latest code and restart selected services</span>
846
- </div>
847
- </div>
848
- <div class="modal-actions">
849
- <button id="hub-settings-close" class="ghost">Close</button>
741
+ </div>
742
+ <!-- Hub Settings Modal -->
743
+ <div class="modal-overlay" hidden="" id="hub-settings-modal">
744
+ <div aria-describedby="hub-settings-modal-body" aria-labelledby="hub-settings-modal-title" aria-modal="true"
745
+ class="modal-dialog" role="dialog" tabindex="-1">
746
+ <div class="modal-header">
747
+ <span class="label" id="hub-settings-modal-title">Hub Settings</span>
748
+ </div>
749
+ <div class="modal-body" id="hub-settings-modal-body">
750
+ <p class="muted small">System-wide settings for Codex Autorunner.</p>
751
+ <div class="form-group">
752
+ <label>System Update</label>
753
+ <select id="hub-update-target">
754
+ <option value="both">Web + Telegram</option>
755
+ <option value="web">Web only</option>
756
+ <option value="telegram">Telegram only</option>
757
+ </select>
758
+ <button class="primary sm" id="hub-update-btn">Update CAR</button>
759
+ <span class="form-hint">Pull latest code and restart selected services</span>
850
760
  </div>
851
761
  </div>
762
+ <div class="modal-actions">
763
+ <button class="ghost" id="hub-settings-close">Close</button>
764
+ </div>
852
765
  </div>
853
-
854
- <!-- Repo Settings Modal -->
855
- <div id="repo-settings-modal" class="modal-overlay" hidden>
856
- <div
857
- class="modal-dialog"
858
- role="dialog"
859
- aria-modal="true"
860
- aria-labelledby="repo-settings-modal-title"
861
- aria-describedby="repo-settings-modal-body"
862
- tabindex="-1"
863
- >
864
- <div class="modal-header">
865
- <span class="label" id="repo-settings-modal-title">Repo Settings</span>
766
+ </div>
767
+ <!-- Repo Settings Modal -->
768
+ <div class="modal-overlay" hidden="" id="repo-settings-modal">
769
+ <div aria-describedby="repo-settings-modal-body" aria-labelledby="repo-settings-modal-title" aria-modal="true"
770
+ class="modal-dialog" role="dialog" tabindex="-1">
771
+ <div class="modal-header">
772
+ <span class="label" id="repo-settings-modal-title">Repo Settings</span>
773
+ </div>
774
+ <div class="modal-body" id="repo-settings-modal-body">
775
+ <p class="muted small">Settings for the current repository session.</p>
776
+ <div class="form-group">
777
+ <label>System Update</label>
778
+ <select id="repo-update-target">
779
+ <option value="both">Web + Telegram</option>
780
+ <option value="web">Web only</option>
781
+ <option value="telegram">Telegram only</option>
782
+ </select>
783
+ <button class="primary sm" id="repo-update-btn">Update CAR</button>
784
+ <span class="form-hint">Pull latest code and restart selected services</span>
866
785
  </div>
867
- <div class="modal-body" id="repo-settings-modal-body">
868
- <p class="muted small">Settings for the current repository session.</p>
869
- <div class="form-group">
870
- <label>System Update</label>
871
- <select id="repo-update-target">
872
- <option value="both">Web + Telegram</option>
873
- <option value="web">Web only</option>
874
- <option value="telegram">Telegram only</option>
875
- </select>
876
- <button id="repo-update-btn" class="primary sm">Update CAR</button>
877
- <span class="form-hint">Pull latest code and restart selected services</span>
878
- </div>
879
- <div class="form-group">
880
- <label>Autorunner Settings</label>
881
- <div class="settings-grid">
882
- <div>
883
- <label for="autorunner-model-select" class="muted small">Model</label>
884
- <select id="autorunner-model-select"></select>
885
- </div>
886
- <div>
887
- <label for="autorunner-effort-select" class="muted small">Reasoning effort</label>
888
- <select id="autorunner-effort-select"></select>
889
- </div>
890
- <div>
891
- <label for="autorunner-approval-select" class="muted small">Approval policy</label>
892
- <select id="autorunner-approval-select"></select>
893
- </div>
894
- <div>
895
- <label for="autorunner-sandbox-select" class="muted small">Sandbox</label>
896
- <select id="autorunner-sandbox-select"></select>
897
- </div>
898
- <div>
899
- <label for="autorunner-max-runs-input" class="muted small">Max runs</label>
900
- <input id="autorunner-max-runs-input" type="number" min="1" step="1" placeholder="Unlimited" />
901
- <span class="form-hint">Maximum number of autorunner cycles (empty = unlimited)</span>
902
- </div>
903
- </div>
904
- <div id="autorunner-network-row" class="settings-toggle-row">
905
- <label class="form-checkbox">
906
- <input id="autorunner-network-toggle" type="checkbox" />
907
- <span>Allow network access in workspace-write mode</span>
908
- </label>
786
+ <div class="form-group">
787
+ <label>Autorunner Settings</label>
788
+ <div class="settings-grid">
789
+ <div>
790
+ <label class="muted small" for="autorunner-model-select">Model</label>
791
+ <select id="autorunner-model-select"></select>
909
792
  </div>
910
- <div class="settings-actions">
911
- <button id="autorunner-settings-save" class="primary sm">Save settings</button>
912
- <button id="autorunner-settings-reload" class="ghost sm">Reload</button>
793
+ <div>
794
+ <label class="muted small" for="autorunner-effort-select">Reasoning effort</label>
795
+ <select id="autorunner-effort-select"></select>
913
796
  </div>
914
- <span id="autorunner-settings-warning" class="form-hint warning">Changing these settings starts a new autorunner conversation.</span>
915
- </div>
916
- <div class="form-group">
917
- <label>Thread Tools</label>
918
- <div id="thread-tools-list" class="thread-tools-list"></div>
919
- <div class="thread-tools-actions">
920
- <button id="thread-new-autorunner" class="ghost sm">New autorunner thread</button>
921
- <button id="thread-archive-autorunner" class="ghost sm">Archive autorunner thread</button>
922
- <button id="thread-reset-all" class="danger sm">Reset all conversations</button>
923
- <button id="thread-backup-download" class="ghost sm">Download backup</button>
797
+ <div>
798
+ <label class="muted small" for="autorunner-approval-select">Approval policy</label>
799
+ <select id="autorunner-approval-select"></select>
924
800
  </div>
925
- <span class="form-hint">Resetting conversations clears stored thread IDs and restarts chats.</span>
926
- </div>
927
- </div>
928
- <div class="modal-actions">
929
- <button id="repo-settings-close" class="ghost">Close</button>
930
- </div>
931
- </div>
932
- </div>
933
-
934
- <div id="run-details-modal" class="modal-overlay" hidden>
935
- <div
936
- class="modal-dialog run-details-modal"
937
- role="dialog"
938
- aria-modal="true"
939
- aria-labelledby="run-details-title"
940
- aria-describedby="run-details-meta"
941
- tabindex="-1"
942
- >
943
- <div class="modal-header">
944
- <span class="label" id="run-details-title">Run</span>
945
- </div>
946
- <div class="modal-body">
947
- <div id="run-details-meta" class="muted small">–</div>
948
- <div class="run-details-grid">
949
- <div class="run-details-section">
950
- <div class="run-details-title">Completed TODOs</div>
951
- <div id="run-details-todos" class="run-details-list">–</div>
801
+ <div>
802
+ <label class="muted small" for="autorunner-sandbox-select">Sandbox</label>
803
+ <select id="autorunner-sandbox-select"></select>
952
804
  </div>
953
- <div class="run-details-section">
954
- <div class="run-details-title">Token breakdown</div>
955
- <div id="run-details-tokens" class="run-details-list">–</div>
805
+ <div>
806
+ <label class="muted small" for="autorunner-max-runs-input">Max runs</label>
807
+ <input id="autorunner-max-runs-input" min="1" placeholder="Unlimited" step="1" type="number" />
808
+ <span class="form-hint">Maximum number of autorunner cycles (empty = unlimited)</span>
956
809
  </div>
957
810
  </div>
958
- <div class="run-details-section">
959
- <div class="run-details-title">Plan</div>
960
- <pre id="run-details-plan" class="run-details-artifact">–</pre>
811
+ <div class="settings-toggle-row" id="autorunner-network-row">
812
+ <label class="form-checkbox">
813
+ <input id="autorunner-network-toggle" type="checkbox" />
814
+ <span>Allow network access in workspace-write mode</span>
815
+ </label>
961
816
  </div>
962
- <div class="run-details-section">
963
- <div class="run-details-title">Diff</div>
964
- <pre id="run-details-diff" class="run-details-artifact">–</pre>
817
+ <div class="settings-actions">
818
+ <button class="primary sm" id="autorunner-settings-save">Save settings</button>
819
+ <button class="ghost sm" id="autorunner-settings-reload">Reload</button>
965
820
  </div>
966
- <div class="run-details-section">
967
- <div class="run-details-title">Final output</div>
968
- <pre id="run-details-output" class="run-details-artifact">–</pre>
821
+ <span class="form-hint warning" id="autorunner-settings-warning">Changing these settings starts a new
822
+ autorunner conversation.</span>
823
+ </div>
824
+ <div class="form-group">
825
+ <label>Thread Tools</label>
826
+ <div class="thread-tools-list" id="thread-tools-list"></div>
827
+ <div class="thread-tools-actions">
828
+ <button class="ghost sm" id="thread-new-autorunner">New autorunner thread</button>
829
+ <button class="ghost sm" id="thread-archive-autorunner">Archive autorunner thread</button>
830
+ <button class="danger sm" id="thread-reset-all">Reset all conversations</button>
831
+ <button class="ghost sm" id="thread-backup-download">Download backup</button>
969
832
  </div>
833
+ <span class="form-hint">Resetting conversations clears stored thread IDs and restarts chats.</span>
834
+ </div>
835
+ </div>
836
+ <div class="modal-actions">
837
+ <button class="ghost" id="repo-settings-close">Close</button>
838
+ </div>
839
+ </div>
840
+ </div>
841
+ <!-- Reason Details Modal -->
842
+ <div class="modal-overlay" hidden="" id="reason-modal">
843
+ <div aria-describedby="reason-modal-content" aria-labelledby="reason-modal-title" aria-modal="true"
844
+ class="modal-dialog reason-modal-dialog" role="dialog" tabindex="-1">
845
+ <h3 class="reason-modal-title" id="reason-modal-title">Status Details</h3>
846
+ <pre class="reason-modal-content" id="reason-modal-content"></pre>
847
+ <div class="modal-actions">
848
+ <button class="ghost" id="reason-modal-close">Close</button>
849
+ </div>
850
+ </div>
851
+ </div>
852
+ <!-- File Picker Modal -->
853
+ <div class="modal-overlay file-picker-modal" hidden="" id="file-picker-modal">
854
+ <div aria-labelledby="file-picker-modal-title" aria-modal="true"
855
+ class="modal-dialog file-picker-dialog" role="dialog" tabindex="-1">
856
+ <div class="file-picker-header">
857
+ <span class="file-picker-title" id="file-picker-modal-title">Select File</span>
858
+ <button class="file-picker-close" id="file-picker-close" aria-label="Close">&times;</button>
859
+ </div>
860
+ <div class="file-picker-body" id="file-picker-body">
861
+ <!-- File list rendered here by JS -->
862
+ </div>
863
+ </div>
864
+ </div>
865
+ <!-- Workspace Create Modal -->
866
+ <div class="modal-overlay" hidden="" id="workspace-create-modal">
867
+ <div aria-describedby="workspace-create-body" aria-labelledby="workspace-create-title" aria-modal="true"
868
+ class="modal-dialog workspace-create-dialog" role="dialog" tabindex="-1">
869
+ <div class="modal-header">
870
+ <span class="label" id="workspace-create-title">Create</span>
871
+ <button class="file-picker-close" id="workspace-create-close" aria-label="Close">&times;</button>
872
+ </div>
873
+ <div class="modal-body" id="workspace-create-body">
874
+ <div class="form-group">
875
+ <label class="muted small" for="workspace-create-name">Name</label>
876
+ <input id="workspace-create-name" placeholder="my-note.md" type="text" />
877
+ <span class="form-hint" id="workspace-create-hint">Created under current folder</span>
970
878
  </div>
971
- <div class="modal-actions run-details-actions">
972
- <a id="run-details-log" class="ghost sm" target="_blank" rel="noreferrer">Open log</a>
973
- <button id="run-details-close" class="ghost">Close</button>
879
+ <div class="form-group">
880
+ <label class="muted small" for="workspace-create-path">Location</label>
881
+ <select id="workspace-create-path"></select>
974
882
  </div>
975
883
  </div>
884
+ <div class="modal-actions workspace-create-actions">
885
+ <button class="ghost sm" id="workspace-create-cancel">Cancel</button>
886
+ <button class="primary sm" id="workspace-create-submit">Create</button>
887
+ </div>
976
888
  </div>
977
-
978
- <script src="static/loader.js?v=__CAR_ASSET_VERSION__" data-car-loader></script>
979
- </body>
889
+ </div>
890
+ <!-- Workspace Confirm Modal -->
891
+ <div class="modal-overlay" hidden="" id="workspace-confirm-modal">
892
+ <div aria-describedby="workspace-confirm-body" aria-labelledby="workspace-confirm-title" aria-modal="true"
893
+ class="modal-dialog workspace-confirm-dialog" role="dialog" tabindex="-1">
894
+ <div class="modal-header">
895
+ <span class="label" id="workspace-confirm-title">Confirm</span>
896
+ </div>
897
+ <div class="modal-body" id="workspace-confirm-body">
898
+ <p id="workspace-confirm-text"></p>
899
+ </div>
900
+ <div class="modal-actions workspace-confirm-actions">
901
+ <button class="ghost sm" id="workspace-confirm-cancel">Cancel</button>
902
+ <button class="primary sm" id="workspace-confirm-yes">Confirm</button>
903
+ </div>
904
+ </div>
905
+ </div>
906
+ <script data-car-loader="" src="static/loader.js?v=__CAR_ASSET_VERSION__"></script>
907
+ </body>
908
+
980
909
  </html>