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.
- codex_autorunner/__main__.py +4 -0
- codex_autorunner/agents/opencode/client.py +68 -35
- codex_autorunner/agents/opencode/logging.py +21 -5
- codex_autorunner/agents/opencode/run_prompt.py +1 -0
- codex_autorunner/agents/opencode/runtime.py +118 -30
- codex_autorunner/agents/opencode/supervisor.py +36 -48
- codex_autorunner/agents/registry.py +136 -8
- codex_autorunner/api.py +25 -0
- codex_autorunner/bootstrap.py +16 -35
- codex_autorunner/cli.py +157 -139
- codex_autorunner/core/about_car.py +44 -32
- codex_autorunner/core/adapter_utils.py +21 -0
- codex_autorunner/core/app_server_logging.py +7 -3
- codex_autorunner/core/app_server_prompts.py +27 -260
- codex_autorunner/core/app_server_threads.py +15 -26
- codex_autorunner/core/codex_runner.py +6 -0
- codex_autorunner/core/config.py +390 -100
- codex_autorunner/core/docs.py +10 -2
- codex_autorunner/core/drafts.py +82 -0
- codex_autorunner/core/engine.py +278 -262
- codex_autorunner/core/flows/__init__.py +25 -0
- codex_autorunner/core/flows/controller.py +178 -0
- codex_autorunner/core/flows/definition.py +82 -0
- codex_autorunner/core/flows/models.py +75 -0
- codex_autorunner/core/flows/runtime.py +351 -0
- codex_autorunner/core/flows/store.py +485 -0
- codex_autorunner/core/flows/transition.py +133 -0
- codex_autorunner/core/flows/worker_process.py +242 -0
- codex_autorunner/core/hub.py +15 -9
- codex_autorunner/core/locks.py +4 -0
- codex_autorunner/core/prompt.py +15 -7
- codex_autorunner/core/redaction.py +29 -0
- codex_autorunner/core/review_context.py +5 -8
- codex_autorunner/core/run_index.py +6 -0
- codex_autorunner/core/runner_process.py +5 -2
- codex_autorunner/core/state.py +0 -88
- codex_autorunner/core/static_assets.py +55 -0
- codex_autorunner/core/supervisor_utils.py +67 -0
- codex_autorunner/core/update.py +20 -11
- codex_autorunner/core/update_runner.py +2 -0
- codex_autorunner/core/utils.py +29 -2
- codex_autorunner/discovery.py +2 -4
- codex_autorunner/flows/ticket_flow/__init__.py +3 -0
- codex_autorunner/flows/ticket_flow/definition.py +91 -0
- codex_autorunner/integrations/agents/__init__.py +27 -0
- codex_autorunner/integrations/agents/agent_backend.py +142 -0
- codex_autorunner/integrations/agents/codex_backend.py +307 -0
- codex_autorunner/integrations/agents/opencode_backend.py +325 -0
- codex_autorunner/integrations/agents/run_event.py +71 -0
- codex_autorunner/integrations/app_server/client.py +576 -92
- codex_autorunner/integrations/app_server/supervisor.py +59 -33
- codex_autorunner/integrations/telegram/adapter.py +141 -167
- codex_autorunner/integrations/telegram/api_schemas.py +120 -0
- codex_autorunner/integrations/telegram/config.py +175 -0
- codex_autorunner/integrations/telegram/constants.py +16 -1
- codex_autorunner/integrations/telegram/dispatch.py +17 -0
- codex_autorunner/integrations/telegram/doctor.py +47 -0
- codex_autorunner/integrations/telegram/handlers/callbacks.py +0 -4
- codex_autorunner/integrations/telegram/handlers/commands/__init__.py +2 -0
- codex_autorunner/integrations/telegram/handlers/commands/execution.py +53 -57
- codex_autorunner/integrations/telegram/handlers/commands/files.py +2 -6
- codex_autorunner/integrations/telegram/handlers/commands/flows.py +227 -0
- codex_autorunner/integrations/telegram/handlers/commands/formatting.py +1 -1
- codex_autorunner/integrations/telegram/handlers/commands/github.py +41 -582
- codex_autorunner/integrations/telegram/handlers/commands/workspace.py +8 -8
- codex_autorunner/integrations/telegram/handlers/commands_runtime.py +133 -475
- codex_autorunner/integrations/telegram/handlers/commands_spec.py +11 -4
- codex_autorunner/integrations/telegram/handlers/messages.py +120 -9
- codex_autorunner/integrations/telegram/helpers.py +88 -16
- codex_autorunner/integrations/telegram/outbox.py +208 -37
- codex_autorunner/integrations/telegram/progress_stream.py +3 -10
- codex_autorunner/integrations/telegram/service.py +214 -40
- codex_autorunner/integrations/telegram/state.py +100 -2
- codex_autorunner/integrations/telegram/ticket_flow_bridge.py +322 -0
- codex_autorunner/integrations/telegram/transport.py +36 -3
- codex_autorunner/integrations/telegram/trigger_mode.py +53 -0
- codex_autorunner/manifest.py +2 -0
- codex_autorunner/plugin_api.py +22 -0
- codex_autorunner/routes/__init__.py +23 -14
- codex_autorunner/routes/analytics.py +239 -0
- codex_autorunner/routes/base.py +81 -109
- codex_autorunner/routes/file_chat.py +836 -0
- codex_autorunner/routes/flows.py +980 -0
- codex_autorunner/routes/messages.py +459 -0
- codex_autorunner/routes/system.py +6 -1
- codex_autorunner/routes/usage.py +87 -0
- codex_autorunner/routes/workspace.py +271 -0
- codex_autorunner/server.py +2 -1
- codex_autorunner/static/agentControls.js +1 -0
- codex_autorunner/static/agentEvents.js +248 -0
- codex_autorunner/static/app.js +25 -22
- codex_autorunner/static/autoRefresh.js +29 -1
- codex_autorunner/static/bootstrap.js +1 -0
- codex_autorunner/static/bus.js +1 -0
- codex_autorunner/static/cache.js +1 -0
- codex_autorunner/static/constants.js +20 -4
- codex_autorunner/static/dashboard.js +162 -196
- codex_autorunner/static/diffRenderer.js +37 -0
- codex_autorunner/static/docChatCore.js +324 -0
- codex_autorunner/static/docChatStorage.js +65 -0
- codex_autorunner/static/docChatVoice.js +65 -0
- codex_autorunner/static/docEditor.js +133 -0
- codex_autorunner/static/env.js +1 -0
- codex_autorunner/static/eventSummarizer.js +166 -0
- codex_autorunner/static/fileChat.js +182 -0
- codex_autorunner/static/health.js +155 -0
- codex_autorunner/static/hub.js +41 -118
- codex_autorunner/static/index.html +787 -858
- codex_autorunner/static/liveUpdates.js +1 -0
- codex_autorunner/static/loader.js +1 -0
- codex_autorunner/static/messages.js +470 -0
- codex_autorunner/static/mobileCompact.js +2 -1
- codex_autorunner/static/settings.js +24 -211
- codex_autorunner/static/styles.css +7567 -3865
- codex_autorunner/static/tabs.js +28 -5
- codex_autorunner/static/terminal.js +14 -0
- codex_autorunner/static/terminalManager.js +34 -59
- codex_autorunner/static/ticketChatActions.js +333 -0
- codex_autorunner/static/ticketChatEvents.js +16 -0
- codex_autorunner/static/ticketChatStorage.js +16 -0
- codex_autorunner/static/ticketChatStream.js +264 -0
- codex_autorunner/static/ticketEditor.js +750 -0
- codex_autorunner/static/ticketVoice.js +9 -0
- codex_autorunner/static/tickets.js +1315 -0
- codex_autorunner/static/utils.js +32 -3
- codex_autorunner/static/voice.js +1 -0
- codex_autorunner/static/workspace.js +672 -0
- codex_autorunner/static/workspaceApi.js +53 -0
- codex_autorunner/static/workspaceFileBrowser.js +504 -0
- codex_autorunner/tickets/__init__.py +20 -0
- codex_autorunner/tickets/agent_pool.py +377 -0
- codex_autorunner/tickets/files.py +85 -0
- codex_autorunner/tickets/frontmatter.py +55 -0
- codex_autorunner/tickets/lint.py +102 -0
- codex_autorunner/tickets/models.py +95 -0
- codex_autorunner/tickets/outbox.py +232 -0
- codex_autorunner/tickets/replies.py +179 -0
- codex_autorunner/tickets/runner.py +823 -0
- codex_autorunner/tickets/spec_ingest.py +77 -0
- codex_autorunner/web/app.py +269 -91
- codex_autorunner/web/middleware.py +3 -4
- codex_autorunner/web/schemas.py +89 -109
- codex_autorunner/web/static_assets.py +1 -44
- codex_autorunner/workspace/__init__.py +40 -0
- codex_autorunner/workspace/paths.py +319 -0
- {codex_autorunner-0.1.2.dist-info → codex_autorunner-1.0.0.dist-info}/METADATA +18 -21
- codex_autorunner-1.0.0.dist-info/RECORD +251 -0
- {codex_autorunner-0.1.2.dist-info → codex_autorunner-1.0.0.dist-info}/WHEEL +1 -1
- codex_autorunner/agents/execution/policy.py +0 -292
- codex_autorunner/agents/factory.py +0 -52
- codex_autorunner/agents/orchestrator.py +0 -358
- codex_autorunner/core/doc_chat.py +0 -1446
- codex_autorunner/core/snapshot.py +0 -580
- codex_autorunner/integrations/github/chatops.py +0 -268
- codex_autorunner/integrations/github/pr_flow.py +0 -1314
- codex_autorunner/routes/docs.py +0 -381
- codex_autorunner/routes/github.py +0 -327
- codex_autorunner/routes/runs.py +0 -250
- codex_autorunner/spec_ingest.py +0 -812
- codex_autorunner/static/docChatActions.js +0 -287
- codex_autorunner/static/docChatEvents.js +0 -300
- codex_autorunner/static/docChatRender.js +0 -205
- codex_autorunner/static/docChatStream.js +0 -361
- codex_autorunner/static/docs.js +0 -20
- codex_autorunner/static/docsClipboard.js +0 -69
- codex_autorunner/static/docsCrud.js +0 -257
- codex_autorunner/static/docsDocUpdates.js +0 -62
- codex_autorunner/static/docsDrafts.js +0 -16
- codex_autorunner/static/docsElements.js +0 -69
- codex_autorunner/static/docsInit.js +0 -285
- codex_autorunner/static/docsParse.js +0 -160
- codex_autorunner/static/docsSnapshot.js +0 -87
- codex_autorunner/static/docsSpecIngest.js +0 -263
- codex_autorunner/static/docsState.js +0 -127
- codex_autorunner/static/docsThreadRegistry.js +0 -44
- codex_autorunner/static/docsUi.js +0 -153
- codex_autorunner/static/docsVoice.js +0 -56
- codex_autorunner/static/github.js +0 -504
- codex_autorunner/static/logs.js +0 -678
- codex_autorunner/static/review.js +0 -157
- codex_autorunner/static/runs.js +0 -418
- codex_autorunner/static/snapshot.js +0 -124
- codex_autorunner/static/state.js +0 -94
- codex_autorunner/static/todoPreview.js +0 -27
- codex_autorunner/workspace.py +0 -16
- codex_autorunner-0.1.2.dist-info/RECORD +0 -222
- {codex_autorunner-0.1.2.dist-info → codex_autorunner-1.0.0.dist-info}/entry_points.txt +0 -0
- {codex_autorunner-0.1.2.dist-info → codex_autorunner-1.0.0.dist-info}/licenses/LICENSE +0 -0
- {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
|
-
|
|
102
|
-
-
|
|
103
|
-
-
|
|
104
|
-
-
|
|
105
|
-
|
|
106
|
-
|
|
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
|
-
-
|
|
111
|
-
-
|
|
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
|
-
{
|
|
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
|
-
"
|
|
319
|
-
"
|
|
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
|
-
|
|
326
|
-
|
|
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
|
-
"
|
|
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
|
-
|
|
340
|
-
|
|
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
|
-
|
|
346
|
-
"
|
|
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", "
|
|
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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
"
|
|
91
|
-
|
|
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
|