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
@@ -0,0 +1,25 @@
1
+ from .controller import FlowController
2
+ from .definition import FlowDefinition, StepFn, StepOutcome
3
+ from .models import (
4
+ FlowArtifact,
5
+ FlowEvent,
6
+ FlowEventType,
7
+ FlowRunRecord,
8
+ FlowRunStatus,
9
+ )
10
+ from .runtime import FlowRuntime
11
+ from .store import FlowStore
12
+
13
+ __all__ = [
14
+ "FlowController",
15
+ "FlowDefinition",
16
+ "StepFn",
17
+ "StepOutcome",
18
+ "FlowArtifact",
19
+ "FlowEvent",
20
+ "FlowEventType",
21
+ "FlowRunRecord",
22
+ "FlowRunStatus",
23
+ "FlowRuntime",
24
+ "FlowStore",
25
+ ]
@@ -0,0 +1,178 @@
1
+ import asyncio
2
+ import logging
3
+ import uuid
4
+ from pathlib import Path
5
+ from typing import Any, AsyncGenerator, Callable, Dict, Optional, Set
6
+
7
+ from .definition import FlowDefinition
8
+ from .models import FlowEvent, FlowRunRecord, FlowRunStatus
9
+ from .runtime import FlowRuntime
10
+ from .store import FlowStore
11
+
12
+ _logger = logging.getLogger(__name__)
13
+
14
+
15
+ class FlowController:
16
+ def __init__(
17
+ self,
18
+ definition: FlowDefinition,
19
+ db_path: Path,
20
+ artifacts_root: Path,
21
+ ):
22
+ self.definition = definition
23
+ self.db_path = db_path
24
+ self.artifacts_root = artifacts_root
25
+ self.store = FlowStore(db_path)
26
+ self._event_listeners: Set[Callable[[FlowEvent], None]] = set()
27
+ self._lock = asyncio.Lock()
28
+
29
+ def initialize(self) -> None:
30
+ self.artifacts_root.mkdir(parents=True, exist_ok=True)
31
+ self.store.initialize()
32
+
33
+ def shutdown(self) -> None:
34
+ self.store.close()
35
+
36
+ async def start_flow(
37
+ self,
38
+ input_data: Dict[str, Any],
39
+ run_id: Optional[str] = None,
40
+ initial_state: Optional[Dict[str, Any]] = None,
41
+ metadata: Optional[Dict[str, Any]] = None,
42
+ ) -> FlowRunRecord:
43
+ """Create a new flow run record without executing the flow."""
44
+ if run_id is None:
45
+ run_id = str(uuid.uuid4())
46
+
47
+ async with self._lock:
48
+ existing = self.store.get_flow_run(run_id)
49
+ if existing:
50
+ raise ValueError(f"Flow run {run_id} already exists")
51
+
52
+ self._prepare_artifacts_dir(run_id)
53
+
54
+ record = self.store.create_flow_run(
55
+ run_id=run_id,
56
+ flow_type=self.definition.flow_type,
57
+ input_data=input_data,
58
+ metadata=metadata,
59
+ state=initial_state or {},
60
+ current_step=self.definition.initial_step,
61
+ )
62
+
63
+ return record
64
+
65
+ async def run_flow(
66
+ self, run_id: str, initial_state: Optional[Dict[str, Any]] = None
67
+ ) -> FlowRunRecord:
68
+ """Run or resume a flow to completion in-process (used by workers/tests)."""
69
+ runtime = FlowRuntime(
70
+ definition=self.definition,
71
+ store=self.store,
72
+ emit_event=self._emit_event,
73
+ )
74
+ return await runtime.run_flow(run_id=run_id, initial_state=initial_state)
75
+
76
+ async def stop_flow(self, run_id: str) -> FlowRunRecord:
77
+ record = self.store.set_stop_requested(run_id, True)
78
+ if not record:
79
+ raise ValueError(f"Flow run {run_id} not found")
80
+
81
+ if record.status == FlowRunStatus.RUNNING:
82
+ updated = self.store.update_flow_run_status(
83
+ run_id=run_id,
84
+ status=FlowRunStatus.STOPPING,
85
+ )
86
+ if updated:
87
+ record = updated
88
+
89
+ updated = self.store.get_flow_run(run_id)
90
+ if not updated:
91
+ raise RuntimeError(f"Failed to get record for run {run_id}")
92
+ return updated
93
+
94
+ async def resume_flow(self, run_id: str) -> FlowRunRecord:
95
+ async with self._lock:
96
+ record = self.store.get_flow_run(run_id)
97
+ if not record:
98
+ raise ValueError(f"Flow run {run_id} not found")
99
+
100
+ if record.status == FlowRunStatus.RUNNING:
101
+ raise ValueError(f"Flow run {run_id} is already active")
102
+
103
+ cleared = self.store.set_stop_requested(run_id, False)
104
+ if not cleared:
105
+ raise RuntimeError(f"Failed to clear stop flag for run {run_id}")
106
+ return cleared
107
+
108
+ def get_status(self, run_id: str) -> Optional[FlowRunRecord]:
109
+ return self.store.get_flow_run(run_id)
110
+
111
+ def list_runs(self, status: Optional[FlowRunStatus] = None) -> list[FlowRunRecord]:
112
+ return self.store.list_flow_runs(
113
+ flow_type=self.definition.flow_type, status=status
114
+ )
115
+
116
+ async def stream_events(
117
+ self, run_id: str, after_seq: Optional[int] = None
118
+ ) -> AsyncGenerator[FlowEvent, None]:
119
+ last_seq = after_seq
120
+
121
+ while True:
122
+ events = self.store.get_events(
123
+ run_id=run_id,
124
+ after_seq=last_seq,
125
+ limit=100,
126
+ )
127
+
128
+ for event in events:
129
+ yield event
130
+ last_seq = event.seq
131
+
132
+ record = self.store.get_flow_run(run_id)
133
+ if (
134
+ record
135
+ and (record.status.is_terminal() or record.status.is_paused())
136
+ and not events
137
+ ):
138
+ break
139
+
140
+ await asyncio.sleep(0.5)
141
+
142
+ def get_events(
143
+ self, run_id: str, after_seq: Optional[int] = None
144
+ ) -> list[FlowEvent]:
145
+ return self.store.get_events(run_id=run_id, after_seq=after_seq)
146
+
147
+ def add_event_listener(self, listener: Callable[[FlowEvent], None]) -> None:
148
+ self._event_listeners.add(listener)
149
+
150
+ def remove_event_listener(self, listener: Callable[[FlowEvent], None]) -> None:
151
+ self._event_listeners.discard(listener)
152
+
153
+ def _emit_event(self, event: FlowEvent) -> None:
154
+ for listener in self._event_listeners:
155
+ try:
156
+ listener(event)
157
+ except Exception as e:
158
+ _logger.exception("Error in event listener: %s", e)
159
+
160
+ def _prepare_artifacts_dir(self, run_id: str) -> Path:
161
+ artifacts_dir = self.artifacts_root / run_id
162
+ artifacts_dir.mkdir(parents=True, exist_ok=True)
163
+ return artifacts_dir
164
+
165
+ def get_artifacts_dir(self, run_id: str) -> Optional[Path]:
166
+ artifacts_dir = self.artifacts_root / run_id
167
+ if artifacts_dir.exists():
168
+ return artifacts_dir
169
+ return None
170
+
171
+ def get_artifacts(self, run_id: str) -> list:
172
+ return self.store.get_artifacts(run_id)
173
+
174
+ async def stream_events_since(
175
+ self, run_id: str, start_seq: Optional[int] = None
176
+ ) -> AsyncGenerator[FlowEvent, None]:
177
+ async for event in self.stream_events(run_id, after_seq=start_seq):
178
+ yield event
@@ -0,0 +1,82 @@
1
+ import asyncio
2
+ import logging
3
+ from typing import Any, Awaitable, Callable, Dict, Optional, Set, Union
4
+
5
+ from .models import FlowEventType, FlowRunRecord, FlowRunStatus
6
+
7
+ _logger = logging.getLogger(__name__)
8
+
9
+
10
+ class StepOutcome:
11
+ def __init__(
12
+ self,
13
+ status: FlowRunStatus,
14
+ next_steps: Optional[Set[str]] = None,
15
+ output: Optional[Dict[str, Any]] = None,
16
+ error: Optional[str] = None,
17
+ ):
18
+ self.status = status
19
+ self.next_steps = next_steps or set()
20
+ self.output = output or {}
21
+ self.error = error
22
+
23
+ @classmethod
24
+ def continue_to(
25
+ cls, next_steps: Set[str], output: Optional[Dict[str, Any]] = None
26
+ ) -> "StepOutcome":
27
+ return cls(status=FlowRunStatus.RUNNING, next_steps=next_steps, output=output)
28
+
29
+ @classmethod
30
+ def complete(cls, output: Optional[Dict[str, Any]] = None) -> "StepOutcome":
31
+ return cls(status=FlowRunStatus.COMPLETED, output=output)
32
+
33
+ @classmethod
34
+ def fail(cls, error: str, output: Optional[Dict[str, Any]] = None) -> "StepOutcome":
35
+ return cls(status=FlowRunStatus.FAILED, error=error, output=output)
36
+
37
+ @classmethod
38
+ def stop(cls, output: Optional[Dict[str, Any]] = None) -> "StepOutcome":
39
+ return cls(status=FlowRunStatus.STOPPED, output=output)
40
+
41
+ @classmethod
42
+ def pause(cls, output: Optional[Dict[str, Any]] = None) -> "StepOutcome":
43
+ return cls(status=FlowRunStatus.PAUSED, output=output)
44
+
45
+
46
+ EmitEventFn = Callable[[FlowEventType, Dict[str, Any]], None]
47
+ StepFn2 = Callable[[FlowRunRecord, Dict[str, Any]], Awaitable[StepOutcome]]
48
+ StepFn3 = Callable[
49
+ [FlowRunRecord, Dict[str, Any], Optional[EmitEventFn]], Awaitable[StepOutcome]
50
+ ]
51
+ StepFn = Union[StepFn2, StepFn3]
52
+
53
+
54
+ class FlowDefinition:
55
+ def __init__(
56
+ self,
57
+ flow_type: str,
58
+ initial_step: str,
59
+ steps: Dict[str, StepFn],
60
+ *,
61
+ name: Optional[str] = None,
62
+ description: Optional[str] = None,
63
+ input_schema: Optional[Dict[str, Any]] = None,
64
+ ):
65
+ self.flow_type = flow_type
66
+ self.initial_step = initial_step
67
+ self.steps = steps
68
+ self.name = name or flow_type
69
+ self.description = description
70
+ self.input_schema = input_schema
71
+
72
+ def validate(self) -> None:
73
+ if self.initial_step not in self.steps:
74
+ raise ValueError(
75
+ f"Initial step '{self.initial_step}' not found in steps: {list(self.steps.keys())}"
76
+ )
77
+
78
+ for step_id, step_fn in self.steps.items():
79
+ if not asyncio.iscoroutinefunction(step_fn):
80
+ raise ValueError(
81
+ f"Step function for '{step_id}' must be async (coroutine function)"
82
+ )
@@ -0,0 +1,75 @@
1
+ import logging
2
+ from enum import Enum
3
+ from typing import Any, Dict, Optional
4
+
5
+ from pydantic import BaseModel, Field
6
+
7
+ _logger = logging.getLogger(__name__)
8
+
9
+
10
+ class FlowRunStatus(str, Enum):
11
+ PENDING = "pending"
12
+ RUNNING = "running"
13
+ PAUSED = "paused"
14
+ STOPPING = "stopping"
15
+ STOPPED = "stopped"
16
+ COMPLETED = "completed"
17
+ FAILED = "failed"
18
+
19
+ def is_terminal(self) -> bool:
20
+ return self in {self.COMPLETED, self.FAILED, self.STOPPED}
21
+
22
+ def is_active(self) -> bool:
23
+ return self in {self.PENDING, self.RUNNING, self.STOPPING}
24
+
25
+ def is_paused(self) -> bool:
26
+ return self == self.PAUSED
27
+
28
+
29
+ class FlowEventType(str, Enum):
30
+ STEP_STARTED = "step_started"
31
+ STEP_PROGRESS = "step_progress"
32
+ STEP_COMPLETED = "step_completed"
33
+ STEP_FAILED = "step_failed"
34
+ AGENT_STREAM_DELTA = "agent_stream_delta"
35
+ APP_SERVER_EVENT = "app_server_event"
36
+ TOKEN_USAGE = "token_usage"
37
+ FLOW_STARTED = "flow_started"
38
+ FLOW_STOPPED = "flow_stopped"
39
+ FLOW_RESUMED = "flow_resumed"
40
+ FLOW_COMPLETED = "flow_completed"
41
+ FLOW_FAILED = "flow_failed"
42
+
43
+
44
+ class FlowRunRecord(BaseModel):
45
+ id: str
46
+ flow_type: str
47
+ status: FlowRunStatus
48
+ input_data: Dict[str, Any] = Field(default_factory=dict)
49
+ state: Dict[str, Any] = Field(default_factory=dict)
50
+ current_step: Optional[str] = None
51
+ stop_requested: bool = False
52
+ created_at: str
53
+ started_at: Optional[str] = None
54
+ finished_at: Optional[str] = None
55
+ error_message: Optional[str] = None
56
+ metadata: Dict[str, Any] = Field(default_factory=dict)
57
+
58
+
59
+ class FlowEvent(BaseModel):
60
+ seq: int
61
+ id: str
62
+ run_id: str
63
+ event_type: FlowEventType
64
+ timestamp: str
65
+ data: Dict[str, Any] = Field(default_factory=dict)
66
+ step_id: Optional[str] = None
67
+
68
+
69
+ class FlowArtifact(BaseModel):
70
+ id: str
71
+ run_id: str
72
+ kind: str
73
+ path: str
74
+ created_at: str
75
+ metadata: Dict[str, Any] = Field(default_factory=dict)