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
@@ -3,119 +3,31 @@ from __future__ import annotations
3
3
  from pathlib import Path
4
4
  from typing import Callable, Optional
5
5
 
6
- from .config import (
7
- AppServerAutorunnerPromptConfig,
8
- AppServerDocChatPromptConfig,
9
- AppServerSpecIngestPromptConfig,
10
- Config,
11
- )
6
+ from .config import AppServerAutorunnerPromptConfig, Config
12
7
 
13
8
  TRUNCATION_MARKER = "...[truncated]"
14
9
 
15
10
 
16
- DOC_CHAT_APP_SERVER_TEMPLATE = """You are an autonomous coding assistant helping maintain the work docs for this repository.
17
-
18
- Instructions:
19
- - This run is non-interactive. Do not ask the user questions. If unsure, make reasonable assumptions and proceed.
20
- - Use the base doc content below. Drafts (if present) are the authoritative base.
21
- - You may inspect the repo and update the work docs listed when needed.
22
- - If you update docs, edit the files directly. If no changes are needed, do not edit files.
23
- - Respond with a short summary of what you did or found.
24
-
25
- Work docs (paths):
26
- - TODO: {todo_path}
27
- - PROGRESS: {progress_path}
28
- - OPINIONS: {opinions_path}
29
- - SPEC: {spec_path}
30
- - SUMMARY: {summary_path}
31
-
32
- {user_viewing_block}
33
-
34
- User request:
35
- {message}
36
-
37
- {docs_context_block}
38
- {recent_summary_block}
39
- """
40
-
41
-
42
- SPEC_INGEST_APP_SERVER_TEMPLATE = """You are preparing work docs (TODO/PROGRESS/OPINIONS) from the SPEC.
43
-
44
- SPEC path: {spec_path}
45
- TODO path: {todo_path}
46
- PROGRESS path: {progress_path}
47
- OPINIONS path: {opinions_path}
48
-
49
- Instructions:
50
- - Read the SPEC and existing docs from disk.
51
- - Edit the TODO, PROGRESS, and OPINIONS files directly to reflect the SPEC.
52
- - The TODO must be a Markdown checklist. Every task MUST be a checkbox line:
53
- - Use `- [ ] <task>` for open items and `- [x] <task>` for completed items.
54
- - Do NOT use plain bullets like `- task` or paragraphs for tasks.
55
- - Do NOT output a patch block. Just edit the files.
56
- - Output a short summary prefixed with "Agent: " explaining what you did.
57
-
58
- User request:
59
- {message}
60
-
61
- {spec_excerpt_block}
62
- """
63
-
64
-
65
- SNAPSHOT_APP_SERVER_TEMPLATE = """You are generating a compact Markdown repo snapshot meant to be pasted into another LLM chat.
66
-
67
- Snapshot path: {snapshot_path}
68
-
69
- Instructions:
70
- - Analyze the provided context and the repository.
71
- - Write the snapshot content directly to the snapshot path.
72
- - Keep the file concise and high-signal.
73
-
74
- Required output format (keep headings exactly):
75
- # Repo Snapshot
76
-
77
- ## What this repo is
78
- - 3–6 bullets.
79
-
80
- ## Architecture overview
81
- - Components and responsibilities.
82
- - Data/control flow (high level).
83
- - How things actually work
84
-
85
- ## Key files and modules
86
- - Bullet list of important paths with 1-line notes.
87
-
88
- ## Extension points and sharp edges
89
- - Config/state/concurrency hazards, limits, sharp edges.
90
-
91
- Inputs:
92
- {seed_context}
93
-
94
- {changes_block}
95
- {previous_snapshot_block}
96
- """
97
-
98
-
99
11
  AUTORUNNER_APP_SERVER_TEMPLATE = """You are an autonomous coding assistant operating on a git repository.
100
12
 
101
- Work docs (read from disk as needed):
102
- - TODO: {todo_path}
103
- - PROGRESS: {progress_path}
104
- - OPINIONS: {opinions_path}
105
- - SPEC: {spec_path}
106
- - SUMMARY: {summary_path}
13
+ Workspace docs (optional; read from disk when useful):
14
+ - Active context: {active_context_path}
15
+ - Decisions: {decisions_path}
16
+ - Spec: {spec_path}
17
+
18
+ Tickets:
19
+ - The authoritative work items are ticket files under `.codex-autorunner/tickets/`.
20
+ - Pick the next not-done ticket, implement it, and update the ticket file (`done: true`) when complete.
107
21
 
108
22
  Instructions:
109
23
  - This run is non-interactive. Do not ask the user questions. If unsure, make reasonable assumptions and proceed.
110
- - Work through TODO items from top to bottom.
111
- - Prefer fixing issues over documenting them.
112
- - Keep TODO/PROGRESS/OPINIONS/SPEC/SUMMARY in sync.
113
- - Make actual edits in the repo as needed.
24
+ - Prefer small, safe diffs and keep work focused on the current ticket.
25
+ - You may create new tickets only when needed to break down the current work.
114
26
 
115
27
  User request:
116
28
  {message}
117
29
 
118
- {todo_excerpt_block}
30
+ {workspace_spec_block}
119
31
  {prev_run_block}
120
32
  """
