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,646 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Callable
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from hashlib import sha256
|
|
6
|
+
from time import monotonic_ns, time_ns
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from .repository import SqliteTransaction
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _current_time_ms() -> int:
|
|
14
|
+
return time_ns() // 1_000_000
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass(frozen=True, slots=True)
|
|
18
|
+
class Migration:
|
|
19
|
+
version: int
|
|
20
|
+
name: str
|
|
21
|
+
statements: tuple[str, ...]
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def checksum(self) -> str:
|
|
25
|
+
content = "\n".join(self.statements).encode("utf-8")
|
|
26
|
+
return sha256(content).hexdigest()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class MigrationError(RuntimeError):
|
|
30
|
+
"""The database cannot be safely brought to the application schema."""
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class MigrationChecksumError(MigrationError):
|
|
34
|
+
"""A migration ledger entry no longer matches the application migration."""
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
SCHEMA_MIGRATION = Migration(
|
|
38
|
+
version=1,
|
|
39
|
+
name="initial_node_schema",
|
|
40
|
+
statements=(
|
|
41
|
+
"""
|
|
42
|
+
-- Immutable migration ledger and checksum verification record.
|
|
43
|
+
CREATE TABLE schema_migrations (
|
|
44
|
+
-- Monotonic migration version used for application-level ledger checks.
|
|
45
|
+
version INTEGER PRIMARY KEY,
|
|
46
|
+
-- Human-readable migration name.
|
|
47
|
+
migration_name TEXT,
|
|
48
|
+
-- Migration content checksum.
|
|
49
|
+
checksum TEXT,
|
|
50
|
+
-- Migration application time.
|
|
51
|
+
applied_at_ms INTEGER,
|
|
52
|
+
-- Migration execution duration.
|
|
53
|
+
duration_ms INTEGER
|
|
54
|
+
)
|
|
55
|
+
""",
|
|
56
|
+
"""
|
|
57
|
+
-- Singleton node identity, workspace binding, and cached schema version.
|
|
58
|
+
CREATE TABLE node_state (
|
|
59
|
+
-- Fixed application-managed row key for the singleton state record.
|
|
60
|
+
singleton_key INTEGER PRIMARY KEY,
|
|
61
|
+
-- Stable identifier of this node installation.
|
|
62
|
+
node_id TEXT,
|
|
63
|
+
-- Cached version of the migration ledger.
|
|
64
|
+
schema_version INTEGER,
|
|
65
|
+
-- UUIDv7-backed identifier of the shared workspace used by all runtime sessions.
|
|
66
|
+
workspace_id TEXT,
|
|
67
|
+
-- Creation time of the node state.
|
|
68
|
+
created_at_ms INTEGER,
|
|
69
|
+
-- Last update time of node metadata or schema cache.
|
|
70
|
+
updated_at_ms INTEGER,
|
|
71
|
+
-- Non-sensitive node metadata encoded as JSON.
|
|
72
|
+
metadata_json TEXT
|
|
73
|
+
)
|
|
74
|
+
""",
|
|
75
|
+
"""
|
|
76
|
+
-- Provider thread identity and channel-level following state.
|
|
77
|
+
CREATE TABLE channel_sessions (
|
|
78
|
+
-- Stable local identifier for the normalized channel session.
|
|
79
|
+
id TEXT PRIMARY KEY,
|
|
80
|
+
-- Selected channel adapter name.
|
|
81
|
+
channel TEXT,
|
|
82
|
+
-- Provider-native routable thread identity used for lookup.
|
|
83
|
+
provider_thread_id TEXT,
|
|
84
|
+
-- Normalized target category used by the command layer.
|
|
85
|
+
target_kind TEXT,
|
|
86
|
+
-- Application-managed following flag.
|
|
87
|
+
following INTEGER,
|
|
88
|
+
-- Non-sensitive provider identity references encoded as JSON.
|
|
89
|
+
provider_identity_ref_json TEXT,
|
|
90
|
+
-- Creation time of the channel session.
|
|
91
|
+
created_at_ms INTEGER,
|
|
92
|
+
-- Last update time of channel identity or lifecycle state.
|
|
93
|
+
updated_at_ms INTEGER,
|
|
94
|
+
-- Last normalized inbound time observed for this session.
|
|
95
|
+
last_inbound_at_ms INTEGER,
|
|
96
|
+
-- Last outbound attempt time observed for this session.
|
|
97
|
+
last_outbound_at_ms INTEGER
|
|
98
|
+
)
|
|
99
|
+
""",
|
|
100
|
+
"""
|
|
101
|
+
-- Stable bcn session bound to one channel session and the shared workspace.
|
|
102
|
+
CREATE TABLE bcn_sessions (
|
|
103
|
+
-- Stable local identifier exposed to the runtime command wrapper.
|
|
104
|
+
id TEXT PRIMARY KEY,
|
|
105
|
+
-- Application-managed association to a channel session.
|
|
106
|
+
channel_session_id TEXT,
|
|
107
|
+
-- UUIDv7-backed identifier of the shared workspace used by this session.
|
|
108
|
+
workspace_id TEXT,
|
|
109
|
+
-- Creation time of the bcn session.
|
|
110
|
+
created_at_ms INTEGER,
|
|
111
|
+
-- Last update time of durable session metadata.
|
|
112
|
+
updated_at_ms INTEGER,
|
|
113
|
+
-- Last message or runtime activity time.
|
|
114
|
+
last_activity_at_ms INTEGER,
|
|
115
|
+
-- Non-sensitive session metadata encoded as JSON.
|
|
116
|
+
metadata_json TEXT
|
|
117
|
+
)
|
|
118
|
+
""",
|
|
119
|
+
"""
|
|
120
|
+
-- One durable agent runtime/thread binding.
|
|
121
|
+
CREATE TABLE runtime_sessions (
|
|
122
|
+
-- Stable local identifier for one runtime binding.
|
|
123
|
+
id TEXT PRIMARY KEY,
|
|
124
|
+
-- Application-managed association to a bcn session.
|
|
125
|
+
bcn_session_id TEXT,
|
|
126
|
+
-- Application-managed channel session association for correlation.
|
|
127
|
+
channel_session_id TEXT,
|
|
128
|
+
-- Selected agent runtime adapter name.
|
|
129
|
+
runtime TEXT,
|
|
130
|
+
-- Runtime adapter or protocol version used for this process.
|
|
131
|
+
runtime_version TEXT,
|
|
132
|
+
-- Provider-native runtime thread identifier when available.
|
|
133
|
+
provider_thread_id TEXT,
|
|
134
|
+
-- Creation time of the runtime session record.
|
|
135
|
+
created_at_ms INTEGER,
|
|
136
|
+
-- Last update time of durable runtime metadata.
|
|
137
|
+
updated_at_ms INTEGER,
|
|
138
|
+
-- Non-sensitive runtime metadata encoded as JSON.
|
|
139
|
+
metadata_json TEXT
|
|
140
|
+
)
|
|
141
|
+
""",
|
|
142
|
+
"""
|
|
143
|
+
-- Durable runtime turn state used for completion, interruption, and reconciliation.
|
|
144
|
+
CREATE TABLE runtime_turns (
|
|
145
|
+
-- Stable local identifier for one runtime turn.
|
|
146
|
+
turn_id TEXT PRIMARY KEY,
|
|
147
|
+
-- Application-managed association to the runtime session.
|
|
148
|
+
session_id TEXT,
|
|
149
|
+
-- Provider-native turn identifier when available.
|
|
150
|
+
provider_turn_id TEXT,
|
|
151
|
+
-- Client message identifier that caused this turn.
|
|
152
|
+
client_user_message_id TEXT,
|
|
153
|
+
-- Application-managed turn lifecycle state.
|
|
154
|
+
state TEXT,
|
|
155
|
+
-- Turn start time.
|
|
156
|
+
started_at_ms INTEGER,
|
|
157
|
+
-- Turn completion time when a terminal result is known.
|
|
158
|
+
completed_at_ms INTEGER,
|
|
159
|
+
-- Latest normalized runtime event name.
|
|
160
|
+
last_event_name TEXT,
|
|
161
|
+
-- Stable application error category for the turn.
|
|
162
|
+
error_kind TEXT,
|
|
163
|
+
-- Redacted summary of the turn failure.
|
|
164
|
+
error_message TEXT,
|
|
165
|
+
-- Non-sensitive turn metadata encoded as JSON.
|
|
166
|
+
metadata_json TEXT
|
|
167
|
+
)
|
|
168
|
+
""",
|
|
169
|
+
"""
|
|
170
|
+
-- Append-only normalized inbound message log with the node-local delivery sequence.
|
|
171
|
+
CREATE TABLE inbound_messages (
|
|
172
|
+
-- Stable local UUIDv7 message identifier used as the physical row identity.
|
|
173
|
+
message_id TEXT PRIMARY KEY,
|
|
174
|
+
-- Node-local monotonic sequence used for cursor and snapshot boundaries.
|
|
175
|
+
seq INTEGER,
|
|
176
|
+
-- Application-managed association to a bcn session.
|
|
177
|
+
session_id TEXT,
|
|
178
|
+
-- Application-managed association to a channel session.
|
|
179
|
+
channel_session_id TEXT,
|
|
180
|
+
-- Channel adapter name that normalized the message.
|
|
181
|
+
channel TEXT,
|
|
182
|
+
-- Provider-native routable thread identity mapped to the channel session.
|
|
183
|
+
provider_thread_id TEXT,
|
|
184
|
+
-- Provider-native message identifier used for application-level deduplication.
|
|
185
|
+
provider_message_id TEXT,
|
|
186
|
+
-- Provider timestamp, if supplied.
|
|
187
|
+
provider_time_ms INTEGER,
|
|
188
|
+
-- Local receipt time.
|
|
189
|
+
received_at_ms INTEGER,
|
|
190
|
+
-- Provider-neutral sender identity shown to the runtime.
|
|
191
|
+
sender TEXT,
|
|
192
|
+
-- Normalized sender or event type.
|
|
193
|
+
message_type TEXT,
|
|
194
|
+
-- Canonical target used by reply commands.
|
|
195
|
+
canonical_target TEXT,
|
|
196
|
+
-- Provider-neutral direct-message or group classification.
|
|
197
|
+
target_kind TEXT,
|
|
198
|
+
-- Provider-native identifier of the message being replied to.
|
|
199
|
+
reply_to_provider_message_id TEXT,
|
|
200
|
+
-- Normalized message body.
|
|
201
|
+
body TEXT,
|
|
202
|
+
-- Whether the provider reports an explicit mention of the agent.
|
|
203
|
+
mentions_agent INTEGER,
|
|
204
|
+
-- Persisted application decision to expose this message as unread.
|
|
205
|
+
notifies_runtime INTEGER,
|
|
206
|
+
-- Controlled reference to retained provider payload data.
|
|
207
|
+
provider_payload_ref TEXT,
|
|
208
|
+
-- Non-sensitive normalized metadata encoded as JSON.
|
|
209
|
+
metadata_json TEXT
|
|
210
|
+
)
|
|
211
|
+
""",
|
|
212
|
+
"""
|
|
213
|
+
-- Terminal local descriptors for provider-neutral inbound attachments.
|
|
214
|
+
CREATE TABLE inbound_attachments (
|
|
215
|
+
attachment_id TEXT PRIMARY KEY,
|
|
216
|
+
message_id TEXT,
|
|
217
|
+
ordinal INTEGER,
|
|
218
|
+
name TEXT,
|
|
219
|
+
kind TEXT,
|
|
220
|
+
state TEXT,
|
|
221
|
+
media_type TEXT,
|
|
222
|
+
relative_path TEXT,
|
|
223
|
+
size_bytes INTEGER,
|
|
224
|
+
error TEXT
|
|
225
|
+
)
|
|
226
|
+
""",
|
|
227
|
+
"""
|
|
228
|
+
-- Outbound command attempts, fresh-check evidence, provider receipt, and delivery state.
|
|
229
|
+
CREATE TABLE outbound_messages (
|
|
230
|
+
-- Stable local UUIDv7 identifier for one outbound command attempt.
|
|
231
|
+
outbound_message_id TEXT PRIMARY KEY,
|
|
232
|
+
-- Stable identifier of the originating command invocation.
|
|
233
|
+
command_id TEXT,
|
|
234
|
+
-- Application-managed association to a bcn session.
|
|
235
|
+
session_id TEXT,
|
|
236
|
+
-- Application-managed association to a channel session.
|
|
237
|
+
channel_session_id TEXT,
|
|
238
|
+
-- Canonical target supplied to the send command.
|
|
239
|
+
target TEXT,
|
|
240
|
+
-- Local inbound message identity for an optional reply intent.
|
|
241
|
+
reply_to_message_id TEXT,
|
|
242
|
+
-- Outbound message body captured for retry and audit.
|
|
243
|
+
body TEXT,
|
|
244
|
+
-- Application-managed delivery lifecycle state.
|
|
245
|
+
state TEXT,
|
|
246
|
+
-- Application-managed fresh-check result.
|
|
247
|
+
fresh_check_state TEXT,
|
|
248
|
+
-- Inbound snapshot boundary used by the command.
|
|
249
|
+
snapshot_seq INTEGER,
|
|
250
|
+
-- Current inbound boundary observed during fresh-check.
|
|
251
|
+
current_inbound_seq INTEGER,
|
|
252
|
+
-- Provider-native message identifier after provider acceptance.
|
|
253
|
+
provider_message_id TEXT,
|
|
254
|
+
-- Controlled reference to the provider delivery receipt.
|
|
255
|
+
provider_receipt_ref TEXT,
|
|
256
|
+
-- Creation time of the outbound attempt.
|
|
257
|
+
created_at_ms INTEGER,
|
|
258
|
+
-- Time at which the provider call was attempted.
|
|
259
|
+
provider_attempted_at_ms INTEGER,
|
|
260
|
+
-- Completion time of the provider call.
|
|
261
|
+
completed_at_ms INTEGER,
|
|
262
|
+
-- Time at which a refused draft was persisted.
|
|
263
|
+
draft_saved_at_ms INTEGER,
|
|
264
|
+
-- Stable application error category for the attempt.
|
|
265
|
+
error_kind TEXT,
|
|
266
|
+
-- Redacted summary of the outbound failure.
|
|
267
|
+
error_message TEXT,
|
|
268
|
+
-- Human- and machine-actionable next step.
|
|
269
|
+
next_action TEXT,
|
|
270
|
+
-- Non-sensitive outbound metadata encoded as JSON.
|
|
271
|
+
metadata_json TEXT
|
|
272
|
+
)
|
|
273
|
+
""",
|
|
274
|
+
"""
|
|
275
|
+
-- Per-session delivery cursor and the latest inbox snapshot used by fresh-check.
|
|
276
|
+
CREATE TABLE consumer_cursors (
|
|
277
|
+
-- Stable bcn session identifier used as the cursor record identity.
|
|
278
|
+
session_id TEXT PRIMARY KEY,
|
|
279
|
+
-- Highest inbound sequence already delivered by check.
|
|
280
|
+
delivered_through_seq INTEGER,
|
|
281
|
+
-- Latest inbound sequence observed by check or read.
|
|
282
|
+
inbox_snapshot_seq INTEGER,
|
|
283
|
+
-- Operation that produced the latest snapshot.
|
|
284
|
+
inbox_snapshot_source TEXT,
|
|
285
|
+
-- Time at which the latest snapshot was recorded.
|
|
286
|
+
inbox_snapshot_at_ms INTEGER,
|
|
287
|
+
-- Last check operation time.
|
|
288
|
+
last_check_at_ms INTEGER,
|
|
289
|
+
-- Last read operation time.
|
|
290
|
+
last_read_at_ms INTEGER,
|
|
291
|
+
-- Last cursor or snapshot update time.
|
|
292
|
+
updated_at_ms INTEGER
|
|
293
|
+
)
|
|
294
|
+
""",
|
|
295
|
+
"""
|
|
296
|
+
-- Append-only operational and audit events with cross-component correlation fields.
|
|
297
|
+
CREATE TABLE runtime_events (
|
|
298
|
+
-- Node-local monotonic sequence for the event log.
|
|
299
|
+
event_seq INTEGER PRIMARY KEY,
|
|
300
|
+
-- Stable event identifier for external correlation.
|
|
301
|
+
event_id TEXT,
|
|
302
|
+
-- Event creation time.
|
|
303
|
+
created_at_ms INTEGER,
|
|
304
|
+
-- Normalized log severity.
|
|
305
|
+
level TEXT,
|
|
306
|
+
-- Stable event name.
|
|
307
|
+
event_name TEXT,
|
|
308
|
+
-- Application-managed event state.
|
|
309
|
+
state TEXT,
|
|
310
|
+
-- Event duration when the operation has completed.
|
|
311
|
+
duration_ms INTEGER,
|
|
312
|
+
-- Node identifier that emitted the event.
|
|
313
|
+
node_id TEXT,
|
|
314
|
+
-- Channel adapter name associated with the event.
|
|
315
|
+
channel TEXT,
|
|
316
|
+
-- Runtime adapter name associated with the event.
|
|
317
|
+
runtime TEXT,
|
|
318
|
+
-- Channel session correlation identifier.
|
|
319
|
+
channel_session_id TEXT,
|
|
320
|
+
-- Bcn session correlation identifier.
|
|
321
|
+
bcn_session_id TEXT,
|
|
322
|
+
-- Agent runtime session correlation identifier.
|
|
323
|
+
runtime_session_id TEXT,
|
|
324
|
+
-- Runtime turn correlation identifier.
|
|
325
|
+
turn_id TEXT,
|
|
326
|
+
-- Provider or protocol request correlation identifier.
|
|
327
|
+
request_id TEXT,
|
|
328
|
+
-- Local command correlation identifier.
|
|
329
|
+
command_id TEXT,
|
|
330
|
+
-- Related inbound message sequence when available.
|
|
331
|
+
inbound_seq INTEGER,
|
|
332
|
+
-- Related outbound message identifier when available.
|
|
333
|
+
outbound_message_id TEXT,
|
|
334
|
+
-- Stable application error category.
|
|
335
|
+
error_kind TEXT,
|
|
336
|
+
-- Runtime error type after redaction.
|
|
337
|
+
error_type TEXT,
|
|
338
|
+
-- Redacted error summary.
|
|
339
|
+
error_message TEXT,
|
|
340
|
+
-- Controlled reference to a retained traceback.
|
|
341
|
+
traceback_ref TEXT,
|
|
342
|
+
-- Non-sensitive event metadata encoded as JSON.
|
|
343
|
+
metadata_json TEXT
|
|
344
|
+
)
|
|
345
|
+
""",
|
|
346
|
+
"""
|
|
347
|
+
CREATE INDEX idx_inbound_session_seq
|
|
348
|
+
ON inbound_messages (session_id, seq)
|
|
349
|
+
""",
|
|
350
|
+
"""
|
|
351
|
+
CREATE INDEX idx_inbound_seq
|
|
352
|
+
ON inbound_messages (seq)
|
|
353
|
+
""",
|
|
354
|
+
"""
|
|
355
|
+
CREATE INDEX idx_inbound_channel_received
|
|
356
|
+
ON inbound_messages (channel_session_id, received_at_ms)
|
|
357
|
+
""",
|
|
358
|
+
"""
|
|
359
|
+
CREATE INDEX idx_outbound_session_created
|
|
360
|
+
ON outbound_messages (session_id, created_at_ms)
|
|
361
|
+
""",
|
|
362
|
+
"""
|
|
363
|
+
CREATE INDEX idx_outbound_state_created
|
|
364
|
+
ON outbound_messages (state, created_at_ms)
|
|
365
|
+
""",
|
|
366
|
+
"""
|
|
367
|
+
CREATE INDEX idx_runtime_turns_session_state
|
|
368
|
+
ON runtime_turns (session_id, state, started_at_ms)
|
|
369
|
+
""",
|
|
370
|
+
"""
|
|
371
|
+
CREATE INDEX idx_runtime_events_session_seq
|
|
372
|
+
ON runtime_events (bcn_session_id, event_seq)
|
|
373
|
+
""",
|
|
374
|
+
"""
|
|
375
|
+
CREATE INDEX idx_runtime_events_name_seq
|
|
376
|
+
ON runtime_events (event_name, event_seq)
|
|
377
|
+
""",
|
|
378
|
+
"""
|
|
379
|
+
CREATE INDEX idx_runtime_events_created
|
|
380
|
+
ON runtime_events (created_at_ms)
|
|
381
|
+
""",
|
|
382
|
+
),
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
SESSION_MAPPING_INDEX_MIGRATION = Migration(
|
|
386
|
+
version=2,
|
|
387
|
+
name="session_mapping_indexes",
|
|
388
|
+
statements=(
|
|
389
|
+
"""
|
|
390
|
+
-- Provider identity lookup used by channel session get-or-create.
|
|
391
|
+
CREATE INDEX idx_channel_sessions_provider_identity
|
|
392
|
+
ON channel_sessions (
|
|
393
|
+
channel,
|
|
394
|
+
provider_thread_id
|
|
395
|
+
)
|
|
396
|
+
""",
|
|
397
|
+
"""
|
|
398
|
+
-- Channel-to-bcn session lookup used during recovery reconciliation.
|
|
399
|
+
CREATE INDEX idx_bcn_sessions_channel
|
|
400
|
+
ON bcn_sessions (channel_session_id)
|
|
401
|
+
""",
|
|
402
|
+
"""
|
|
403
|
+
-- Bcn-to-runtime session lookup used during process reconciliation.
|
|
404
|
+
CREATE INDEX idx_runtime_sessions_bcn
|
|
405
|
+
ON runtime_sessions (bcn_session_id)
|
|
406
|
+
""",
|
|
407
|
+
),
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
MESSAGE_LOG_INDEX_MIGRATION = Migration(
|
|
411
|
+
version=3,
|
|
412
|
+
name="message_log_indexes",
|
|
413
|
+
statements=(
|
|
414
|
+
"""
|
|
415
|
+
-- Provider-scoped inbound deduplication lookup.
|
|
416
|
+
CREATE INDEX idx_inbound_provider_identity
|
|
417
|
+
ON inbound_messages (channel, provider_message_id)
|
|
418
|
+
""",
|
|
419
|
+
"""
|
|
420
|
+
-- Target-filtered history lookup for one bcn session.
|
|
421
|
+
CREATE INDEX idx_inbound_session_target_seq
|
|
422
|
+
ON inbound_messages (session_id, canonical_target, seq)
|
|
423
|
+
""",
|
|
424
|
+
),
|
|
425
|
+
)
|
|
426
|
+
|
|
427
|
+
RUNTIME_ATTEMPT_FACT_MIGRATION = Migration(
|
|
428
|
+
version=4,
|
|
429
|
+
name="runtime_attempt_facts",
|
|
430
|
+
statements=(
|
|
431
|
+
"""
|
|
432
|
+
CREATE TABLE runtime_attempts (
|
|
433
|
+
turn_id TEXT PRIMARY KEY,
|
|
434
|
+
session_id TEXT,
|
|
435
|
+
client_user_message_id TEXT,
|
|
436
|
+
started_at_ms INTEGER
|
|
437
|
+
)
|
|
438
|
+
""",
|
|
439
|
+
"""
|
|
440
|
+
INSERT INTO runtime_attempts (
|
|
441
|
+
turn_id,
|
|
442
|
+
session_id,
|
|
443
|
+
client_user_message_id,
|
|
444
|
+
started_at_ms
|
|
445
|
+
)
|
|
446
|
+
SELECT
|
|
447
|
+
turn_id,
|
|
448
|
+
session_id,
|
|
449
|
+
client_user_message_id,
|
|
450
|
+
started_at_ms
|
|
451
|
+
FROM runtime_turns
|
|
452
|
+
WHERE client_user_message_id IS NOT NULL
|
|
453
|
+
""",
|
|
454
|
+
"""
|
|
455
|
+
DROP INDEX idx_runtime_turns_session_state
|
|
456
|
+
""",
|
|
457
|
+
"""
|
|
458
|
+
DROP TABLE runtime_turns
|
|
459
|
+
""",
|
|
460
|
+
"""
|
|
461
|
+
CREATE INDEX idx_runtime_attempts_session_started
|
|
462
|
+
ON runtime_attempts (session_id, started_at_ms)
|
|
463
|
+
""",
|
|
464
|
+
),
|
|
465
|
+
)
|
|
466
|
+
|
|
467
|
+
INBOUND_MESSAGE_REFERENCE_MIGRATION = Migration(
|
|
468
|
+
version=5,
|
|
469
|
+
name="inbound_message_references",
|
|
470
|
+
statements=(
|
|
471
|
+
"""
|
|
472
|
+
ALTER TABLE inbound_messages
|
|
473
|
+
RENAME COLUMN reply_to_provider_message_id TO reply_to_message_id
|
|
474
|
+
""",
|
|
475
|
+
"""
|
|
476
|
+
UPDATE inbound_messages AS current
|
|
477
|
+
SET reply_to_message_id = (
|
|
478
|
+
SELECT referenced.message_id
|
|
479
|
+
FROM inbound_messages AS referenced
|
|
480
|
+
WHERE referenced.channel = current.channel
|
|
481
|
+
AND referenced.provider_message_id = current.reply_to_message_id
|
|
482
|
+
ORDER BY referenced.seq
|
|
483
|
+
LIMIT 1
|
|
484
|
+
)
|
|
485
|
+
WHERE current.reply_to_message_id IS NOT NULL
|
|
486
|
+
""",
|
|
487
|
+
"""
|
|
488
|
+
CREATE INDEX idx_inbound_reply_to_message
|
|
489
|
+
ON inbound_messages (reply_to_message_id)
|
|
490
|
+
""",
|
|
491
|
+
),
|
|
492
|
+
)
|
|
493
|
+
|
|
494
|
+
INBOUND_MESSAGE_REFERENCE_INTEGRITY_MIGRATION = Migration(
|
|
495
|
+
version=6,
|
|
496
|
+
name="inbound_message_reference_integrity",
|
|
497
|
+
statements=(
|
|
498
|
+
"""
|
|
499
|
+
UPDATE inbound_messages AS current
|
|
500
|
+
SET reply_to_message_id = NULL
|
|
501
|
+
WHERE current.reply_to_message_id IS NOT NULL
|
|
502
|
+
AND NOT EXISTS (
|
|
503
|
+
SELECT 1
|
|
504
|
+
FROM inbound_messages AS referenced
|
|
505
|
+
WHERE referenced.message_id = current.reply_to_message_id
|
|
506
|
+
AND referenced.session_id = current.session_id
|
|
507
|
+
AND referenced.seq < current.seq
|
|
508
|
+
)
|
|
509
|
+
""",
|
|
510
|
+
),
|
|
511
|
+
)
|
|
512
|
+
|
|
513
|
+
INBOUND_PROVIDER_IDENTITY_MIGRATION = Migration(
|
|
514
|
+
version=7,
|
|
515
|
+
name="inbound_provider_identity",
|
|
516
|
+
statements=(
|
|
517
|
+
"""
|
|
518
|
+
DROP INDEX idx_inbound_provider_identity
|
|
519
|
+
""",
|
|
520
|
+
"""
|
|
521
|
+
CREATE UNIQUE INDEX idx_inbound_provider_identity
|
|
522
|
+
ON inbound_messages (
|
|
523
|
+
channel,
|
|
524
|
+
provider_thread_id,
|
|
525
|
+
provider_message_id
|
|
526
|
+
)
|
|
527
|
+
""",
|
|
528
|
+
),
|
|
529
|
+
)
|
|
530
|
+
|
|
531
|
+
TRANSIENT_STREAM_EVENT_MIGRATION = Migration(
|
|
532
|
+
version=8,
|
|
533
|
+
name="transient_stream_events",
|
|
534
|
+
statements=(
|
|
535
|
+
"""
|
|
536
|
+
DELETE FROM runtime_events
|
|
537
|
+
WHERE event_name = 'codex.turn.progress'
|
|
538
|
+
AND (
|
|
539
|
+
json_extract(metadata_json, '$.provider_method') = 'turn/progress'
|
|
540
|
+
OR (
|
|
541
|
+
json_extract(metadata_json, '$.provider_method') LIKE 'item/%'
|
|
542
|
+
AND json_extract(metadata_json, '$.provider_method') NOT IN (
|
|
543
|
+
'item/started',
|
|
544
|
+
'item/completed',
|
|
545
|
+
'item/autoApprovalReview/started',
|
|
546
|
+
'item/autoApprovalReview/completed'
|
|
547
|
+
)
|
|
548
|
+
)
|
|
549
|
+
)
|
|
550
|
+
""",
|
|
551
|
+
),
|
|
552
|
+
)
|
|
553
|
+
|
|
554
|
+
MIGRATIONS: tuple[Migration, ...] = (
|
|
555
|
+
SCHEMA_MIGRATION,
|
|
556
|
+
SESSION_MAPPING_INDEX_MIGRATION,
|
|
557
|
+
MESSAGE_LOG_INDEX_MIGRATION,
|
|
558
|
+
RUNTIME_ATTEMPT_FACT_MIGRATION,
|
|
559
|
+
INBOUND_MESSAGE_REFERENCE_MIGRATION,
|
|
560
|
+
INBOUND_MESSAGE_REFERENCE_INTEGRITY_MIGRATION,
|
|
561
|
+
INBOUND_PROVIDER_IDENTITY_MIGRATION,
|
|
562
|
+
TRANSIENT_STREAM_EVENT_MIGRATION,
|
|
563
|
+
)
|
|
564
|
+
|
|
565
|
+
|
|
566
|
+
async def apply_migrations(
|
|
567
|
+
transaction: SqliteTransaction,
|
|
568
|
+
*,
|
|
569
|
+
clock: Callable[[], int] = _current_time_ms,
|
|
570
|
+
) -> int:
|
|
571
|
+
"""Apply the ordered migration ledger inside the caller's transaction."""
|
|
572
|
+
|
|
573
|
+
ledger_exists = (
|
|
574
|
+
await transaction.fetchone(
|
|
575
|
+
"SELECT 1 FROM sqlite_master "
|
|
576
|
+
"WHERE type = 'table' AND name = 'schema_migrations'"
|
|
577
|
+
)
|
|
578
|
+
is not None
|
|
579
|
+
)
|
|
580
|
+
applied_rows = []
|
|
581
|
+
if ledger_exists:
|
|
582
|
+
applied_rows = await transaction.fetchall(
|
|
583
|
+
"SELECT version, migration_name, checksum "
|
|
584
|
+
"FROM schema_migrations ORDER BY version"
|
|
585
|
+
)
|
|
586
|
+
known_versions = {migration.version for migration in MIGRATIONS}
|
|
587
|
+
unknown_versions = {
|
|
588
|
+
int(row["version"])
|
|
589
|
+
for row in applied_rows
|
|
590
|
+
if int(row["version"]) not in known_versions
|
|
591
|
+
}
|
|
592
|
+
if unknown_versions:
|
|
593
|
+
raise MigrationError(
|
|
594
|
+
"database contains unknown migration versions: "
|
|
595
|
+
+ ", ".join(str(version) for version in sorted(unknown_versions))
|
|
596
|
+
)
|
|
597
|
+
|
|
598
|
+
applied_by_version = {int(row["version"]): row for row in applied_rows}
|
|
599
|
+
preexisting_ledger = ledger_exists
|
|
600
|
+
latest_version = 0
|
|
601
|
+
missing_version = False
|
|
602
|
+
for migration in MIGRATIONS:
|
|
603
|
+
row = applied_by_version.get(migration.version)
|
|
604
|
+
if row is None:
|
|
605
|
+
missing_version = True
|
|
606
|
+
continue
|
|
607
|
+
if missing_version:
|
|
608
|
+
raise MigrationError(
|
|
609
|
+
"migration ledger contains a later version after a missing "
|
|
610
|
+
f"version before {migration.version}"
|
|
611
|
+
)
|
|
612
|
+
if (
|
|
613
|
+
row["migration_name"] != migration.name
|
|
614
|
+
or row["checksum"] != migration.checksum
|
|
615
|
+
):
|
|
616
|
+
raise MigrationChecksumError(
|
|
617
|
+
f"migration {migration.version} does not match its ledger entry"
|
|
618
|
+
)
|
|
619
|
+
latest_version = migration.version
|
|
620
|
+
|
|
621
|
+
if preexisting_ledger and latest_version == 0:
|
|
622
|
+
raise MigrationError(
|
|
623
|
+
f"migration ledger is missing version {MIGRATIONS[0].version}"
|
|
624
|
+
)
|
|
625
|
+
|
|
626
|
+
for migration in MIGRATIONS:
|
|
627
|
+
if migration.version <= latest_version:
|
|
628
|
+
continue
|
|
629
|
+
started_at_ns = monotonic_ns()
|
|
630
|
+
for statement in migration.statements:
|
|
631
|
+
await transaction.execute(statement)
|
|
632
|
+
await transaction.execute(
|
|
633
|
+
"INSERT INTO schema_migrations "
|
|
634
|
+
"(version, migration_name, checksum, applied_at_ms, duration_ms) "
|
|
635
|
+
"VALUES (?, ?, ?, ?, ?)",
|
|
636
|
+
(
|
|
637
|
+
migration.version,
|
|
638
|
+
migration.name,
|
|
639
|
+
migration.checksum,
|
|
640
|
+
clock(),
|
|
641
|
+
(monotonic_ns() - started_at_ns) // 1_000_000,
|
|
642
|
+
),
|
|
643
|
+
)
|
|
644
|
+
latest_version = migration.version
|
|
645
|
+
|
|
646
|
+
return latest_version
|