bazaar-compute-node 0.1.3__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.
- bazaar_compute_node/__init__.py +3 -0
- bazaar_compute_node/app/__init__.py +1 -0
- bazaar_compute_node/app/application.py +398 -0
- bazaar_compute_node/app/attachments.py +154 -0
- bazaar_compute_node/app/command.py +342 -0
- bazaar_compute_node/app/config.py +121 -0
- bazaar_compute_node/app/registry.py +120 -0
- bazaar_compute_node/app/transport.py +264 -0
- bazaar_compute_node/app/windows_pipe.py +463 -0
- bazaar_compute_node/app/wrapper.py +63 -0
- bazaar_compute_node/bcc.py +524 -0
- bazaar_compute_node/cli.py +382 -0
- bazaar_compute_node/contrib/__init__.py +1 -0
- bazaar_compute_node/contrib/codex_app_server/__init__.py +63 -0
- bazaar_compute_node/contrib/codex_app_server/approval.py +168 -0
- bazaar_compute_node/contrib/codex_app_server/client.py +408 -0
- bazaar_compute_node/contrib/codex_app_server/events.py +431 -0
- bazaar_compute_node/contrib/codex_app_server/plugin.py +15 -0
- bazaar_compute_node/contrib/codex_app_server/process.py +583 -0
- bazaar_compute_node/contrib/codex_app_server/protocol.py +103 -0
- bazaar_compute_node/contrib/codex_app_server/runtime.py +513 -0
- bazaar_compute_node/contrib/logging/__init__.py +5 -0
- bazaar_compute_node/contrib/logging/audit.py +61 -0
- bazaar_compute_node/contrib/logging/plugin.py +11 -0
- bazaar_compute_node/contrib/sqlite/__init__.py +14 -0
- bazaar_compute_node/contrib/sqlite/codec.py +768 -0
- bazaar_compute_node/contrib/sqlite/database.py +282 -0
- bazaar_compute_node/contrib/sqlite/migrations.py +646 -0
- bazaar_compute_node/contrib/sqlite/plugin.py +11 -0
- bazaar_compute_node/contrib/sqlite/repository.py +1059 -0
- bazaar_compute_node/contrib/wecom/__init__.py +1 -0
- bazaar_compute_node/contrib/wecom/channel.py +960 -0
- bazaar_compute_node/contrib/wecom/markdown.py +146 -0
- bazaar_compute_node/contrib/wecom/plugin.py +29 -0
- bazaar_compute_node/core/__init__.py +5 -0
- bazaar_compute_node/core/approval.py +51 -0
- bazaar_compute_node/core/audit.py +101 -0
- bazaar_compute_node/core/channel.py +121 -0
- bazaar_compute_node/core/client.py +30 -0
- bazaar_compute_node/core/command.py +85 -0
- bazaar_compute_node/core/concurrency.py +29 -0
- bazaar_compute_node/core/correlation.py +48 -0
- bazaar_compute_node/core/instruction.py +224 -0
- bazaar_compute_node/core/lifecycle.py +48 -0
- bazaar_compute_node/core/models/__init__.py +63 -0
- bazaar_compute_node/core/models/entities.py +514 -0
- bazaar_compute_node/core/models/states.py +369 -0
- bazaar_compute_node/core/observability.py +47 -0
- bazaar_compute_node/core/orchestration/__init__.py +5 -0
- bazaar_compute_node/core/orchestration/command.py +614 -0
- bazaar_compute_node/core/orchestration/services.py +135 -0
- bazaar_compute_node/core/orchestration/session.py +891 -0
- bazaar_compute_node/core/orchestration/turn.py +451 -0
- bazaar_compute_node/core/outcomes.py +51 -0
- bazaar_compute_node/core/paths.py +19 -0
- bazaar_compute_node/core/runtime.py +118 -0
- bazaar_compute_node/core/storage.py +167 -0
- bazaar_compute_node-0.1.3.dist-info/METADATA +178 -0
- bazaar_compute_node-0.1.3.dist-info/RECORD +62 -0
- bazaar_compute_node-0.1.3.dist-info/WHEEL +4 -0
- bazaar_compute_node-0.1.3.dist-info/entry_points.txt +15 -0
- bazaar_compute_node-0.1.3.dist-info/licenses/LICENSE +613 -0
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Mapping
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from enum import Enum, StrEnum
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AgentState(StrEnum):
|
|
9
|
+
"""Provider-neutral lifecycle state for one bcn agent session."""
|
|
10
|
+
|
|
11
|
+
CREATED = "created"
|
|
12
|
+
STARTING = "starting"
|
|
13
|
+
IDLE = "idle"
|
|
14
|
+
WORKING = "working"
|
|
15
|
+
COMPACTION_STARTING = "compaction_starting"
|
|
16
|
+
COMPACTING = "compacting"
|
|
17
|
+
COMPACTION_COMPLETED = "compaction_completed"
|
|
18
|
+
STOPPING = "stopping"
|
|
19
|
+
FAILED = "failed"
|
|
20
|
+
UNKNOWN = "unknown"
|
|
21
|
+
RECONCILING = "reconciling"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ChannelTargetKind(StrEnum):
|
|
25
|
+
DM = "dm"
|
|
26
|
+
GROUP = "group"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class AgentTickSource(StrEnum):
|
|
30
|
+
"""Origin of an observation; the orchestrator remains the state writer."""
|
|
31
|
+
|
|
32
|
+
SESSION = "session"
|
|
33
|
+
CHANNEL = "channel"
|
|
34
|
+
RUNTIME = "runtime"
|
|
35
|
+
RECOVERY = "recovery"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class AgentSignal(StrEnum):
|
|
39
|
+
"""Provider-neutral facts that the core reducer can apply to an agent."""
|
|
40
|
+
|
|
41
|
+
START_REQUESTED = "start_requested"
|
|
42
|
+
START_CONFIRMED = "start_confirmed"
|
|
43
|
+
TURN_STARTED = "turn_started"
|
|
44
|
+
TURN_COMPLETED = "turn_completed"
|
|
45
|
+
TURN_FAILED = "turn_failed"
|
|
46
|
+
TURN_CANCELLED = "turn_cancelled"
|
|
47
|
+
WORKING_OBSERVED = "working_observed"
|
|
48
|
+
COMPACTION_STARTED = "compaction_started"
|
|
49
|
+
COMPACTION_IN_PROGRESS = "compaction_in_progress"
|
|
50
|
+
COMPACTION_COMPLETED = "compaction_completed"
|
|
51
|
+
STOP_REQUESTED = "stop_requested"
|
|
52
|
+
FAILED = "failed"
|
|
53
|
+
UNKNOWN = "unknown"
|
|
54
|
+
RECONCILE_REQUESTED = "reconcile_requested"
|
|
55
|
+
RECONCILE_CONFIRMED = "reconcile_confirmed"
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclass(frozen=True, slots=True)
|
|
59
|
+
class AgentTick:
|
|
60
|
+
"""An immutable, provider-neutral lifecycle observation."""
|
|
61
|
+
|
|
62
|
+
source: AgentTickSource
|
|
63
|
+
signal: AgentSignal
|
|
64
|
+
observed_at_ms: int
|
|
65
|
+
error_kind: str | None = None
|
|
66
|
+
error_message: str | None = None
|
|
67
|
+
|
|
68
|
+
def __post_init__(self) -> None:
|
|
69
|
+
if not isinstance(self.source, AgentTickSource):
|
|
70
|
+
raise TypeError("agent tick source is invalid")
|
|
71
|
+
if not isinstance(self.signal, AgentSignal):
|
|
72
|
+
raise TypeError("agent tick signal is invalid")
|
|
73
|
+
if not isinstance(self.observed_at_ms, int) or self.observed_at_ms < 0:
|
|
74
|
+
raise ValueError("observed_at_ms must be a non-negative integer")
|
|
75
|
+
if self.error_kind is not None and (
|
|
76
|
+
not isinstance(self.error_kind, str) or not self.error_kind
|
|
77
|
+
):
|
|
78
|
+
raise ValueError("error_kind must be a non-empty string when provided")
|
|
79
|
+
if self.error_message is not None and not isinstance(self.error_message, str):
|
|
80
|
+
raise TypeError("error_message must be a string when provided")
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
AGENT_TICK_TRANSITIONS: Mapping[AgentState, Mapping[AgentSignal, AgentState]] = {
|
|
84
|
+
AgentState.CREATED: {
|
|
85
|
+
AgentSignal.START_REQUESTED: AgentState.STARTING,
|
|
86
|
+
AgentSignal.WORKING_OBSERVED: AgentState.WORKING,
|
|
87
|
+
AgentSignal.STOP_REQUESTED: AgentState.STOPPING,
|
|
88
|
+
AgentSignal.FAILED: AgentState.FAILED,
|
|
89
|
+
AgentSignal.UNKNOWN: AgentState.UNKNOWN,
|
|
90
|
+
},
|
|
91
|
+
AgentState.STARTING: {
|
|
92
|
+
AgentSignal.START_REQUESTED: AgentState.STARTING,
|
|
93
|
+
AgentSignal.START_CONFIRMED: AgentState.IDLE,
|
|
94
|
+
AgentSignal.WORKING_OBSERVED: AgentState.WORKING,
|
|
95
|
+
AgentSignal.STOP_REQUESTED: AgentState.STOPPING,
|
|
96
|
+
AgentSignal.FAILED: AgentState.FAILED,
|
|
97
|
+
AgentSignal.UNKNOWN: AgentState.UNKNOWN,
|
|
98
|
+
},
|
|
99
|
+
AgentState.IDLE: {
|
|
100
|
+
AgentSignal.START_CONFIRMED: AgentState.IDLE,
|
|
101
|
+
AgentSignal.WORKING_OBSERVED: AgentState.WORKING,
|
|
102
|
+
AgentSignal.TURN_STARTED: AgentState.WORKING,
|
|
103
|
+
AgentSignal.TURN_COMPLETED: AgentState.IDLE,
|
|
104
|
+
AgentSignal.TURN_FAILED: AgentState.IDLE,
|
|
105
|
+
AgentSignal.TURN_CANCELLED: AgentState.IDLE,
|
|
106
|
+
AgentSignal.COMPACTION_STARTED: AgentState.COMPACTION_STARTING,
|
|
107
|
+
AgentSignal.COMPACTION_IN_PROGRESS: AgentState.COMPACTING,
|
|
108
|
+
AgentSignal.COMPACTION_COMPLETED: AgentState.COMPACTION_COMPLETED,
|
|
109
|
+
AgentSignal.STOP_REQUESTED: AgentState.STOPPING,
|
|
110
|
+
AgentSignal.FAILED: AgentState.FAILED,
|
|
111
|
+
AgentSignal.UNKNOWN: AgentState.UNKNOWN,
|
|
112
|
+
AgentSignal.RECONCILE_CONFIRMED: AgentState.IDLE,
|
|
113
|
+
},
|
|
114
|
+
AgentState.WORKING: {
|
|
115
|
+
AgentSignal.WORKING_OBSERVED: AgentState.WORKING,
|
|
116
|
+
AgentSignal.TURN_STARTED: AgentState.WORKING,
|
|
117
|
+
AgentSignal.TURN_COMPLETED: AgentState.IDLE,
|
|
118
|
+
AgentSignal.TURN_FAILED: AgentState.IDLE,
|
|
119
|
+
AgentSignal.TURN_CANCELLED: AgentState.IDLE,
|
|
120
|
+
AgentSignal.COMPACTION_STARTED: AgentState.COMPACTION_STARTING,
|
|
121
|
+
AgentSignal.COMPACTION_IN_PROGRESS: AgentState.COMPACTING,
|
|
122
|
+
AgentSignal.COMPACTION_COMPLETED: AgentState.COMPACTION_COMPLETED,
|
|
123
|
+
AgentSignal.STOP_REQUESTED: AgentState.STOPPING,
|
|
124
|
+
AgentSignal.FAILED: AgentState.FAILED,
|
|
125
|
+
AgentSignal.UNKNOWN: AgentState.UNKNOWN,
|
|
126
|
+
},
|
|
127
|
+
AgentState.COMPACTION_STARTING: {
|
|
128
|
+
AgentSignal.WORKING_OBSERVED: AgentState.WORKING,
|
|
129
|
+
AgentSignal.COMPACTION_STARTED: AgentState.COMPACTION_STARTING,
|
|
130
|
+
AgentSignal.COMPACTION_IN_PROGRESS: AgentState.COMPACTING,
|
|
131
|
+
AgentSignal.COMPACTION_COMPLETED: AgentState.COMPACTION_COMPLETED,
|
|
132
|
+
AgentSignal.TURN_STARTED: AgentState.WORKING,
|
|
133
|
+
AgentSignal.TURN_COMPLETED: AgentState.IDLE,
|
|
134
|
+
AgentSignal.STOP_REQUESTED: AgentState.STOPPING,
|
|
135
|
+
AgentSignal.FAILED: AgentState.FAILED,
|
|
136
|
+
AgentSignal.UNKNOWN: AgentState.UNKNOWN,
|
|
137
|
+
},
|
|
138
|
+
AgentState.COMPACTING: {
|
|
139
|
+
AgentSignal.WORKING_OBSERVED: AgentState.WORKING,
|
|
140
|
+
AgentSignal.COMPACTION_STARTED: AgentState.COMPACTING,
|
|
141
|
+
AgentSignal.COMPACTION_IN_PROGRESS: AgentState.COMPACTING,
|
|
142
|
+
AgentSignal.COMPACTION_COMPLETED: AgentState.COMPACTION_COMPLETED,
|
|
143
|
+
AgentSignal.TURN_STARTED: AgentState.WORKING,
|
|
144
|
+
AgentSignal.TURN_COMPLETED: AgentState.IDLE,
|
|
145
|
+
AgentSignal.STOP_REQUESTED: AgentState.STOPPING,
|
|
146
|
+
AgentSignal.FAILED: AgentState.FAILED,
|
|
147
|
+
AgentSignal.UNKNOWN: AgentState.UNKNOWN,
|
|
148
|
+
},
|
|
149
|
+
AgentState.COMPACTION_COMPLETED: {
|
|
150
|
+
AgentSignal.WORKING_OBSERVED: AgentState.WORKING,
|
|
151
|
+
AgentSignal.COMPACTION_STARTED: AgentState.COMPACTION_STARTING,
|
|
152
|
+
AgentSignal.COMPACTION_IN_PROGRESS: AgentState.COMPACTING,
|
|
153
|
+
AgentSignal.COMPACTION_COMPLETED: AgentState.COMPACTION_COMPLETED,
|
|
154
|
+
AgentSignal.TURN_STARTED: AgentState.WORKING,
|
|
155
|
+
AgentSignal.TURN_COMPLETED: AgentState.IDLE,
|
|
156
|
+
AgentSignal.STOP_REQUESTED: AgentState.STOPPING,
|
|
157
|
+
AgentSignal.FAILED: AgentState.FAILED,
|
|
158
|
+
AgentSignal.UNKNOWN: AgentState.UNKNOWN,
|
|
159
|
+
},
|
|
160
|
+
AgentState.STOPPING: {
|
|
161
|
+
AgentSignal.STOP_REQUESTED: AgentState.STOPPING,
|
|
162
|
+
AgentSignal.FAILED: AgentState.FAILED,
|
|
163
|
+
AgentSignal.UNKNOWN: AgentState.UNKNOWN,
|
|
164
|
+
},
|
|
165
|
+
AgentState.FAILED: {
|
|
166
|
+
AgentSignal.START_REQUESTED: AgentState.STARTING,
|
|
167
|
+
AgentSignal.STOP_REQUESTED: AgentState.STOPPING,
|
|
168
|
+
AgentSignal.FAILED: AgentState.FAILED,
|
|
169
|
+
AgentSignal.TURN_FAILED: AgentState.FAILED,
|
|
170
|
+
AgentSignal.TURN_CANCELLED: AgentState.FAILED,
|
|
171
|
+
AgentSignal.UNKNOWN: AgentState.UNKNOWN,
|
|
172
|
+
},
|
|
173
|
+
AgentState.UNKNOWN: {
|
|
174
|
+
AgentSignal.RECONCILE_REQUESTED: AgentState.RECONCILING,
|
|
175
|
+
AgentSignal.STOP_REQUESTED: AgentState.STOPPING,
|
|
176
|
+
AgentSignal.UNKNOWN: AgentState.UNKNOWN,
|
|
177
|
+
},
|
|
178
|
+
AgentState.RECONCILING: {
|
|
179
|
+
AgentSignal.START_REQUESTED: AgentState.STARTING,
|
|
180
|
+
AgentSignal.START_CONFIRMED: AgentState.IDLE,
|
|
181
|
+
AgentSignal.WORKING_OBSERVED: AgentState.WORKING,
|
|
182
|
+
AgentSignal.RECONCILE_REQUESTED: AgentState.RECONCILING,
|
|
183
|
+
AgentSignal.RECONCILE_CONFIRMED: AgentState.IDLE,
|
|
184
|
+
AgentSignal.STOP_REQUESTED: AgentState.STOPPING,
|
|
185
|
+
AgentSignal.FAILED: AgentState.FAILED,
|
|
186
|
+
AgentSignal.UNKNOWN: AgentState.UNKNOWN,
|
|
187
|
+
},
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
AGENT_STATE_TRANSITIONS: Mapping[AgentState, frozenset[AgentState]] = {
|
|
192
|
+
current: frozenset(
|
|
193
|
+
target for target in signal_targets.values() if target is not current
|
|
194
|
+
)
|
|
195
|
+
for current, signal_targets in AGENT_TICK_TRANSITIONS.items()
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def reduce_agent_tick(current: AgentState, tick: AgentTick) -> AgentState:
|
|
200
|
+
"""Reduce one tick without mutating state or performing I/O."""
|
|
201
|
+
|
|
202
|
+
if not isinstance(current, AgentState):
|
|
203
|
+
raise TypeError("agent state is invalid")
|
|
204
|
+
if not isinstance(tick, AgentTick):
|
|
205
|
+
raise TypeError("agent tick is invalid")
|
|
206
|
+
target = AGENT_TICK_TRANSITIONS.get(current, {}).get(tick.signal)
|
|
207
|
+
if target is None:
|
|
208
|
+
raise StateTransitionError("agent", current, tick.signal)
|
|
209
|
+
ensure_transition("agent", current, target, AGENT_STATE_TRANSITIONS)
|
|
210
|
+
return target
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
class RuntimeTurnState(StrEnum):
|
|
214
|
+
STARTING = "starting"
|
|
215
|
+
RUNNING = "running"
|
|
216
|
+
COMPLETED = "completed"
|
|
217
|
+
FAILED = "failed"
|
|
218
|
+
CANCELLED = "cancelled"
|
|
219
|
+
UNKNOWN = "unknown"
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
class OutboundDeliveryState(StrEnum):
|
|
223
|
+
DRAFT = "draft"
|
|
224
|
+
PENDING = "pending"
|
|
225
|
+
QUEUED = "queued"
|
|
226
|
+
SENT = "sent"
|
|
227
|
+
PARTIAL = "partial"
|
|
228
|
+
FAILED = "failed"
|
|
229
|
+
UNKNOWN = "unknown"
|
|
230
|
+
REJECTED = "rejected"
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
class FreshCheckState(StrEnum):
|
|
234
|
+
REQUIRED = "required"
|
|
235
|
+
PASSED = "passed"
|
|
236
|
+
FAILED = "failed"
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
class RuntimeEventState(StrEnum):
|
|
240
|
+
STARTED = "started"
|
|
241
|
+
COMPLETED = "completed"
|
|
242
|
+
FAILED = "failed"
|
|
243
|
+
CANCELLED = "cancelled"
|
|
244
|
+
UNKNOWN = "unknown"
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
class StreamEventKind(StrEnum):
|
|
248
|
+
AGENT_MESSAGE_DELTA = "agent-message-delta"
|
|
249
|
+
PLAN_DELTA = "plan-delta"
|
|
250
|
+
REASONING_SUMMARY_DELTA = "reasoning-summary-delta"
|
|
251
|
+
REASONING_TEXT_DELTA = "reasoning-text-delta"
|
|
252
|
+
COMMAND_OUTPUT_DELTA = "command-output-delta"
|
|
253
|
+
COMMAND_INTERACTION = "command-interaction"
|
|
254
|
+
FILE_CHANGE_UPDATE = "file-change-update"
|
|
255
|
+
TOOL_PROGRESS = "tool-progress"
|
|
256
|
+
ITEM_PROGRESS = "item-progress"
|
|
257
|
+
TURN_PROGRESS = "turn-progress"
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
class ApprovalDecision(StrEnum):
|
|
261
|
+
APPROVED = "approved"
|
|
262
|
+
REJECTED = "rejected"
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
class StateTransitionError(ValueError):
|
|
266
|
+
def __init__(self, aggregate: str, current: Enum, target: Enum) -> None:
|
|
267
|
+
self.aggregate = aggregate
|
|
268
|
+
self.current = current
|
|
269
|
+
self.target = target
|
|
270
|
+
super().__init__(
|
|
271
|
+
f"Invalid {aggregate} state transition: {current.value} -> {target.value}"
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def ensure_transition[StateT: Enum](
|
|
276
|
+
aggregate: str,
|
|
277
|
+
current: StateT,
|
|
278
|
+
target: StateT,
|
|
279
|
+
transitions: Mapping[StateT, frozenset[StateT]],
|
|
280
|
+
) -> None:
|
|
281
|
+
if current is target:
|
|
282
|
+
return
|
|
283
|
+
if target not in transitions.get(current, frozenset()):
|
|
284
|
+
raise StateTransitionError(aggregate, current, target)
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
RUNTIME_TURN_TRANSITIONS: Mapping[RuntimeTurnState, frozenset[RuntimeTurnState]] = {
|
|
288
|
+
RuntimeTurnState.STARTING: frozenset(
|
|
289
|
+
{
|
|
290
|
+
RuntimeTurnState.RUNNING,
|
|
291
|
+
RuntimeTurnState.FAILED,
|
|
292
|
+
RuntimeTurnState.CANCELLED,
|
|
293
|
+
RuntimeTurnState.UNKNOWN,
|
|
294
|
+
}
|
|
295
|
+
),
|
|
296
|
+
RuntimeTurnState.RUNNING: frozenset(
|
|
297
|
+
{
|
|
298
|
+
RuntimeTurnState.COMPLETED,
|
|
299
|
+
RuntimeTurnState.FAILED,
|
|
300
|
+
RuntimeTurnState.CANCELLED,
|
|
301
|
+
RuntimeTurnState.UNKNOWN,
|
|
302
|
+
}
|
|
303
|
+
),
|
|
304
|
+
RuntimeTurnState.COMPLETED: frozenset(),
|
|
305
|
+
RuntimeTurnState.FAILED: frozenset(),
|
|
306
|
+
RuntimeTurnState.CANCELLED: frozenset(),
|
|
307
|
+
RuntimeTurnState.UNKNOWN: frozenset(),
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
OUTBOUND_DELIVERY_TRANSITIONS: Mapping[
|
|
311
|
+
OutboundDeliveryState, frozenset[OutboundDeliveryState]
|
|
312
|
+
] = {
|
|
313
|
+
OutboundDeliveryState.DRAFT: frozenset(
|
|
314
|
+
{OutboundDeliveryState.PENDING, OutboundDeliveryState.REJECTED}
|
|
315
|
+
),
|
|
316
|
+
OutboundDeliveryState.PENDING: frozenset(
|
|
317
|
+
{
|
|
318
|
+
OutboundDeliveryState.QUEUED,
|
|
319
|
+
OutboundDeliveryState.SENT,
|
|
320
|
+
OutboundDeliveryState.PARTIAL,
|
|
321
|
+
OutboundDeliveryState.FAILED,
|
|
322
|
+
OutboundDeliveryState.UNKNOWN,
|
|
323
|
+
}
|
|
324
|
+
),
|
|
325
|
+
OutboundDeliveryState.QUEUED: frozenset(
|
|
326
|
+
{
|
|
327
|
+
OutboundDeliveryState.SENT,
|
|
328
|
+
OutboundDeliveryState.PARTIAL,
|
|
329
|
+
OutboundDeliveryState.FAILED,
|
|
330
|
+
OutboundDeliveryState.UNKNOWN,
|
|
331
|
+
}
|
|
332
|
+
),
|
|
333
|
+
OutboundDeliveryState.SENT: frozenset(),
|
|
334
|
+
OutboundDeliveryState.PARTIAL: frozenset(),
|
|
335
|
+
OutboundDeliveryState.FAILED: frozenset(),
|
|
336
|
+
OutboundDeliveryState.UNKNOWN: frozenset(
|
|
337
|
+
{
|
|
338
|
+
OutboundDeliveryState.SENT,
|
|
339
|
+
OutboundDeliveryState.PARTIAL,
|
|
340
|
+
OutboundDeliveryState.FAILED,
|
|
341
|
+
}
|
|
342
|
+
),
|
|
343
|
+
OutboundDeliveryState.REJECTED: frozenset(),
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
FRESH_CHECK_TRANSITIONS: Mapping[FreshCheckState, frozenset[FreshCheckState]] = {
|
|
347
|
+
FreshCheckState.REQUIRED: frozenset(
|
|
348
|
+
{FreshCheckState.PASSED, FreshCheckState.FAILED}
|
|
349
|
+
),
|
|
350
|
+
FreshCheckState.PASSED: frozenset(),
|
|
351
|
+
FreshCheckState.FAILED: frozenset(),
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
RUNTIME_EVENT_TRANSITIONS: Mapping[RuntimeEventState, frozenset[RuntimeEventState]] = {
|
|
355
|
+
RuntimeEventState.STARTED: frozenset(
|
|
356
|
+
{
|
|
357
|
+
RuntimeEventState.COMPLETED,
|
|
358
|
+
RuntimeEventState.FAILED,
|
|
359
|
+
RuntimeEventState.CANCELLED,
|
|
360
|
+
RuntimeEventState.UNKNOWN,
|
|
361
|
+
}
|
|
362
|
+
),
|
|
363
|
+
RuntimeEventState.COMPLETED: frozenset(),
|
|
364
|
+
RuntimeEventState.FAILED: frozenset(),
|
|
365
|
+
RuntimeEventState.CANCELLED: frozenset(),
|
|
366
|
+
RuntimeEventState.UNKNOWN: frozenset(
|
|
367
|
+
{RuntimeEventState.COMPLETED, RuntimeEventState.FAILED}
|
|
368
|
+
),
|
|
369
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Mapping
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from enum import StrEnum
|
|
6
|
+
from typing import TYPE_CHECKING, Protocol
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from .audit import AuditEvent
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class LogLevel(StrEnum):
|
|
13
|
+
DEBUG = "debug"
|
|
14
|
+
INFO = "info"
|
|
15
|
+
WARNING = "warning"
|
|
16
|
+
ERROR = "error"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass(frozen=True, slots=True)
|
|
20
|
+
class LogRecord:
|
|
21
|
+
"""Structured runtime log record without raw provider payloads."""
|
|
22
|
+
|
|
23
|
+
level: LogLevel
|
|
24
|
+
event_name: str
|
|
25
|
+
message: str
|
|
26
|
+
fields: Mapping[str, object] = field(default_factory=dict)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class ILogger(Protocol):
|
|
30
|
+
"""Synchronous, non-blocking stderr logging boundary."""
|
|
31
|
+
|
|
32
|
+
def emit(self, record: LogRecord, *, error: BaseException | None = None) -> None:
|
|
33
|
+
"""Emit a redacted record without blocking the asyncio event loop."""
|
|
34
|
+
...
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class IAudit(Protocol):
|
|
38
|
+
"""Durable append-only operational event boundary."""
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def name(self) -> str:
|
|
42
|
+
"""Return the stable entry-point identity of this adapter."""
|
|
43
|
+
...
|
|
44
|
+
|
|
45
|
+
async def append(self, event: AuditEvent, *, timeout: float) -> None:
|
|
46
|
+
"""Persist one event; cancellation must propagate to the caller."""
|
|
47
|
+
...
|