codex-autorunner 0.1.2__py3-none-any.whl → 1.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- codex_autorunner/__init__.py +12 -1
- codex_autorunner/__main__.py +4 -0
- codex_autorunner/agents/codex/harness.py +1 -1
- codex_autorunner/agents/opencode/client.py +68 -35
- codex_autorunner/agents/opencode/constants.py +3 -0
- codex_autorunner/agents/opencode/harness.py +6 -1
- codex_autorunner/agents/opencode/logging.py +21 -5
- codex_autorunner/agents/opencode/run_prompt.py +1 -0
- codex_autorunner/agents/opencode/runtime.py +176 -47
- codex_autorunner/agents/opencode/supervisor.py +36 -48
- codex_autorunner/agents/registry.py +155 -8
- codex_autorunner/api.py +25 -0
- codex_autorunner/bootstrap.py +22 -37
- codex_autorunner/cli.py +5 -1156
- codex_autorunner/codex_cli.py +20 -84
- codex_autorunner/core/__init__.py +4 -0
- codex_autorunner/core/about_car.py +49 -32
- codex_autorunner/core/adapter_utils.py +21 -0
- codex_autorunner/core/app_server_ids.py +59 -0
- codex_autorunner/core/app_server_logging.py +7 -3
- codex_autorunner/core/app_server_prompts.py +27 -260
- codex_autorunner/core/app_server_threads.py +26 -28
- codex_autorunner/core/app_server_utils.py +165 -0
- codex_autorunner/core/archive.py +349 -0
- codex_autorunner/core/codex_runner.py +12 -2
- codex_autorunner/core/config.py +587 -103
- codex_autorunner/core/docs.py +10 -2
- codex_autorunner/core/drafts.py +136 -0
- codex_autorunner/core/engine.py +1531 -866
- codex_autorunner/core/exceptions.py +4 -0
- codex_autorunner/core/flows/__init__.py +25 -0
- codex_autorunner/core/flows/controller.py +202 -0
- codex_autorunner/core/flows/definition.py +82 -0
- codex_autorunner/core/flows/models.py +88 -0
- codex_autorunner/core/flows/reasons.py +52 -0
- codex_autorunner/core/flows/reconciler.py +131 -0
- codex_autorunner/core/flows/runtime.py +382 -0
- codex_autorunner/core/flows/store.py +568 -0
- codex_autorunner/core/flows/transition.py +138 -0
- codex_autorunner/core/flows/ux_helpers.py +257 -0
- codex_autorunner/core/flows/worker_process.py +242 -0
- codex_autorunner/core/git_utils.py +62 -0
- codex_autorunner/core/hub.py +136 -16
- codex_autorunner/core/locks.py +4 -0
- codex_autorunner/core/notifications.py +14 -2
- codex_autorunner/core/ports/__init__.py +28 -0
- codex_autorunner/core/ports/agent_backend.py +150 -0
- codex_autorunner/core/ports/backend_orchestrator.py +41 -0
- codex_autorunner/core/ports/run_event.py +91 -0
- codex_autorunner/core/prompt.py +15 -7
- codex_autorunner/core/redaction.py +29 -0
- codex_autorunner/core/review_context.py +5 -8
- codex_autorunner/core/run_index.py +6 -0
- codex_autorunner/core/runner_process.py +5 -2
- codex_autorunner/core/state.py +0 -88
- codex_autorunner/core/state_roots.py +57 -0
- codex_autorunner/core/supervisor_protocol.py +15 -0
- codex_autorunner/core/supervisor_utils.py +67 -0
- codex_autorunner/core/text_delta_coalescer.py +54 -0
- codex_autorunner/core/ticket_linter_cli.py +201 -0
- codex_autorunner/core/ticket_manager_cli.py +432 -0
- codex_autorunner/core/update.py +24 -16
- codex_autorunner/core/update_paths.py +28 -0
- codex_autorunner/core/update_runner.py +2 -0
- codex_autorunner/core/usage.py +164 -12
- codex_autorunner/core/utils.py +120 -11
- codex_autorunner/discovery.py +2 -4
- codex_autorunner/flows/review/__init__.py +17 -0
- codex_autorunner/{core/review.py → flows/review/service.py} +15 -10
- codex_autorunner/flows/ticket_flow/__init__.py +3 -0
- codex_autorunner/flows/ticket_flow/definition.py +98 -0
- codex_autorunner/integrations/agents/__init__.py +17 -0
- codex_autorunner/integrations/agents/backend_orchestrator.py +284 -0
- codex_autorunner/integrations/agents/codex_adapter.py +90 -0
- codex_autorunner/integrations/agents/codex_backend.py +448 -0
- codex_autorunner/integrations/agents/opencode_adapter.py +108 -0
- codex_autorunner/integrations/agents/opencode_backend.py +598 -0
- codex_autorunner/integrations/agents/runner.py +91 -0
- codex_autorunner/integrations/agents/wiring.py +271 -0
- codex_autorunner/integrations/app_server/client.py +583 -152
- codex_autorunner/integrations/app_server/env.py +2 -107
- codex_autorunner/{core/app_server_events.py → integrations/app_server/event_buffer.py} +15 -8
- codex_autorunner/integrations/app_server/supervisor.py +59 -33
- codex_autorunner/integrations/telegram/adapter.py +204 -165
- codex_autorunner/integrations/telegram/api_schemas.py +120 -0
- codex_autorunner/integrations/telegram/config.py +221 -0
- codex_autorunner/integrations/telegram/constants.py +17 -2
- codex_autorunner/integrations/telegram/dispatch.py +17 -0
- codex_autorunner/integrations/telegram/doctor.py +47 -0
- codex_autorunner/integrations/telegram/handlers/callbacks.py +7 -4
- codex_autorunner/integrations/telegram/handlers/commands/__init__.py +2 -0
- codex_autorunner/integrations/telegram/handlers/commands/execution.py +53 -57
- codex_autorunner/integrations/telegram/handlers/commands/files.py +2 -6
- codex_autorunner/integrations/telegram/handlers/commands/flows.py +1364 -0
- codex_autorunner/integrations/telegram/handlers/commands/formatting.py +1 -1
- codex_autorunner/integrations/telegram/handlers/commands/github.py +41 -582
- codex_autorunner/integrations/telegram/handlers/commands/workspace.py +8 -8
- codex_autorunner/integrations/telegram/handlers/commands_runtime.py +137 -478
- codex_autorunner/integrations/telegram/handlers/commands_spec.py +17 -4
- codex_autorunner/integrations/telegram/handlers/messages.py +121 -9
- codex_autorunner/integrations/telegram/handlers/selections.py +61 -1
- codex_autorunner/integrations/telegram/helpers.py +111 -16
- codex_autorunner/integrations/telegram/outbox.py +208 -37
- codex_autorunner/integrations/telegram/progress_stream.py +3 -10
- codex_autorunner/integrations/telegram/service.py +221 -42
- codex_autorunner/integrations/telegram/state.py +100 -2
- codex_autorunner/integrations/telegram/ticket_flow_bridge.py +611 -0
- codex_autorunner/integrations/telegram/transport.py +39 -4
- codex_autorunner/integrations/telegram/trigger_mode.py +53 -0
- codex_autorunner/manifest.py +2 -0
- codex_autorunner/plugin_api.py +22 -0
- codex_autorunner/routes/__init__.py +37 -67
- codex_autorunner/routes/agents.py +2 -137
- codex_autorunner/routes/analytics.py +3 -0
- codex_autorunner/routes/app_server.py +2 -131
- codex_autorunner/routes/base.py +2 -624
- codex_autorunner/routes/file_chat.py +7 -0
- codex_autorunner/routes/flows.py +7 -0
- codex_autorunner/routes/messages.py +7 -0
- codex_autorunner/routes/repos.py +2 -196
- codex_autorunner/routes/review.py +2 -147
- codex_autorunner/routes/sessions.py +2 -175
- codex_autorunner/routes/settings.py +2 -168
- codex_autorunner/routes/shared.py +2 -275
- codex_autorunner/routes/system.py +4 -188
- codex_autorunner/routes/usage.py +3 -0
- codex_autorunner/routes/voice.py +2 -119
- codex_autorunner/routes/workspace.py +3 -0
- codex_autorunner/server.py +3 -2
- codex_autorunner/static/agentControls.js +41 -11
- codex_autorunner/static/agentEvents.js +248 -0
- codex_autorunner/static/app.js +35 -24
- codex_autorunner/static/archive.js +826 -0
- codex_autorunner/static/archiveApi.js +37 -0
- codex_autorunner/static/autoRefresh.js +36 -8
- codex_autorunner/static/bootstrap.js +1 -0
- codex_autorunner/static/bus.js +1 -0
- codex_autorunner/static/cache.js +1 -0
- codex_autorunner/static/constants.js +20 -4
- codex_autorunner/static/dashboard.js +344 -325
- codex_autorunner/static/diffRenderer.js +37 -0
- codex_autorunner/static/docChatCore.js +324 -0
- codex_autorunner/static/docChatStorage.js +65 -0
- codex_autorunner/static/docChatVoice.js +65 -0
- codex_autorunner/static/docEditor.js +133 -0
- codex_autorunner/static/env.js +1 -0
- codex_autorunner/static/eventSummarizer.js +166 -0
- codex_autorunner/static/fileChat.js +182 -0
- codex_autorunner/static/health.js +155 -0
- codex_autorunner/static/hub.js +126 -185
- codex_autorunner/static/index.html +839 -863
- codex_autorunner/static/liveUpdates.js +1 -0
- codex_autorunner/static/loader.js +1 -0
- codex_autorunner/static/messages.js +873 -0
- codex_autorunner/static/mobileCompact.js +2 -1
- codex_autorunner/static/preserve.js +17 -0
- codex_autorunner/static/settings.js +149 -217
- codex_autorunner/static/smartRefresh.js +52 -0
- codex_autorunner/static/styles.css +8850 -3876
- codex_autorunner/static/tabs.js +175 -11
- codex_autorunner/static/terminal.js +32 -0
- codex_autorunner/static/terminalManager.js +34 -59
- codex_autorunner/static/ticketChatActions.js +333 -0
- codex_autorunner/static/ticketChatEvents.js +16 -0
- codex_autorunner/static/ticketChatStorage.js +16 -0
- codex_autorunner/static/ticketChatStream.js +264 -0
- codex_autorunner/static/ticketEditor.js +844 -0
- codex_autorunner/static/ticketVoice.js +9 -0
- codex_autorunner/static/tickets.js +1988 -0
- codex_autorunner/static/utils.js +43 -3
- codex_autorunner/static/voice.js +1 -0
- codex_autorunner/static/workspace.js +765 -0
- codex_autorunner/static/workspaceApi.js +53 -0
- codex_autorunner/static/workspaceFileBrowser.js +504 -0
- codex_autorunner/surfaces/__init__.py +5 -0
- codex_autorunner/surfaces/cli/__init__.py +6 -0
- codex_autorunner/surfaces/cli/cli.py +1224 -0
- codex_autorunner/surfaces/cli/codex_cli.py +20 -0
- codex_autorunner/surfaces/telegram/__init__.py +3 -0
- codex_autorunner/surfaces/web/__init__.py +1 -0
- codex_autorunner/surfaces/web/app.py +2019 -0
- codex_autorunner/surfaces/web/hub_jobs.py +192 -0
- codex_autorunner/surfaces/web/middleware.py +587 -0
- codex_autorunner/surfaces/web/pty_session.py +370 -0
- codex_autorunner/surfaces/web/review.py +6 -0
- codex_autorunner/surfaces/web/routes/__init__.py +78 -0
- codex_autorunner/surfaces/web/routes/agents.py +138 -0
- codex_autorunner/surfaces/web/routes/analytics.py +277 -0
- codex_autorunner/surfaces/web/routes/app_server.py +132 -0
- codex_autorunner/surfaces/web/routes/archive.py +357 -0
- codex_autorunner/surfaces/web/routes/base.py +615 -0
- codex_autorunner/surfaces/web/routes/file_chat.py +836 -0
- codex_autorunner/surfaces/web/routes/flows.py +1164 -0
- codex_autorunner/surfaces/web/routes/messages.py +459 -0
- codex_autorunner/surfaces/web/routes/repos.py +197 -0
- codex_autorunner/surfaces/web/routes/review.py +148 -0
- codex_autorunner/surfaces/web/routes/sessions.py +176 -0
- codex_autorunner/surfaces/web/routes/settings.py +169 -0
- codex_autorunner/surfaces/web/routes/shared.py +280 -0
- codex_autorunner/surfaces/web/routes/system.py +196 -0
- codex_autorunner/surfaces/web/routes/usage.py +89 -0
- codex_autorunner/surfaces/web/routes/voice.py +120 -0
- codex_autorunner/surfaces/web/routes/workspace.py +271 -0
- codex_autorunner/surfaces/web/runner_manager.py +25 -0
- codex_autorunner/surfaces/web/schemas.py +417 -0
- codex_autorunner/surfaces/web/static_assets.py +490 -0
- codex_autorunner/surfaces/web/static_refresh.py +86 -0
- codex_autorunner/surfaces/web/terminal_sessions.py +78 -0
- codex_autorunner/tickets/__init__.py +27 -0
- codex_autorunner/tickets/agent_pool.py +399 -0
- codex_autorunner/tickets/files.py +89 -0
- codex_autorunner/tickets/frontmatter.py +55 -0
- codex_autorunner/tickets/lint.py +102 -0
- codex_autorunner/tickets/models.py +97 -0
- codex_autorunner/tickets/outbox.py +244 -0
- codex_autorunner/tickets/replies.py +179 -0
- codex_autorunner/tickets/runner.py +881 -0
- codex_autorunner/tickets/spec_ingest.py +77 -0
- codex_autorunner/web/__init__.py +5 -1
- codex_autorunner/web/app.py +2 -1771
- codex_autorunner/web/hub_jobs.py +2 -191
- codex_autorunner/web/middleware.py +2 -587
- codex_autorunner/web/pty_session.py +2 -369
- codex_autorunner/web/runner_manager.py +2 -24
- codex_autorunner/web/schemas.py +2 -396
- codex_autorunner/web/static_assets.py +4 -484
- codex_autorunner/web/static_refresh.py +2 -85
- codex_autorunner/web/terminal_sessions.py +2 -77
- codex_autorunner/workspace/__init__.py +40 -0
- codex_autorunner/workspace/paths.py +335 -0
- codex_autorunner-1.1.0.dist-info/METADATA +154 -0
- codex_autorunner-1.1.0.dist-info/RECORD +308 -0
- {codex_autorunner-0.1.2.dist-info → codex_autorunner-1.1.0.dist-info}/WHEEL +1 -1
- codex_autorunner/agents/execution/policy.py +0 -292
- codex_autorunner/agents/factory.py +0 -52
- codex_autorunner/agents/orchestrator.py +0 -358
- codex_autorunner/core/doc_chat.py +0 -1446
- codex_autorunner/core/snapshot.py +0 -580
- codex_autorunner/integrations/github/chatops.py +0 -268
- codex_autorunner/integrations/github/pr_flow.py +0 -1314
- codex_autorunner/routes/docs.py +0 -381
- codex_autorunner/routes/github.py +0 -327
- codex_autorunner/routes/runs.py +0 -250
- codex_autorunner/spec_ingest.py +0 -812
- codex_autorunner/static/docChatActions.js +0 -287
- codex_autorunner/static/docChatEvents.js +0 -300
- codex_autorunner/static/docChatRender.js +0 -205
- codex_autorunner/static/docChatStream.js +0 -361
- codex_autorunner/static/docs.js +0 -20
- codex_autorunner/static/docsClipboard.js +0 -69
- codex_autorunner/static/docsCrud.js +0 -257
- codex_autorunner/static/docsDocUpdates.js +0 -62
- codex_autorunner/static/docsDrafts.js +0 -16
- codex_autorunner/static/docsElements.js +0 -69
- codex_autorunner/static/docsInit.js +0 -285
- codex_autorunner/static/docsParse.js +0 -160
- codex_autorunner/static/docsSnapshot.js +0 -87
- codex_autorunner/static/docsSpecIngest.js +0 -263
- codex_autorunner/static/docsState.js +0 -127
- codex_autorunner/static/docsThreadRegistry.js +0 -44
- codex_autorunner/static/docsUi.js +0 -153
- codex_autorunner/static/docsVoice.js +0 -56
- codex_autorunner/static/github.js +0 -504
- codex_autorunner/static/logs.js +0 -678
- codex_autorunner/static/review.js +0 -157
- codex_autorunner/static/runs.js +0 -418
- codex_autorunner/static/snapshot.js +0 -124
- codex_autorunner/static/state.js +0 -94
- codex_autorunner/static/todoPreview.js +0 -27
- codex_autorunner/workspace.py +0 -16
- codex_autorunner-0.1.2.dist-info/METADATA +0 -249
- codex_autorunner-0.1.2.dist-info/RECORD +0 -222
- /codex_autorunner/{routes → surfaces/web/routes}/terminal_images.py +0 -0
- {codex_autorunner-0.1.2.dist-info → codex_autorunner-1.1.0.dist-info}/entry_points.txt +0 -0
- {codex_autorunner-0.1.2.dist-info → codex_autorunner-1.1.0.dist-info}/licenses/LICENSE +0 -0
- {codex_autorunner-0.1.2.dist-info → codex_autorunner-1.1.0.dist-info}/top_level.txt +0 -0
|
@@ -8,6 +8,21 @@ from pathlib import Path
|
|
|
8
8
|
from typing import Any, Iterable, Optional
|
|
9
9
|
|
|
10
10
|
from .adapter import TelegramAllowlist
|
|
11
|
+
from .constants import (
|
|
12
|
+
CACHE_CLEANUP_INTERVAL_SECONDS,
|
|
13
|
+
COALESCE_BUFFER_TTL_SECONDS,
|
|
14
|
+
DEFAULT_AGENT_TURN_TIMEOUT_SECONDS,
|
|
15
|
+
MEDIA_BATCH_BUFFER_TTL_SECONDS,
|
|
16
|
+
MODEL_PENDING_TTL_SECONDS,
|
|
17
|
+
OVERSIZE_WARNING_TTL_SECONDS,
|
|
18
|
+
PENDING_APPROVAL_TTL_SECONDS,
|
|
19
|
+
PENDING_QUESTION_TTL_SECONDS,
|
|
20
|
+
PROGRESS_STREAM_TTL_SECONDS,
|
|
21
|
+
REASONING_BUFFER_TTL_SECONDS,
|
|
22
|
+
SELECTION_STATE_TTL_SECONDS,
|
|
23
|
+
TURN_PREVIEW_TTL_SECONDS,
|
|
24
|
+
UPDATE_ID_PERSIST_INTERVAL_SECONDS,
|
|
25
|
+
)
|
|
11
26
|
from .state import APPROVAL_MODE_YOLO, normalize_approval_mode
|
|
12
27
|
|
|
13
28
|
DEFAULT_ALLOWED_UPDATES = ("message", "edited_message", "callback_query")
|
|
@@ -17,6 +32,8 @@ DEFAULT_SAFE_APPROVAL_POLICY = "on-request"
|
|
|
17
32
|
DEFAULT_YOLO_APPROVAL_POLICY = "never"
|
|
18
33
|
DEFAULT_YOLO_SANDBOX_POLICY = "dangerFullAccess"
|
|
19
34
|
DEFAULT_PARSE_MODE = "HTML"
|
|
35
|
+
DEFAULT_TRIGGER_MODE = "all"
|
|
36
|
+
TRIGGER_MODE_OPTIONS = {"all", "mentions"}
|
|
20
37
|
DEFAULT_STATE_FILE = ".codex-autorunner/telegram_state.sqlite3"
|
|
21
38
|
DEFAULT_APP_SERVER_COMMAND = ["codex", "app-server"]
|
|
22
39
|
DEFAULT_APP_SERVER_MAX_HANDLES = 20
|
|
@@ -45,6 +62,7 @@ DEFAULT_MESSAGE_OVERFLOW = "document"
|
|
|
45
62
|
MESSAGE_OVERFLOW_OPTIONS = {"document", "split", "trim"}
|
|
46
63
|
DEFAULT_METRICS_MODE = "separate"
|
|
47
64
|
METRICS_MODE_OPTIONS = {"separate", "append_to_response", "append_to_progress"}
|
|
65
|
+
DEFAULT_PAUSE_DISPATCH_MAX_FILE_BYTES = 50 * 1024 * 1024
|
|
48
66
|
|
|
49
67
|
PARSE_MODE_ALIASES = {
|
|
50
68
|
"html": "HTML",
|
|
@@ -107,6 +125,22 @@ class TelegramBotShellConfig:
|
|
|
107
125
|
max_output_chars: int
|
|
108
126
|
|
|
109
127
|
|
|
128
|
+
@dataclass(frozen=True)
|
|
129
|
+
class TelegramBotCacheConfig:
|
|
130
|
+
cleanup_interval_seconds: float
|
|
131
|
+
coalesce_buffer_ttl_seconds: float
|
|
132
|
+
media_batch_buffer_ttl_seconds: float
|
|
133
|
+
model_pending_ttl_seconds: float
|
|
134
|
+
pending_approval_ttl_seconds: float
|
|
135
|
+
pending_question_ttl_seconds: float
|
|
136
|
+
reasoning_buffer_ttl_seconds: float
|
|
137
|
+
selection_state_ttl_seconds: float
|
|
138
|
+
turn_preview_ttl_seconds: float
|
|
139
|
+
progress_stream_ttl_seconds: float
|
|
140
|
+
oversize_warning_ttl_seconds: float
|
|
141
|
+
update_id_persist_interval_seconds: float
|
|
142
|
+
|
|
143
|
+
|
|
110
144
|
@dataclass(frozen=True)
|
|
111
145
|
class TelegramBotCommandScope:
|
|
112
146
|
scope: dict[str, Any]
|
|
@@ -127,6 +161,14 @@ class TelegramBotProgressStreamConfig:
|
|
|
127
161
|
min_edit_interval_seconds: float
|
|
128
162
|
|
|
129
163
|
|
|
164
|
+
@dataclass(frozen=True)
|
|
165
|
+
class PauseDispatchNotifications:
|
|
166
|
+
enabled: bool
|
|
167
|
+
send_attachments: bool
|
|
168
|
+
max_file_size_bytes: int
|
|
169
|
+
chunk_long_messages: bool
|
|
170
|
+
|
|
171
|
+
|
|
130
172
|
@dataclass(frozen=True)
|
|
131
173
|
class TelegramMediaCandidate:
|
|
132
174
|
kind: str
|
|
@@ -150,12 +192,15 @@ class TelegramBotConfig:
|
|
|
150
192
|
allowed_chat_ids: set[int]
|
|
151
193
|
allowed_user_ids: set[int]
|
|
152
194
|
require_topics: bool
|
|
195
|
+
trigger_mode: str
|
|
153
196
|
defaults: TelegramBotDefaults
|
|
154
197
|
concurrency: TelegramBotConcurrency
|
|
155
198
|
media: TelegramBotMediaConfig
|
|
156
199
|
shell: TelegramBotShellConfig
|
|
200
|
+
cache: TelegramBotCacheConfig
|
|
157
201
|
progress_stream: TelegramBotProgressStreamConfig
|
|
158
202
|
command_registration: TelegramBotCommandRegistration
|
|
203
|
+
opencode_command: list[str]
|
|
159
204
|
state_file: Path
|
|
160
205
|
app_server_command_env: str
|
|
161
206
|
app_server_command: list[str]
|
|
@@ -164,6 +209,7 @@ class TelegramBotConfig:
|
|
|
164
209
|
app_server_start_timeout_seconds: float
|
|
165
210
|
app_server_start_max_attempts: Optional[int]
|
|
166
211
|
app_server_turn_timeout_seconds: Optional[float]
|
|
212
|
+
agent_turn_timeout_seconds: dict[str, Optional[float]]
|
|
167
213
|
poll_timeout_seconds: int
|
|
168
214
|
poll_request_timeout_seconds: Optional[float]
|
|
169
215
|
poll_allowed_updates: list[str]
|
|
@@ -171,6 +217,9 @@ class TelegramBotConfig:
|
|
|
171
217
|
metrics_mode: str
|
|
172
218
|
coalesce_window_seconds: float
|
|
173
219
|
agent_binaries: dict[str, str]
|
|
220
|
+
ticket_flow_auto_resume: bool
|
|
221
|
+
pause_dispatch_notifications: PauseDispatchNotifications
|
|
222
|
+
default_notification_chat_id: Optional[int]
|
|
174
223
|
|
|
175
224
|
@classmethod
|
|
176
225
|
def from_raw(
|
|
@@ -183,6 +232,16 @@ class TelegramBotConfig:
|
|
|
183
232
|
) -> "TelegramBotConfig":
|
|
184
233
|
env = env or dict(os.environ)
|
|
185
234
|
cfg: dict[str, Any] = raw if isinstance(raw, dict) else {}
|
|
235
|
+
|
|
236
|
+
def _positive_float(value: Any, default: float) -> float:
|
|
237
|
+
try:
|
|
238
|
+
parsed = float(value)
|
|
239
|
+
except (TypeError, ValueError):
|
|
240
|
+
return default
|
|
241
|
+
if parsed <= 0:
|
|
242
|
+
return default
|
|
243
|
+
return parsed
|
|
244
|
+
|
|
186
245
|
enabled = bool(cfg.get("enabled", False))
|
|
187
246
|
mode = str(cfg.get("mode", "polling"))
|
|
188
247
|
bot_token_env = str(cfg.get("bot_token_env", "CAR_TELEGRAM_BOT_TOKEN"))
|
|
@@ -204,6 +263,10 @@ class TelegramBotConfig:
|
|
|
204
263
|
|
|
205
264
|
require_topics = bool(cfg.get("require_topics", False))
|
|
206
265
|
|
|
266
|
+
trigger_mode = (
|
|
267
|
+
str(cfg.get("trigger_mode", DEFAULT_TRIGGER_MODE)).strip().lower()
|
|
268
|
+
)
|
|
269
|
+
|
|
207
270
|
defaults_raw_value = cfg.get("defaults")
|
|
208
271
|
defaults_raw: dict[str, Any] = (
|
|
209
272
|
defaults_raw_value if isinstance(defaults_raw_value, dict) else {}
|
|
@@ -313,6 +376,81 @@ class TelegramBotConfig:
|
|
|
313
376
|
timeout_ms=shell_timeout_ms,
|
|
314
377
|
max_output_chars=shell_max_output_chars,
|
|
315
378
|
)
|
|
379
|
+
cache_raw_value = cfg.get("cache")
|
|
380
|
+
cache_raw: dict[str, Any] = (
|
|
381
|
+
cache_raw_value if isinstance(cache_raw_value, dict) else {}
|
|
382
|
+
)
|
|
383
|
+
cache = TelegramBotCacheConfig(
|
|
384
|
+
cleanup_interval_seconds=_positive_float(
|
|
385
|
+
cache_raw.get(
|
|
386
|
+
"cleanup_interval_seconds", CACHE_CLEANUP_INTERVAL_SECONDS
|
|
387
|
+
),
|
|
388
|
+
CACHE_CLEANUP_INTERVAL_SECONDS,
|
|
389
|
+
),
|
|
390
|
+
coalesce_buffer_ttl_seconds=_positive_float(
|
|
391
|
+
cache_raw.get(
|
|
392
|
+
"coalesce_buffer_ttl_seconds", COALESCE_BUFFER_TTL_SECONDS
|
|
393
|
+
),
|
|
394
|
+
COALESCE_BUFFER_TTL_SECONDS,
|
|
395
|
+
),
|
|
396
|
+
media_batch_buffer_ttl_seconds=_positive_float(
|
|
397
|
+
cache_raw.get(
|
|
398
|
+
"media_batch_buffer_ttl_seconds", MEDIA_BATCH_BUFFER_TTL_SECONDS
|
|
399
|
+
),
|
|
400
|
+
MEDIA_BATCH_BUFFER_TTL_SECONDS,
|
|
401
|
+
),
|
|
402
|
+
model_pending_ttl_seconds=_positive_float(
|
|
403
|
+
cache_raw.get("model_pending_ttl_seconds", MODEL_PENDING_TTL_SECONDS),
|
|
404
|
+
MODEL_PENDING_TTL_SECONDS,
|
|
405
|
+
),
|
|
406
|
+
pending_approval_ttl_seconds=_positive_float(
|
|
407
|
+
cache_raw.get(
|
|
408
|
+
"pending_approval_ttl_seconds", PENDING_APPROVAL_TTL_SECONDS
|
|
409
|
+
),
|
|
410
|
+
PENDING_APPROVAL_TTL_SECONDS,
|
|
411
|
+
),
|
|
412
|
+
pending_question_ttl_seconds=_positive_float(
|
|
413
|
+
cache_raw.get(
|
|
414
|
+
"pending_question_ttl_seconds", PENDING_QUESTION_TTL_SECONDS
|
|
415
|
+
),
|
|
416
|
+
PENDING_QUESTION_TTL_SECONDS,
|
|
417
|
+
),
|
|
418
|
+
reasoning_buffer_ttl_seconds=_positive_float(
|
|
419
|
+
cache_raw.get(
|
|
420
|
+
"reasoning_buffer_ttl_seconds", REASONING_BUFFER_TTL_SECONDS
|
|
421
|
+
),
|
|
422
|
+
REASONING_BUFFER_TTL_SECONDS,
|
|
423
|
+
),
|
|
424
|
+
selection_state_ttl_seconds=_positive_float(
|
|
425
|
+
cache_raw.get(
|
|
426
|
+
"selection_state_ttl_seconds", SELECTION_STATE_TTL_SECONDS
|
|
427
|
+
),
|
|
428
|
+
SELECTION_STATE_TTL_SECONDS,
|
|
429
|
+
),
|
|
430
|
+
turn_preview_ttl_seconds=_positive_float(
|
|
431
|
+
cache_raw.get("turn_preview_ttl_seconds", TURN_PREVIEW_TTL_SECONDS),
|
|
432
|
+
TURN_PREVIEW_TTL_SECONDS,
|
|
433
|
+
),
|
|
434
|
+
progress_stream_ttl_seconds=_positive_float(
|
|
435
|
+
cache_raw.get(
|
|
436
|
+
"progress_stream_ttl_seconds", PROGRESS_STREAM_TTL_SECONDS
|
|
437
|
+
),
|
|
438
|
+
PROGRESS_STREAM_TTL_SECONDS,
|
|
439
|
+
),
|
|
440
|
+
oversize_warning_ttl_seconds=_positive_float(
|
|
441
|
+
cache_raw.get(
|
|
442
|
+
"oversize_warning_ttl_seconds", OVERSIZE_WARNING_TTL_SECONDS
|
|
443
|
+
),
|
|
444
|
+
OVERSIZE_WARNING_TTL_SECONDS,
|
|
445
|
+
),
|
|
446
|
+
update_id_persist_interval_seconds=_positive_float(
|
|
447
|
+
cache_raw.get(
|
|
448
|
+
"update_id_persist_interval_seconds",
|
|
449
|
+
UPDATE_ID_PERSIST_INTERVAL_SECONDS,
|
|
450
|
+
),
|
|
451
|
+
UPDATE_ID_PERSIST_INTERVAL_SECONDS,
|
|
452
|
+
),
|
|
453
|
+
)
|
|
316
454
|
|
|
317
455
|
progress_raw_value = cfg.get("progress_stream")
|
|
318
456
|
progress_raw: dict[str, Any] = (
|
|
@@ -374,6 +512,44 @@ class TelegramBotConfig:
|
|
|
374
512
|
if coalesce_window_seconds <= 0:
|
|
375
513
|
coalesce_window_seconds = DEFAULT_COALESCE_WINDOW_SECONDS
|
|
376
514
|
|
|
515
|
+
ticket_flow_raw = (
|
|
516
|
+
cfg.get("ticket_flow") if isinstance(cfg.get("ticket_flow"), dict) else {}
|
|
517
|
+
)
|
|
518
|
+
ticket_flow_auto_resume = bool(ticket_flow_raw.get("auto_resume", False))
|
|
519
|
+
|
|
520
|
+
pause_raw_value = cfg.get("pause_dispatch_notifications")
|
|
521
|
+
pause_raw: dict[str, Any] = (
|
|
522
|
+
pause_raw_value if isinstance(pause_raw_value, dict) else {}
|
|
523
|
+
)
|
|
524
|
+
pause_enabled = bool(pause_raw.get("enabled", enabled))
|
|
525
|
+
pause_send_attachments = bool(pause_raw.get("send_attachments", True))
|
|
526
|
+
pause_max_file_size_bytes = int(
|
|
527
|
+
pause_raw.get("max_file_size_bytes", DEFAULT_PAUSE_DISPATCH_MAX_FILE_BYTES)
|
|
528
|
+
)
|
|
529
|
+
if pause_max_file_size_bytes <= 0:
|
|
530
|
+
pause_max_file_size_bytes = DEFAULT_PAUSE_DISPATCH_MAX_FILE_BYTES
|
|
531
|
+
pause_chunk_long_messages = bool(pause_raw.get("chunk_long_messages", True))
|
|
532
|
+
pause_dispatch_notifications = PauseDispatchNotifications(
|
|
533
|
+
enabled=pause_enabled,
|
|
534
|
+
send_attachments=pause_send_attachments,
|
|
535
|
+
max_file_size_bytes=pause_max_file_size_bytes,
|
|
536
|
+
chunk_long_messages=pause_chunk_long_messages,
|
|
537
|
+
)
|
|
538
|
+
|
|
539
|
+
default_notification_chat_raw = cfg.get("default_notification_chat_id")
|
|
540
|
+
default_notification_chat_id: Optional[int] = None
|
|
541
|
+
env_chat_candidates = _parse_int_list(env.get(chat_id_env))
|
|
542
|
+
if default_notification_chat_raw is not None:
|
|
543
|
+
try:
|
|
544
|
+
default_notification_chat_id = int(default_notification_chat_raw)
|
|
545
|
+
except (TypeError, ValueError):
|
|
546
|
+
default_notification_chat_id = None
|
|
547
|
+
if default_notification_chat_id is None:
|
|
548
|
+
if env_chat_candidates:
|
|
549
|
+
default_notification_chat_id = env_chat_candidates[0]
|
|
550
|
+
elif allowed_chat_ids:
|
|
551
|
+
default_notification_chat_id = min(allowed_chat_ids)
|
|
552
|
+
|
|
377
553
|
agent_binaries = dict(agent_binaries or {})
|
|
378
554
|
command_reg_raw_value = cfg.get("command_registration")
|
|
379
555
|
command_reg_raw: dict[str, Any] = (
|
|
@@ -385,9 +561,21 @@ class TelegramBotConfig:
|
|
|
385
561
|
enabled=command_reg_enabled, scopes=scopes
|
|
386
562
|
)
|
|
387
563
|
|
|
564
|
+
opencode_command = []
|
|
565
|
+
opencode_env_command = env.get("CAR_OPENCODE_COMMAND")
|
|
566
|
+
if opencode_env_command:
|
|
567
|
+
opencode_command = _parse_command(opencode_env_command)
|
|
568
|
+
if not opencode_command:
|
|
569
|
+
opencode_command = _parse_command(cfg.get("opencode_command"))
|
|
570
|
+
|
|
388
571
|
state_file = Path(cfg.get("state_file", DEFAULT_STATE_FILE))
|
|
389
572
|
if not state_file.is_absolute():
|
|
390
573
|
state_file = (root / state_file).resolve()
|
|
574
|
+
if state_file.suffix == ".json":
|
|
575
|
+
raise TelegramBotConfigError(
|
|
576
|
+
"telegram_bot.state_file must point to a SQLite database "
|
|
577
|
+
"(.sqlite3). Update your config to .codex-autorunner/telegram_state.sqlite3"
|
|
578
|
+
)
|
|
391
579
|
|
|
392
580
|
app_server_command_env = str(
|
|
393
581
|
cfg.get("app_server_command_env", "CAR_TELEGRAM_APP_SERVER_COMMAND")
|
|
@@ -440,6 +628,30 @@ class TelegramBotConfig:
|
|
|
440
628
|
if app_server_turn_timeout_seconds <= 0:
|
|
441
629
|
app_server_turn_timeout_seconds = None
|
|
442
630
|
|
|
631
|
+
agent_timeouts_raw = cfg.get("agent_timeouts")
|
|
632
|
+
has_explicit_codex_timeout = False
|
|
633
|
+
agent_timeouts: dict[str, Optional[float]] = dict(
|
|
634
|
+
DEFAULT_AGENT_TURN_TIMEOUT_SECONDS
|
|
635
|
+
)
|
|
636
|
+
if isinstance(agent_timeouts_raw, dict):
|
|
637
|
+
for key, value in agent_timeouts_raw.items():
|
|
638
|
+
if str(key) == "codex":
|
|
639
|
+
has_explicit_codex_timeout = True
|
|
640
|
+
if value is None:
|
|
641
|
+
agent_timeouts[str(key)] = None
|
|
642
|
+
continue
|
|
643
|
+
try:
|
|
644
|
+
timeout_value = float(value)
|
|
645
|
+
except (TypeError, ValueError):
|
|
646
|
+
continue
|
|
647
|
+
if timeout_value <= 0:
|
|
648
|
+
agent_timeouts[str(key)] = None
|
|
649
|
+
else:
|
|
650
|
+
agent_timeouts[str(key)] = timeout_value
|
|
651
|
+
|
|
652
|
+
if not has_explicit_codex_timeout:
|
|
653
|
+
agent_timeouts["codex"] = app_server_turn_timeout_seconds
|
|
654
|
+
|
|
443
655
|
polling_raw_value = cfg.get("polling")
|
|
444
656
|
polling_raw: dict[str, Any] = (
|
|
445
657
|
polling_raw_value if isinstance(polling_raw_value, dict) else {}
|
|
@@ -472,12 +684,15 @@ class TelegramBotConfig:
|
|
|
472
684
|
allowed_chat_ids=allowed_chat_ids,
|
|
473
685
|
allowed_user_ids=allowed_user_ids,
|
|
474
686
|
require_topics=require_topics,
|
|
687
|
+
trigger_mode=trigger_mode,
|
|
475
688
|
defaults=defaults,
|
|
476
689
|
concurrency=concurrency,
|
|
477
690
|
media=media,
|
|
478
691
|
shell=shell,
|
|
692
|
+
cache=cache,
|
|
479
693
|
progress_stream=progress_stream,
|
|
480
694
|
command_registration=command_registration,
|
|
695
|
+
opencode_command=opencode_command,
|
|
481
696
|
state_file=state_file,
|
|
482
697
|
app_server_command_env=app_server_command_env,
|
|
483
698
|
app_server_command=app_server_command,
|
|
@@ -486,6 +701,7 @@ class TelegramBotConfig:
|
|
|
486
701
|
app_server_start_timeout_seconds=app_server_start_timeout_seconds,
|
|
487
702
|
app_server_start_max_attempts=app_server_start_max_attempts,
|
|
488
703
|
app_server_turn_timeout_seconds=app_server_turn_timeout_seconds,
|
|
704
|
+
agent_turn_timeout_seconds=agent_timeouts,
|
|
489
705
|
poll_timeout_seconds=poll_timeout_seconds,
|
|
490
706
|
poll_request_timeout_seconds=poll_request_timeout_seconds,
|
|
491
707
|
poll_allowed_updates=poll_allowed_updates,
|
|
@@ -493,6 +709,9 @@ class TelegramBotConfig:
|
|
|
493
709
|
metrics_mode=metrics_mode,
|
|
494
710
|
coalesce_window_seconds=coalesce_window_seconds,
|
|
495
711
|
agent_binaries=agent_binaries,
|
|
712
|
+
ticket_flow_auto_resume=ticket_flow_auto_resume,
|
|
713
|
+
pause_dispatch_notifications=pause_dispatch_notifications,
|
|
714
|
+
default_notification_chat_id=default_notification_chat_id,
|
|
496
715
|
)
|
|
497
716
|
|
|
498
717
|
def validate(self) -> None:
|
|
@@ -516,6 +735,8 @@ class TelegramBotConfig:
|
|
|
516
735
|
issues.append(
|
|
517
736
|
"poll_request_timeout_seconds must be greater than poll_timeout_seconds"
|
|
518
737
|
)
|
|
738
|
+
if self.trigger_mode not in TRIGGER_MODE_OPTIONS:
|
|
739
|
+
issues.append(f"trigger_mode must be one of {sorted(TRIGGER_MODE_OPTIONS)}")
|
|
519
740
|
if issues:
|
|
520
741
|
raise TelegramBotConfigError("; ".join(issues))
|
|
521
742
|
|
|
@@ -18,8 +18,12 @@ RESUME_REFRESH_LIMIT = 10
|
|
|
18
18
|
TOKEN_USAGE_CACHE_LIMIT = 256
|
|
19
19
|
TOKEN_USAGE_TURN_CACHE_LIMIT = 512
|
|
20
20
|
DEFAULT_INTERRUPT_TIMEOUT_SECONDS = 30.0
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
DEFAULT_AGENT_TURN_TIMEOUT_SECONDS = {
|
|
24
|
+
"codex": 28800.0,
|
|
25
|
+
"opencode": 28800.0,
|
|
26
|
+
}
|
|
23
27
|
DEFAULT_AGENT = "codex"
|
|
24
28
|
APP_SERVER_START_BACKOFF_INITIAL_SECONDS = 1.0
|
|
25
29
|
APP_SERVER_START_BACKOFF_MAX_SECONDS = 30.0
|
|
@@ -61,6 +65,7 @@ UPDATE_PICKER_PROMPT = "Select update target (buttons below)."
|
|
|
61
65
|
REVIEW_COMMIT_PICKER_PROMPT = (
|
|
62
66
|
"Select a commit to review (buttons below or reply with number)."
|
|
63
67
|
)
|
|
68
|
+
FLOW_RUNS_PICKER_PROMPT = "Select a ticket flow run (buttons below)."
|
|
64
69
|
REVIEW_COMMIT_BUTTON_LABEL_LIMIT = 80
|
|
65
70
|
UPDATE_TARGET_OPTIONS = (
|
|
66
71
|
("both", "Both (web + Telegram)"),
|
|
@@ -100,6 +105,16 @@ TURN_PROGRESS_MAX_LEN = 160
|
|
|
100
105
|
TURN_PROGRESS_MIN_EDIT_INTERVAL_SECONDS = 1.0
|
|
101
106
|
TURN_PROGRESS_TTL_SECONDS = 900.0
|
|
102
107
|
PROGRESS_HEARTBEAT_INTERVAL_SECONDS = 5.0
|
|
108
|
+
COMPACT_MAX_ACTIONS = 10
|
|
109
|
+
COMPACT_MAX_TEXT_LENGTH = 80
|
|
110
|
+
STATUS_ICONS = {
|
|
111
|
+
"done": "✓",
|
|
112
|
+
"fail": "✗",
|
|
113
|
+
"warn": "⚠",
|
|
114
|
+
"running": "▸",
|
|
115
|
+
"update": "↻",
|
|
116
|
+
"thinking": "🧠",
|
|
117
|
+
}
|
|
103
118
|
COMMAND_DISABLED_TEMPLATE = "'/{name}' is disabled while a task is in progress."
|
|
104
119
|
MAX_MENTION_BYTES = 200_000
|
|
105
120
|
VALID_REASONING_EFFORTS = {"none", "minimal", "low", "medium", "high", "xhigh"}
|
|
@@ -72,14 +72,26 @@ def _log_denied(handlers: Any, update: TelegramUpdate) -> None:
|
|
|
72
72
|
chat_id = None
|
|
73
73
|
user_id = None
|
|
74
74
|
thread_id = None
|
|
75
|
+
message_id = None
|
|
76
|
+
update_id = None
|
|
77
|
+
conversation_id = None
|
|
75
78
|
if update.message:
|
|
76
79
|
chat_id = update.message.chat_id
|
|
77
80
|
user_id = update.message.from_user_id
|
|
78
81
|
thread_id = update.message.thread_id
|
|
82
|
+
message_id = update.message.message_id
|
|
83
|
+
update_id = update.message.update_id
|
|
79
84
|
elif update.callback:
|
|
80
85
|
chat_id = update.callback.chat_id
|
|
81
86
|
user_id = update.callback.from_user_id
|
|
82
87
|
thread_id = update.callback.thread_id
|
|
88
|
+
message_id = update.callback.message_id
|
|
89
|
+
update_id = update.callback.update_id
|
|
90
|
+
if chat_id is not None:
|
|
91
|
+
try:
|
|
92
|
+
conversation_id = topic_key(chat_id, thread_id)
|
|
93
|
+
except Exception:
|
|
94
|
+
conversation_id = None
|
|
83
95
|
log_event(
|
|
84
96
|
handlers._logger,
|
|
85
97
|
logging.INFO,
|
|
@@ -87,6 +99,9 @@ def _log_denied(handlers: Any, update: TelegramUpdate) -> None:
|
|
|
87
99
|
chat_id=chat_id,
|
|
88
100
|
user_id=user_id,
|
|
89
101
|
thread_id=thread_id,
|
|
102
|
+
message_id=message_id,
|
|
103
|
+
update_id=update_id,
|
|
104
|
+
conversation_id=conversation_id,
|
|
90
105
|
)
|
|
91
106
|
|
|
92
107
|
|
|
@@ -172,6 +187,7 @@ async def dispatch_update(handlers: Any, update: TelegramUpdate) -> None:
|
|
|
172
187
|
has_message=bool(update.message),
|
|
173
188
|
has_callback=bool(update.callback),
|
|
174
189
|
update_received_at=now_iso(),
|
|
190
|
+
conversation_id=conversation_id,
|
|
175
191
|
)
|
|
176
192
|
if (
|
|
177
193
|
update.update_id is not None
|
|
@@ -188,6 +204,7 @@ async def dispatch_update(handlers: Any, update: TelegramUpdate) -> None:
|
|
|
188
204
|
chat_id=context.chat_id,
|
|
189
205
|
thread_id=context.thread_id,
|
|
190
206
|
message_id=context.message_id,
|
|
207
|
+
conversation_id=conversation_id,
|
|
191
208
|
)
|
|
192
209
|
return
|
|
193
210
|
if not allowlist_allows(update, handlers._allowlist):
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Telegram integration doctor checks."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict, Union
|
|
4
|
+
|
|
5
|
+
from ...core.config import HubConfig, RepoConfig
|
|
6
|
+
from ...core.engine import DoctorCheck
|
|
7
|
+
from ...core.optional_dependencies import missing_optional_dependencies
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def telegram_doctor_checks(
|
|
11
|
+
config: Union[HubConfig, RepoConfig, Dict[str, Any]],
|
|
12
|
+
) -> list[DoctorCheck]:
|
|
13
|
+
"""Run Telegram-specific doctor checks.
|
|
14
|
+
|
|
15
|
+
Returns a list of DoctorCheck objects for Telegram integration.
|
|
16
|
+
Works with HubConfig, RepoConfig, or raw dict.
|
|
17
|
+
"""
|
|
18
|
+
checks: list[DoctorCheck] = []
|
|
19
|
+
telegram_cfg = None
|
|
20
|
+
|
|
21
|
+
if isinstance(config, dict):
|
|
22
|
+
telegram_cfg = config.get("telegram_bot")
|
|
23
|
+
elif isinstance(config.raw, dict):
|
|
24
|
+
telegram_cfg = config.raw.get("telegram_bot")
|
|
25
|
+
|
|
26
|
+
if isinstance(telegram_cfg, dict) and telegram_cfg.get("enabled") is True:
|
|
27
|
+
missing_telegram = missing_optional_dependencies((("httpx", "httpx"),))
|
|
28
|
+
if missing_telegram:
|
|
29
|
+
deps_list = ", ".join(missing_telegram)
|
|
30
|
+
checks.append(
|
|
31
|
+
DoctorCheck(
|
|
32
|
+
check_id="telegram.dependencies",
|
|
33
|
+
status="error",
|
|
34
|
+
message=f"Telegram is enabled but missing optional deps: {deps_list}",
|
|
35
|
+
fix="Install with `pip install codex-autorunner[telegram]`.",
|
|
36
|
+
)
|
|
37
|
+
)
|
|
38
|
+
else:
|
|
39
|
+
checks.append(
|
|
40
|
+
DoctorCheck(
|
|
41
|
+
check_id="telegram.dependencies",
|
|
42
|
+
status="ok",
|
|
43
|
+
message="Telegram dependencies are installed.",
|
|
44
|
+
)
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
return checks
|
|
@@ -9,9 +9,10 @@ from ..adapter import (
|
|
|
9
9
|
CancelCallback,
|
|
10
10
|
CompactCallback,
|
|
11
11
|
EffortCallback,
|
|
12
|
+
FlowCallback,
|
|
13
|
+
FlowRunCallback,
|
|
12
14
|
ModelCallback,
|
|
13
15
|
PageCallback,
|
|
14
|
-
PrFlowStartCallback,
|
|
15
16
|
QuestionCancelCallback,
|
|
16
17
|
QuestionCustomCallback,
|
|
17
18
|
QuestionDoneCallback,
|
|
@@ -80,9 +81,6 @@ async def handle_callback(handlers: Any, callback: TelegramCallbackQuery) -> Non
|
|
|
80
81
|
elif isinstance(parsed, ReviewCommitCallback):
|
|
81
82
|
if key:
|
|
82
83
|
await handlers._handle_review_commit_callback(key, callback, parsed)
|
|
83
|
-
elif isinstance(parsed, PrFlowStartCallback):
|
|
84
|
-
if key:
|
|
85
|
-
await handlers._handle_pr_flow_start_callback(key, callback, parsed)
|
|
86
84
|
elif isinstance(parsed, CancelCallback):
|
|
87
85
|
if key:
|
|
88
86
|
if parsed.kind == "interrupt":
|
|
@@ -95,3 +93,8 @@ async def handle_callback(handlers: Any, callback: TelegramCallbackQuery) -> Non
|
|
|
95
93
|
elif isinstance(parsed, PageCallback):
|
|
96
94
|
if key:
|
|
97
95
|
await handlers._handle_selection_page(key, parsed, callback)
|
|
96
|
+
elif isinstance(parsed, FlowCallback):
|
|
97
|
+
await handlers._handle_flow_callback(callback, parsed)
|
|
98
|
+
elif isinstance(parsed, FlowRunCallback):
|
|
99
|
+
if key:
|
|
100
|
+
await handlers._handle_flow_run_callback(key, callback, parsed)
|
|
@@ -7,6 +7,7 @@ from ..commands_spec import CommandSpec, build_command_specs
|
|
|
7
7
|
from .approvals import ApprovalsCommands
|
|
8
8
|
from .execution import ExecutionCommands
|
|
9
9
|
from .files import FilesCommands
|
|
10
|
+
from .flows import FlowCommands
|
|
10
11
|
from .formatting import FormattingHelpers
|
|
11
12
|
from .github import GitHubCommands
|
|
12
13
|
from .shared import SharedHelpers
|
|
@@ -19,6 +20,7 @@ __all__ = [
|
|
|
19
20
|
"GitHubCommands",
|
|
20
21
|
"FilesCommands",
|
|
21
22
|
"VoiceCommands",
|
|
23
|
+
"FlowCommands",
|
|
22
24
|
"ExecutionCommands",
|
|
23
25
|
"ApprovalsCommands",
|
|
24
26
|
"FormattingHelpers",
|