@opengeni/db 0.36.0 → 0.36.1
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.
- package/dist/canonical-human-identities.js +2 -2
- package/dist/{chunk-F32YT7MP.js → chunk-FPVAD4CO.js} +2 -2
- package/dist/{chunk-TAUTWOS5.js → chunk-GYO7ED2Q.js} +2 -2
- package/dist/{chunk-P3RE4D2B.js → chunk-HSOWSYOX.js} +2 -2
- package/dist/{chunk-CQZ4QSP5.js → chunk-VTPRIXKG.js} +2 -2
- package/dist/{chunk-JC5QPLUM.js → chunk-Z7VYMNPZ.js} +47 -2
- package/dist/chunk-Z7VYMNPZ.js.map +1 -0
- package/dist/editable-artifact-durable-export.js +1 -1
- package/dist/editable-artifacts.js +2 -2
- package/dist/index.d.ts +29 -0
- package/dist/index.js +365 -21
- package/dist/index.js.map +1 -1
- package/dist/persistence-errors.d.ts +8 -0
- package/dist/session-tenancy.js +2 -2
- package/dist/video-generation.js +2 -2
- package/drizzle/0238_recover_unclaimed_session_turns.sql +307 -0
- package/package.json +4 -4
- package/src/index.ts +468 -17
- package/src/persistence-errors.ts +60 -1
- package/dist/chunk-JC5QPLUM.js.map +0 -1
- /package/dist/{chunk-F32YT7MP.js.map → chunk-FPVAD4CO.js.map} +0 -0
- /package/dist/{chunk-TAUTWOS5.js.map → chunk-GYO7ED2Q.js.map} +0 -0
- /package/dist/{chunk-P3RE4D2B.js.map → chunk-HSOWSYOX.js.map} +0 -0
- /package/dist/{chunk-CQZ4QSP5.js.map → chunk-VTPRIXKG.js.map} +0 -0
|
@@ -23,6 +23,14 @@ export type PersistenceFailureDetails = {
|
|
|
23
23
|
export declare function nestedPostgresSqlState(error: unknown): string | null;
|
|
24
24
|
export declare function databaseFailureCode(sqlState: string | null): DatabaseFailureCode;
|
|
25
25
|
export declare function isRetryablePersistenceSqlState(sqlState: string | null): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Recognize only explicit postgres.js/Node transport codes, including nested
|
|
28
|
+
* driver causes. These failures can arrive as plain Errors with no SQLSTATE or
|
|
29
|
+
* database diagnostic fields when the connection dies before PostgreSQL can
|
|
30
|
+
* answer. Messages are intentionally ignored: they are unstable and may
|
|
31
|
+
* contain connection detail.
|
|
32
|
+
*/
|
|
33
|
+
export declare function isRetryableDatabaseTransportFailure(error: unknown): boolean;
|
|
26
34
|
/**
|
|
27
35
|
* Distinguish database/ORM failures from expected domain exceptions when a
|
|
28
36
|
* driver omitted SQLSTATE. This checks shape only; callers retain the original
|
package/dist/session-tenancy.js
CHANGED
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
canonicalSessionVisibilityTransitionHash,
|
|
4
4
|
forkSessionContent,
|
|
5
5
|
transitionSessionVisibility
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-FPVAD4CO.js";
|
|
7
|
+
import "./chunk-Z7VYMNPZ.js";
|
|
8
8
|
import "./chunk-5KTIEDX7.js";
|
|
9
9
|
import "./chunk-PZ5AY32C.js";
|
|
10
10
|
export {
|
package/dist/video-generation.js
CHANGED
|
@@ -29,8 +29,8 @@ import {
|
|
|
29
29
|
settleVideoGenerationFailure,
|
|
30
30
|
settleVideoGenerationReady,
|
|
31
31
|
updateWorkspaceVideoGenerationPolicy
|
|
32
|
-
} from "./chunk-
|
|
33
|
-
import "./chunk-
|
|
32
|
+
} from "./chunk-VTPRIXKG.js";
|
|
33
|
+
import "./chunk-Z7VYMNPZ.js";
|
|
34
34
|
import "./chunk-5KTIEDX7.js";
|
|
35
35
|
import "./chunk-PZ5AY32C.js";
|
|
36
36
|
export {
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
-- deployment-mode: rolling
|
|
2
|
+
-- A turn activity could previously exhaust a transient attempt-claim failure,
|
|
3
|
+
-- leave durable work with no active attempt, and then let its Temporal workflow
|
|
4
|
+
-- complete. This includes queued/recovering turns, a resumed approval, a
|
|
5
|
+
-- released capacity wait, manual compaction, and pending internal updates. Seed
|
|
6
|
+
-- one delayed durable wake for those exact admitted rows; current workflows may
|
|
7
|
+
-- consume it as an idempotent hint, while closed workflows are restarted by the
|
|
8
|
+
-- ordinary outbox dispatcher. A normal queued turn with an undelivered wake is
|
|
9
|
+
-- healthy and must remain untouched.
|
|
10
|
+
|
|
11
|
+
SET LOCAL lock_timeout = '5s';
|
|
12
|
+
SET LOCAL statement_timeout = '10min';
|
|
13
|
+
|
|
14
|
+
WITH RECURSIVE candidates AS MATERIALIZED (
|
|
15
|
+
SELECT
|
|
16
|
+
session_row.id AS session_id,
|
|
17
|
+
session_row.account_id,
|
|
18
|
+
session_row.workspace_id,
|
|
19
|
+
coalesce(
|
|
20
|
+
session_row.temporal_workflow_id,
|
|
21
|
+
'session-' || session_row.id::text
|
|
22
|
+
) AS temporal_workflow_id
|
|
23
|
+
FROM sessions session_row
|
|
24
|
+
WHERE session_row.status NOT IN ('failed', 'cancelled')
|
|
25
|
+
AND NOT EXISTS (
|
|
26
|
+
SELECT 1
|
|
27
|
+
FROM session_turn_attempts live_attempt
|
|
28
|
+
WHERE live_attempt.workspace_id = session_row.workspace_id
|
|
29
|
+
AND live_attempt.session_id = session_row.id
|
|
30
|
+
AND live_attempt.state IN ('claimed', 'running')
|
|
31
|
+
)
|
|
32
|
+
AND (
|
|
33
|
+
(
|
|
34
|
+
session_row.status = 'recovering'
|
|
35
|
+
AND EXISTS (
|
|
36
|
+
SELECT 1
|
|
37
|
+
FROM session_turns turn_row
|
|
38
|
+
WHERE turn_row.workspace_id = session_row.workspace_id
|
|
39
|
+
AND turn_row.session_id = session_row.id
|
|
40
|
+
AND turn_row.id = session_row.active_turn_id
|
|
41
|
+
AND turn_row.status = 'recovering'
|
|
42
|
+
AND turn_row.active_attempt_id IS NULL
|
|
43
|
+
)
|
|
44
|
+
)
|
|
45
|
+
OR (
|
|
46
|
+
EXISTS (
|
|
47
|
+
SELECT 1
|
|
48
|
+
FROM session_workflow_wake_outbox wake_row
|
|
49
|
+
WHERE wake_row.session_id = session_row.id
|
|
50
|
+
AND wake_row.wake_revision > 0
|
|
51
|
+
AND wake_row.wake_revision = wake_row.delivered_revision
|
|
52
|
+
)
|
|
53
|
+
AND (
|
|
54
|
+
(
|
|
55
|
+
session_row.status = 'queued'
|
|
56
|
+
AND session_row.active_turn_id IS NULL
|
|
57
|
+
AND EXISTS (
|
|
58
|
+
SELECT 1
|
|
59
|
+
FROM session_turns turn_row
|
|
60
|
+
WHERE turn_row.workspace_id = session_row.workspace_id
|
|
61
|
+
AND turn_row.session_id = session_row.id
|
|
62
|
+
AND turn_row.status = 'queued'
|
|
63
|
+
AND turn_row.source IN ('user', 'api')
|
|
64
|
+
AND turn_row.active_attempt_id IS NULL
|
|
65
|
+
)
|
|
66
|
+
)
|
|
67
|
+
OR (
|
|
68
|
+
session_row.status = 'waiting_capacity'
|
|
69
|
+
AND EXISTS (
|
|
70
|
+
SELECT 1
|
|
71
|
+
FROM session_turns turn_row
|
|
72
|
+
WHERE turn_row.workspace_id = session_row.workspace_id
|
|
73
|
+
AND turn_row.session_id = session_row.id
|
|
74
|
+
AND turn_row.id = session_row.active_turn_id
|
|
75
|
+
AND turn_row.status = 'waiting_capacity'
|
|
76
|
+
AND turn_row.active_attempt_id IS NULL
|
|
77
|
+
)
|
|
78
|
+
AND NOT EXISTS (
|
|
79
|
+
SELECT 1
|
|
80
|
+
FROM codex_capacity_waiters waiter
|
|
81
|
+
WHERE waiter.workspace_id = session_row.workspace_id
|
|
82
|
+
AND waiter.session_id = session_row.id
|
|
83
|
+
AND waiter.status = 'waiting'
|
|
84
|
+
)
|
|
85
|
+
AND NOT EXISTS (
|
|
86
|
+
SELECT 1
|
|
87
|
+
FROM xai_capacity_waiters waiter
|
|
88
|
+
WHERE waiter.workspace_id = session_row.workspace_id
|
|
89
|
+
AND waiter.session_id = session_row.id
|
|
90
|
+
AND waiter.status = 'waiting'
|
|
91
|
+
)
|
|
92
|
+
)
|
|
93
|
+
OR (
|
|
94
|
+
session_row.status = 'requires_action'
|
|
95
|
+
AND EXISTS (
|
|
96
|
+
SELECT 1
|
|
97
|
+
FROM session_turns turn_row
|
|
98
|
+
JOIN session_events trigger_event
|
|
99
|
+
ON trigger_event.workspace_id = turn_row.workspace_id
|
|
100
|
+
AND trigger_event.session_id = turn_row.session_id
|
|
101
|
+
AND trigger_event.id = turn_row.trigger_event_id
|
|
102
|
+
WHERE turn_row.workspace_id = session_row.workspace_id
|
|
103
|
+
AND turn_row.session_id = session_row.id
|
|
104
|
+
AND turn_row.id = session_row.active_turn_id
|
|
105
|
+
AND turn_row.status = 'requires_action'
|
|
106
|
+
AND turn_row.active_attempt_id IS NULL
|
|
107
|
+
AND EXISTS (
|
|
108
|
+
SELECT 1
|
|
109
|
+
FROM session_events response_event
|
|
110
|
+
WHERE response_event.workspace_id = session_row.workspace_id
|
|
111
|
+
AND response_event.session_id = session_row.id
|
|
112
|
+
AND response_event.type IN (
|
|
113
|
+
'user.approvalDecision',
|
|
114
|
+
'user.humanInputResponse'
|
|
115
|
+
)
|
|
116
|
+
AND response_event.sequence > trigger_event.sequence
|
|
117
|
+
)
|
|
118
|
+
)
|
|
119
|
+
)
|
|
120
|
+
OR (
|
|
121
|
+
session_row.active_turn_id IS NULL
|
|
122
|
+
AND session_row.status IN ('queued', 'idle')
|
|
123
|
+
AND session_row.compact_requested
|
|
124
|
+
)
|
|
125
|
+
OR (
|
|
126
|
+
session_row.active_turn_id IS NULL
|
|
127
|
+
AND session_row.status IN ('queued', 'idle')
|
|
128
|
+
AND EXISTS (
|
|
129
|
+
SELECT 1
|
|
130
|
+
FROM session_system_updates update_row
|
|
131
|
+
WHERE update_row.workspace_id = session_row.workspace_id
|
|
132
|
+
AND update_row.session_id = session_row.id
|
|
133
|
+
AND update_row.state = 'pending'
|
|
134
|
+
)
|
|
135
|
+
AND (
|
|
136
|
+
EXISTS (
|
|
137
|
+
SELECT 1
|
|
138
|
+
FROM session_system_updates update_row
|
|
139
|
+
WHERE update_row.workspace_id = session_row.workspace_id
|
|
140
|
+
AND update_row.session_id = session_row.id
|
|
141
|
+
AND update_row.state = 'pending'
|
|
142
|
+
AND update_row.kind = 'agent_steer_instruction'
|
|
143
|
+
)
|
|
144
|
+
OR NOT EXISTS (
|
|
145
|
+
SELECT 1
|
|
146
|
+
FROM session_turns failed_turn
|
|
147
|
+
JOIN session_events failure_event
|
|
148
|
+
ON failure_event.workspace_id = failed_turn.workspace_id
|
|
149
|
+
AND failure_event.session_id = failed_turn.session_id
|
|
150
|
+
AND failure_event.turn_id = failed_turn.id
|
|
151
|
+
AND failure_event.type = 'turn.failed'
|
|
152
|
+
AND failure_event.payload ->> 'code' = 'context_compaction_failed'
|
|
153
|
+
WHERE failed_turn.workspace_id = session_row.workspace_id
|
|
154
|
+
AND failed_turn.session_id = session_row.id
|
|
155
|
+
AND failed_turn.finished_at IS NOT NULL
|
|
156
|
+
AND failed_turn.id = (
|
|
157
|
+
SELECT latest_turn.id
|
|
158
|
+
FROM session_turns latest_turn
|
|
159
|
+
WHERE latest_turn.workspace_id = session_row.workspace_id
|
|
160
|
+
AND latest_turn.session_id = session_row.id
|
|
161
|
+
AND latest_turn.finished_at IS NOT NULL
|
|
162
|
+
ORDER BY
|
|
163
|
+
latest_turn.position DESC,
|
|
164
|
+
latest_turn.created_at DESC
|
|
165
|
+
LIMIT 1
|
|
166
|
+
)
|
|
167
|
+
)
|
|
168
|
+
)
|
|
169
|
+
)
|
|
170
|
+
)
|
|
171
|
+
)
|
|
172
|
+
)
|
|
173
|
+
), ancestry AS (
|
|
174
|
+
SELECT
|
|
175
|
+
candidate.session_id AS candidate_session_id,
|
|
176
|
+
session_row.workspace_id,
|
|
177
|
+
session_row.id AS session_id,
|
|
178
|
+
session_row.parent_session_id,
|
|
179
|
+
session_row.direct_control_state,
|
|
180
|
+
session_row.direct_pause_revision,
|
|
181
|
+
session_row.subtree_run_override_revision,
|
|
182
|
+
0::integer AS depth,
|
|
183
|
+
ARRAY[session_row.id]::uuid[] AS path,
|
|
184
|
+
false AS cycle
|
|
185
|
+
FROM candidates candidate
|
|
186
|
+
JOIN sessions session_row
|
|
187
|
+
ON session_row.workspace_id = candidate.workspace_id
|
|
188
|
+
AND session_row.id = candidate.session_id
|
|
189
|
+
UNION ALL
|
|
190
|
+
SELECT
|
|
191
|
+
child.candidate_session_id,
|
|
192
|
+
parent.workspace_id,
|
|
193
|
+
parent.id,
|
|
194
|
+
parent.parent_session_id,
|
|
195
|
+
parent.direct_control_state,
|
|
196
|
+
parent.direct_pause_revision,
|
|
197
|
+
parent.subtree_run_override_revision,
|
|
198
|
+
child.depth + 1,
|
|
199
|
+
child.path || parent.id,
|
|
200
|
+
parent.id = ANY(child.path)
|
|
201
|
+
FROM ancestry child
|
|
202
|
+
JOIN sessions parent
|
|
203
|
+
ON parent.workspace_id = child.workspace_id
|
|
204
|
+
AND parent.id = child.parent_session_id
|
|
205
|
+
WHERE child.parent_session_id IS NOT NULL
|
|
206
|
+
AND NOT child.cycle
|
|
207
|
+
AND child.depth < 10000
|
|
208
|
+
), orphaned AS (
|
|
209
|
+
SELECT candidate.*
|
|
210
|
+
FROM candidates candidate
|
|
211
|
+
JOIN workspace_inference_controls control_row
|
|
212
|
+
ON control_row.workspace_id = candidate.workspace_id
|
|
213
|
+
WHERE EXISTS (
|
|
214
|
+
SELECT 1
|
|
215
|
+
FROM ancestry root
|
|
216
|
+
WHERE root.candidate_session_id = candidate.session_id
|
|
217
|
+
AND root.parent_session_id IS NULL
|
|
218
|
+
AND NOT root.cycle
|
|
219
|
+
)
|
|
220
|
+
AND NOT EXISTS (
|
|
221
|
+
SELECT 1
|
|
222
|
+
FROM ancestry invalid
|
|
223
|
+
WHERE invalid.candidate_session_id = candidate.session_id
|
|
224
|
+
AND invalid.cycle
|
|
225
|
+
)
|
|
226
|
+
AND NOT EXISTS (
|
|
227
|
+
SELECT 1
|
|
228
|
+
FROM ancestry pause
|
|
229
|
+
WHERE pause.candidate_session_id = candidate.session_id
|
|
230
|
+
AND pause.direct_control_state = 'paused'
|
|
231
|
+
AND NOT EXISTS (
|
|
232
|
+
SELECT 1
|
|
233
|
+
FROM ancestry override_row
|
|
234
|
+
WHERE override_row.candidate_session_id = candidate.session_id
|
|
235
|
+
AND override_row.depth < pause.depth
|
|
236
|
+
AND override_row.subtree_run_override_revision > pause.direct_pause_revision
|
|
237
|
+
)
|
|
238
|
+
)
|
|
239
|
+
AND (
|
|
240
|
+
control_row.workspace_state = 'active'
|
|
241
|
+
OR (
|
|
242
|
+
control_row.workspace_state = 'paused'
|
|
243
|
+
AND EXISTS (
|
|
244
|
+
SELECT 1
|
|
245
|
+
FROM ancestry override_row
|
|
246
|
+
WHERE override_row.candidate_session_id = candidate.session_id
|
|
247
|
+
AND override_row.subtree_run_override_revision
|
|
248
|
+
> control_row.workspace_pause_revision
|
|
249
|
+
)
|
|
250
|
+
)
|
|
251
|
+
)
|
|
252
|
+
), seeded AS (
|
|
253
|
+
INSERT INTO session_workflow_wake_outbox (
|
|
254
|
+
session_id,
|
|
255
|
+
account_id,
|
|
256
|
+
workspace_id,
|
|
257
|
+
temporal_workflow_id,
|
|
258
|
+
reason,
|
|
259
|
+
next_attempt_at
|
|
260
|
+
)
|
|
261
|
+
SELECT
|
|
262
|
+
orphaned.session_id,
|
|
263
|
+
orphaned.account_id,
|
|
264
|
+
orphaned.workspace_id,
|
|
265
|
+
orphaned.temporal_workflow_id,
|
|
266
|
+
'unclaimed_attempt_recovery_cutover',
|
|
267
|
+
now() + interval '60 seconds'
|
|
268
|
+
FROM orphaned
|
|
269
|
+
ON CONFLICT (session_id) DO UPDATE SET
|
|
270
|
+
wake_revision = session_workflow_wake_outbox.wake_revision + 1,
|
|
271
|
+
temporal_workflow_id = excluded.temporal_workflow_id,
|
|
272
|
+
reason = excluded.reason,
|
|
273
|
+
attempts = 0,
|
|
274
|
+
next_attempt_at = CASE
|
|
275
|
+
WHEN session_workflow_wake_outbox.wake_revision
|
|
276
|
+
> session_workflow_wake_outbox.delivered_revision
|
|
277
|
+
THEN least(
|
|
278
|
+
session_workflow_wake_outbox.next_attempt_at,
|
|
279
|
+
excluded.next_attempt_at
|
|
280
|
+
)
|
|
281
|
+
ELSE excluded.next_attempt_at
|
|
282
|
+
END,
|
|
283
|
+
last_error = NULL,
|
|
284
|
+
updated_at = now()
|
|
285
|
+
RETURNING account_id, workspace_id, session_id, wake_revision, reason
|
|
286
|
+
)
|
|
287
|
+
INSERT INTO audit_events (
|
|
288
|
+
account_id,
|
|
289
|
+
workspace_id,
|
|
290
|
+
subject_id,
|
|
291
|
+
action,
|
|
292
|
+
target_type,
|
|
293
|
+
target_id,
|
|
294
|
+
metadata
|
|
295
|
+
)
|
|
296
|
+
SELECT
|
|
297
|
+
seeded.account_id,
|
|
298
|
+
seeded.workspace_id,
|
|
299
|
+
'session-recovery-migration',
|
|
300
|
+
'session.workflow.unclaimed_attempt_wake_seeded',
|
|
301
|
+
'session',
|
|
302
|
+
seeded.session_id::text,
|
|
303
|
+
jsonb_build_object(
|
|
304
|
+
'wakeRevision', seeded.wake_revision,
|
|
305
|
+
'reason', seeded.reason
|
|
306
|
+
)
|
|
307
|
+
FROM seeded;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeni/db",
|
|
3
|
-
"version": "0.36.
|
|
3
|
+
"version": "0.36.1",
|
|
4
4
|
"description": "OpenGeni persistence: Drizzle schema, RLS-scoped query layer, the SQL migration runner, and role provisioning.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -70,9 +70,9 @@
|
|
|
70
70
|
"prepublishOnly": "bash ../../scripts/prepublish-guard"
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
|
-
"@opengeni/codemode": "^0.4.
|
|
74
|
-
"@opengeni/codex": "^0.2.
|
|
75
|
-
"@opengeni/config": "^0.16.
|
|
73
|
+
"@opengeni/codemode": "^0.4.2",
|
|
74
|
+
"@opengeni/codex": "^0.2.17",
|
|
75
|
+
"@opengeni/config": "^0.16.2",
|
|
76
76
|
"@opengeni/contracts": "^0.50.0",
|
|
77
77
|
"@opengeni/network": "^0.2.2",
|
|
78
78
|
"drizzle-orm": "^0.45.2",
|