121
33
 
@@ -169,144 +81,6 @@ def _shrink_prompt(
169
81
  return prompt
170
82
 
171
83
 
172
- def build_doc_chat_prompt(
173
- config: Config,
174
- *,
175
- message: str,
176
- recent_summary: Optional[str],
177
- docs: dict[str, dict[str, str]],
178
- context_doc: Optional[str] = None,
179
- ) -> str:
180
- prompt_cfg: AppServerDocChatPromptConfig = config.app_server.prompts.doc_chat
181
- doc_paths = {
182
- "todo": _display_path(config.root, config.doc_path("todo")),
183
- "progress": _display_path(config.root, config.doc_path("progress")),
184
- "opinions": _display_path(config.root, config.doc_path("opinions")),
185
- "spec": _display_path(config.root, config.doc_path("spec")),
186
- "summary": _display_path(config.root, config.doc_path("summary")),
187
- }
188
- message_text = truncate_text(message, prompt_cfg.message_max_chars)
189
- doc_blocks = []
190
- for key, path in doc_paths.items():
191
- payload = docs.get(key, {})
192
- source = payload.get("source") or "disk"
193
- content = truncate_text(
194
- str(payload.get("content") or ""), prompt_cfg.target_excerpt_max_chars
195
- )
196
- if not content.strip():
197
- content = "(empty)"
198
- label = f"{key.upper()} [{path}] ({source.upper()})"
199
- doc_blocks.append(f"{label}\n{content}")
200
- docs_context = "\n\n".join(doc_blocks)
201
- recent_text = truncate_text(
202
- recent_summary or "", prompt_cfg.recent_summary_max_chars
203
- )
204
- user_viewing = ""
205
- if context_doc:
206
- user_viewing = f"The user is currently looking at {context_doc.upper()}."
207
-
208
- sections = {
209
- "message": message_text,
210
- "docs_context": docs_context,
211
- "recent_summary": recent_text,
212
- "user_viewing": user_viewing,
213
- }
214
-
215
- def render() -> str:
216
- return DOC_CHAT_APP_SERVER_TEMPLATE.format(
217
- todo_path=doc_paths["todo"],
218
- progress_path=doc_paths["progress"],
219
- opinions_path=doc_paths["opinions"],
220
- spec_path=doc_paths["spec"],
221
- summary_path=doc_paths["summary"],
222
- message=sections["message"],
223
- user_viewing_block=_optional_block(
224
- "USER_VIEWING", sections["user_viewing"]
225
- ),
226
- docs_context_block=_optional_block("DOC_BASES", sections["docs_context"]),
227
- recent_summary_block=_optional_block(
228
- "RECENT_RUN_SUMMARY", sections["recent_summary"]
229
- ),
230
- )
231
-
232
- return _shrink_prompt(
233
- max_chars=prompt_cfg.max_chars,
234
- render=render,
235
- sections=sections,
236
- order=["recent_summary", "docs_context", "message"],
237
- )
238
-
239
-
240
- def build_spec_ingest_prompt(
241
- config: Config,
242
- *,
243
- message: str,
244
- spec_path: Optional[Path] = None,
245
- ) -> str:
246
- prompt_cfg: AppServerSpecIngestPromptConfig = config.app_server.prompts.spec_ingest
247
- doc_paths = {
248
- "todo": _display_path(config.root, config.doc_path("todo")),
249
- "progress": _display_path(config.root, config.doc_path("progress")),
250
- "opinions": _display_path(config.root, config.doc_path("opinions")),
251
- }
252
- spec_target = spec_path or config.doc_path("spec")
253
- spec_path_str = _display_path(config.root, spec_target)
254
- message_text = truncate_text(message, prompt_cfg.message_max_chars)
255
- spec_excerpt = truncate_text(
256
- spec_target.read_text(encoding="utf-8"),
257
- prompt_cfg.spec_excerpt_max_chars,
258
- )
259
-
260
- sections = {
261
- "message": message_text,
262
- "spec_excerpt": spec_excerpt,
263
- }
264
-
265
- def render() -> str:
266
- return SPEC_INGEST_APP_SERVER_TEMPLATE.format(
267
- spec_path=spec_path_str,
268
- todo_path=doc_paths["todo"],
269
- progress_path=doc_paths["progress"],
270
- opinions_path=doc_paths["opinions"],
271
- message=sections["message"],
272
- spec_excerpt_block=_optional_block(
273
- "SPEC_EXCERPT", sections["spec_excerpt"]
274
- ),
275
- )
276
-
277
- return _shrink_prompt(
278
- max_chars=prompt_cfg.max_chars,
279
- render=render,
280
- sections=sections,
281
- order=["spec_excerpt", "message"],
282
- )
283
-
284
-
285
- def build_app_server_snapshot_prompt(
286
- config: Config,
287
- *,
288
- seed_context: str,
289
- previous_snapshot: Optional[str] = None,
290
- changes: Optional[str] = None,
291
- ) -> str:
292
- snapshot_path = config.doc_path("snapshot")
293
- previous_block = ""
294
- if previous_snapshot:
295
- previous_block = (
296
- f"<PREVIOUS_SNAPSHOT>\n{previous_snapshot.strip()}\n</PREVIOUS_SNAPSHOT>"
297
- )
298
- changes_block = ""
299
- if changes:
300
- changes_block = f"<CHANGES_SINCE_LAST_SNAPSHOT>\n{changes.strip()}\n</CHANGES_SINCE_LAST_SNAPSHOT>"
301
-
302
- return SNAPSHOT_APP_SERVER_TEMPLATE.format(
303
- snapshot_path=snapshot_path,
304
- seed_context=seed_context,
305
- changes_block=changes_block,
306
- previous_snapshot_block=previous_block,
307
- )
308
-
309
-
310
84
  def build_autorunner_prompt(
311
85
  config: Config,
312
86
  *,
@@ -315,35 +89,36 @@ def build_autorunner_prompt(
315
89
  ) -> str:
316
90
  prompt_cfg: AppServerAutorunnerPromptConfig = config.app_server.prompts.autorunner
317
91
  doc_paths = {
318
- "todo": _display_path(config.root, config.doc_path("todo")),
319
- "progress": _display_path(config.root, config.doc_path("progress")),
320
- "opinions": _display_path(config.root, config.doc_path("opinions")),
92
+ "active_context": _display_path(config.root, config.doc_path("active_context")),
93
+ "decisions": _display_path(config.root, config.doc_path("decisions")),
321
94
  "spec": _display_path(config.root, config.doc_path("spec")),
322
- "summary": _display_path(config.root, config.doc_path("summary")),
323
95
  }
96
+
324
97
  message_text = truncate_text(message, prompt_cfg.message_max_chars)
325
- todo_excerpt = truncate_text(
326
- config.doc_path("todo").read_text(encoding="utf-8"),
98
+ spec_excerpt = truncate_text(
99
+ (
100
+ config.doc_path("spec").read_text(encoding="utf-8")
101
+ if config.doc_path("spec").exists()
102
+ else ""
103
+ ),
327
104
  prompt_cfg.todo_excerpt_max_chars,
328
105
  )
329
106
  prev_run_text = truncate_text(prev_run_summary or "", prompt_cfg.prev_run_max_chars)
330
107
 
331
108
  sections = {
332
109
  "message": message_text,
333
- "todo_excerpt": todo_excerpt,
110
+ "workspace_spec": spec_excerpt,
334
111
  "prev_run": prev_run_text,
335
112
  }
336
113
 
337
114
  def render() -> str:
338
115
  return AUTORUNNER_APP_SERVER_TEMPLATE.format(
339
- todo_path=doc_paths["todo"],
340
- progress_path=doc_paths["progress"],
341
- opinions_path=doc_paths["opinions"],
116
+ active_context_path=doc_paths["active_context"],
117
+ decisions_path=doc_paths["decisions"],
342
118
  spec_path=doc_paths["spec"],
343
- summary_path=doc_paths["summary"],
344
119
  message=sections["message"],
345
- todo_excerpt_block=_optional_block(
346
- "TODO_EXCERPT", sections["todo_excerpt"]
120
+ workspace_spec_block=_optional_block(
121
+ "WORKSPACE_SPEC", sections["workspace_spec"]
347
122
  ),
348
123
  prev_run_block=_optional_block("PREV_RUN_SUMMARY", sections["prev_run"]),
349
124
  )
@@ -352,13 +127,11 @@ def build_autorunner_prompt(
352
127
  max_chars=prompt_cfg.max_chars,
353
128
  render=render,
354
129
  sections=sections,
355
- order=["prev_run", "todo_excerpt", "message"],
130
+ order=["prev_run", "workspace_spec", "message"],
356
131
  )
357
132
 
358
133
 
359
134
  APP_SERVER_PROMPT_BUILDERS = {
360
- "doc_chat": build_doc_chat_prompt,
361
- "spec_ingest": build_spec_ingest_prompt,
362
135
  "autorunner": build_autorunner_prompt,
363
136
  }
364
137
 
@@ -366,13 +139,7 @@ APP_SERVER_PROMPT_BUILDERS = {
366
139
  __all__ = [
367
140
  "AUTORUNNER_APP_SERVER_TEMPLATE",
368
141
  "APP_SERVER_PROMPT_BUILDERS",
369
- "DOC_CHAT_APP_SERVER_TEMPLATE",
370
- "SPEC_INGEST_APP_SERVER_TEMPLATE",
371
- "SNAPSHOT_APP_SERVER_TEMPLATE",
372
142
  "TRUNCATION_MARKER",
373
143
  "build_autorunner_prompt",
374
- "build_doc_chat_prompt",
375
- "build_spec_ingest_prompt",
376
- "build_app_server_snapshot_prompt",
377
144
  "truncate_text",
378
145
  ]
@@ -12,19 +12,15 @@ APP_SERVER_THREADS_FILENAME = ".codex-autorunner/app_server_threads.json"
12
12
  APP_SERVER_THREADS_VERSION = 1
13
13
  APP_SERVER_THREADS_CORRUPT_SUFFIX = ".corrupt"
14
14
  APP_SERVER_THREADS_NOTICE_SUFFIX = ".corrupt.json"
15
- DOC_CHAT_KINDS = ("todo", "progress", "opinions", "spec", "summary")
16
- DOC_CHAT_PREFIX = "doc_chat."
17
- DOC_CHAT_KEY = "doc_chat"
18
- DOC_CHAT_OPENCODE_KEY = "doc_chat.opencode"
19
- DOC_CHAT_OPENCODE_PREFIX = "doc_chat.opencode."
20
- DOC_CHAT_KEYS = {DOC_CHAT_KEY} | {f"{DOC_CHAT_PREFIX}{kind}" for kind in DOC_CHAT_KINDS}
21
- DOC_CHAT_KEYS = DOC_CHAT_KEYS | {
22
- DOC_CHAT_OPENCODE_KEY,
23
- *(f"{DOC_CHAT_OPENCODE_PREFIX}{kind}" for kind in DOC_CHAT_KINDS),
24
- }
25
- FEATURE_KEYS = DOC_CHAT_KEYS | {
26
- "spec_ingest",
27
- "spec_ingest.opencode",
15
+ FILE_CHAT_KEY = "file_chat"
16
+ FILE_CHAT_OPENCODE_KEY = "file_chat.opencode"
17
+ FILE_CHAT_PREFIX = "file_chat."
18
+ FILE_CHAT_OPENCODE_PREFIX = "file_chat.opencode."
19
+
20
+ # Static keys that can be reset/managed via the UI.
21
+ FEATURE_KEYS = {
22
+ FILE_CHAT_KEY,
23
+ FILE_CHAT_OPENCODE_KEY,
28
24
  "autorunner",
29
25
  "autorunner.opencode",
30
26
  }
@@ -43,6 +39,10 @@ def normalize_feature_key(raw: str) -> str:
43
39
  key = key.replace("/", ".").replace(":", ".")
44
40
  if key in FEATURE_KEYS:
45
41
  return key
42
+ # Allow per-target file chat threads (e.g. file_chat.ticket.1, file_chat.workspace.spec).
43
+ for prefix in (FILE_CHAT_PREFIX, FILE_CHAT_OPENCODE_PREFIX):
44
+ if key.startswith(prefix) and len(key) > len(prefix):
45
+ return key
46
46
  raise ValueError(f"invalid feature key: {raw}")
47
47
 
48
48
 
@@ -84,20 +84,9 @@ class AppServerThreadRegistry:
84
84
 
85
85
  def feature_map(self) -> dict[str, object]:
86
86
  threads = self.load()
87
- doc_chat_thread = threads.get(DOC_CHAT_KEY)
88
- doc_chat_opencode_thread = threads.get(DOC_CHAT_OPENCODE_KEY)
89
87
  payload: dict[str, object] = {
90
- "doc_chat": {
91
- kind: doc_chat_thread or threads.get(f"{DOC_CHAT_PREFIX}{kind}")
92
- for kind in DOC_CHAT_KINDS
93
- },
94
- "doc_chat_opencode": {
95
- kind: doc_chat_opencode_thread
96
- or threads.get(f"{DOC_CHAT_OPENCODE_PREFIX}{kind}")
97
- for kind in DOC_CHAT_KINDS
98
- },
99
- "spec_ingest": threads.get("spec_ingest"),
100
- "spec_ingest_opencode": threads.get("spec_ingest.opencode"),
88
+ "file_chat": threads.get(FILE_CHAT_KEY),
89
+ "file_chat_opencode": threads.get(FILE_CHAT_OPENCODE_KEY),
101
90
  "autorunner": threads.get("autorunner"),
102
91
  "autorunner_opencode": threads.get("autorunner.opencode"),
103
92
  }
@@ -1,3 +1,9 @@
1
+ # DEPRECATED: This module implements a Codex CLI subprocess runner.
2
+ # The primary execution path now uses the Codex app-server via OpenCode runtime.
3
+ # This file is kept for potential future CLI-as-backend support but is currently
4
+ # not referenced by the main engine. See src/codex_autorunner/core/engine.py for
5
+ # the current execution path (_run_codex_app_server_async).
6
+
1
7
  import asyncio
2
8
  import subprocess
3
9
  from pathlib import Path