@tenetkit/pg 0.28.0
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/README.md +3 -0
- package/dist/postgres/claims.d.ts +26 -0
- package/dist/postgres/claims.js +95 -0
- package/dist/postgres/event-stream.d.ts +20 -0
- package/dist/postgres/event-stream.js +16 -0
- package/dist/postgres/index.d.ts +3 -0
- package/dist/postgres/index.js +3 -0
- package/dist/postgres/locks.d.ts +18 -0
- package/dist/postgres/locks.js +51 -0
- package/dist/postgres/pg-helpers.d.ts +91 -0
- package/dist/postgres/pg-helpers.js +359 -0
- package/dist/postgres/run-schema.d.ts +23 -0
- package/dist/postgres/run-schema.js +92 -0
- package/dist/postgres/runtime-layer.d.ts +15 -0
- package/dist/postgres/runtime-layer.js +28 -0
- package/dist/postgres/schema.d.ts +6 -0
- package/dist/postgres/schema.js +274 -0
- package/dist/postgres/session-cancellation.d.ts +11 -0
- package/dist/postgres/session-cancellation.js +15 -0
- package/dist/postgres/session-storage.d.ts +32 -0
- package/dist/postgres/session-storage.js +63 -0
- package/dist/postgres/session-store.d.ts +24 -0
- package/dist/postgres/session-store.js +388 -0
- package/dist/postgres/store-admit.d.ts +21 -0
- package/dist/postgres/store-admit.js +87 -0
- package/dist/postgres/store-cancel.d.ts +14 -0
- package/dist/postgres/store-cancel.js +73 -0
- package/dist/postgres/store-claims.d.ts +17 -0
- package/dist/postgres/store-claims.js +72 -0
- package/dist/postgres/store-fan-out.d.ts +21 -0
- package/dist/postgres/store-fan-out.js +17 -0
- package/dist/postgres/store-inspection.d.ts +12 -0
- package/dist/postgres/store-inspection.js +44 -0
- package/dist/postgres/store-messaging.d.ts +14 -0
- package/dist/postgres/store-messaging.js +12 -0
- package/dist/postgres/store-model-response.d.ts +18 -0
- package/dist/postgres/store-model-response.js +156 -0
- package/dist/postgres/store-ops.d.ts +21 -0
- package/dist/postgres/store-ops.js +328 -0
- package/dist/postgres/store-program.d.ts +18 -0
- package/dist/postgres/store-program.js +36 -0
- package/dist/postgres/store-suspend.d.ts +13 -0
- package/dist/postgres/store-suspend.js +87 -0
- package/dist/postgres/store.d.ts +7 -0
- package/dist/postgres/store.js +373 -0
- package/dist/postgres/transaction-events.d.ts +15 -0
- package/dist/postgres/transaction-events.js +23 -0
- package/package.json +54 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
export const SCHEMA_VERSION = 7;
|
|
2
|
+
export const SCHEMA_META_TABLE = "baton_schema_meta";
|
|
3
|
+
export const MIGRATIONS_TABLE = "baton_sql_migrations";
|
|
4
|
+
export const NOTIFY_CHANNEL = "baton_run_events";
|
|
5
|
+
export const SCHEMA_STATEMENTS = [
|
|
6
|
+
`CREATE TABLE IF NOT EXISTS baton_schema_meta (
|
|
7
|
+
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
8
|
+
version INTEGER NOT NULL,
|
|
9
|
+
checksum TEXT NOT NULL,
|
|
10
|
+
dirty BOOLEAN NOT NULL DEFAULT FALSE,
|
|
11
|
+
applied_at TIMESTAMPTZ NOT NULL
|
|
12
|
+
)`,
|
|
13
|
+
`CREATE TABLE IF NOT EXISTS baton_lanes (
|
|
14
|
+
address TEXT NOT NULL,
|
|
15
|
+
session_id TEXT NOT NULL,
|
|
16
|
+
accepted_sequence BIGINT NOT NULL,
|
|
17
|
+
queue_json TEXT NOT NULL,
|
|
18
|
+
head_run_id TEXT,
|
|
19
|
+
PRIMARY KEY (address, session_id)
|
|
20
|
+
)`,
|
|
21
|
+
`CREATE TABLE IF NOT EXISTS baton_runs (
|
|
22
|
+
run_id TEXT PRIMARY KEY,
|
|
23
|
+
status TEXT NOT NULL,
|
|
24
|
+
address TEXT NOT NULL,
|
|
25
|
+
session_id TEXT NOT NULL,
|
|
26
|
+
message_id TEXT NOT NULL,
|
|
27
|
+
message_json TEXT NOT NULL,
|
|
28
|
+
message_digest TEXT NOT NULL,
|
|
29
|
+
idempotency_key TEXT NOT NULL,
|
|
30
|
+
executable_ref_json TEXT NOT NULL,
|
|
31
|
+
executable_manifest_json TEXT NOT NULL,
|
|
32
|
+
root_run_id TEXT NOT NULL,
|
|
33
|
+
depth INTEGER NOT NULL,
|
|
34
|
+
max_depth INTEGER NOT NULL,
|
|
35
|
+
max_subagents INTEGER NOT NULL,
|
|
36
|
+
parent_run_id TEXT,
|
|
37
|
+
invocation_id TEXT,
|
|
38
|
+
active_wait_id TEXT,
|
|
39
|
+
attempt INTEGER NOT NULL DEFAULT 0,
|
|
40
|
+
attempt_fence INTEGER NOT NULL DEFAULT 0,
|
|
41
|
+
last_sequence INTEGER NOT NULL DEFAULT -1,
|
|
42
|
+
cancellation_requested BOOLEAN NOT NULL DEFAULT FALSE,
|
|
43
|
+
cancel_reason TEXT,
|
|
44
|
+
terminal_event_id TEXT,
|
|
45
|
+
accepted_sequence BIGINT NOT NULL,
|
|
46
|
+
responded_wait_ids_json TEXT NOT NULL,
|
|
47
|
+
driver_checkpoint_json TEXT,
|
|
48
|
+
suspension_json TEXT,
|
|
49
|
+
continuation_json TEXT,
|
|
50
|
+
pending_outcome_json TEXT,
|
|
51
|
+
owner_worker_id TEXT,
|
|
52
|
+
lease_expires_at TIMESTAMPTZ,
|
|
53
|
+
created_at TIMESTAMPTZ NOT NULL,
|
|
54
|
+
updated_at TIMESTAMPTZ NOT NULL,
|
|
55
|
+
UNIQUE (address, session_id, idempotency_key)
|
|
56
|
+
)`,
|
|
57
|
+
`CREATE TABLE IF NOT EXISTS baton_run_events (
|
|
58
|
+
run_id TEXT NOT NULL REFERENCES baton_runs(run_id),
|
|
59
|
+
sequence INTEGER NOT NULL,
|
|
60
|
+
event_id TEXT NOT NULL UNIQUE,
|
|
61
|
+
event_json TEXT NOT NULL,
|
|
62
|
+
PRIMARY KEY (run_id, sequence)
|
|
63
|
+
)`,
|
|
64
|
+
`CREATE TABLE IF NOT EXISTS baton_run_operations (
|
|
65
|
+
run_id TEXT NOT NULL REFERENCES baton_runs(run_id),
|
|
66
|
+
operation_id TEXT NOT NULL,
|
|
67
|
+
operation_key TEXT NOT NULL,
|
|
68
|
+
kind TEXT NOT NULL,
|
|
69
|
+
status TEXT NOT NULL,
|
|
70
|
+
input_digest TEXT NOT NULL,
|
|
71
|
+
input_json TEXT NOT NULL,
|
|
72
|
+
result_json TEXT,
|
|
73
|
+
error_json TEXT,
|
|
74
|
+
replay_policy TEXT NOT NULL,
|
|
75
|
+
attempt INTEGER NOT NULL,
|
|
76
|
+
owner_worker_id TEXT,
|
|
77
|
+
lease_expires_at TIMESTAMPTZ,
|
|
78
|
+
started_at TIMESTAMPTZ,
|
|
79
|
+
finished_at TIMESTAMPTZ,
|
|
80
|
+
resolution_idempotency_key TEXT,
|
|
81
|
+
resolution_json TEXT,
|
|
82
|
+
PRIMARY KEY (run_id, operation_id),
|
|
83
|
+
UNIQUE (run_id, operation_key)
|
|
84
|
+
)`,
|
|
85
|
+
`CREATE TABLE IF NOT EXISTS baton_run_waits (
|
|
86
|
+
run_id TEXT NOT NULL REFERENCES baton_runs(run_id),
|
|
87
|
+
wait_id TEXT NOT NULL,
|
|
88
|
+
reason TEXT NOT NULL,
|
|
89
|
+
status TEXT NOT NULL,
|
|
90
|
+
response_json TEXT,
|
|
91
|
+
due_at TIMESTAMPTZ,
|
|
92
|
+
owner_worker_id TEXT,
|
|
93
|
+
lease_expires_at TIMESTAMPTZ,
|
|
94
|
+
opened_at TIMESTAMPTZ NOT NULL,
|
|
95
|
+
closed_at TIMESTAMPTZ,
|
|
96
|
+
PRIMARY KEY (run_id, wait_id)
|
|
97
|
+
)`,
|
|
98
|
+
`CREATE TABLE IF NOT EXISTS baton_run_links (
|
|
99
|
+
parent_run_id TEXT NOT NULL REFERENCES baton_runs(run_id),
|
|
100
|
+
child_run_id TEXT NOT NULL REFERENCES baton_runs(run_id),
|
|
101
|
+
invocation_id TEXT NOT NULL,
|
|
102
|
+
readiness TEXT NOT NULL,
|
|
103
|
+
terminal_event_id TEXT,
|
|
104
|
+
created_at TIMESTAMPTZ NOT NULL,
|
|
105
|
+
settled_at TIMESTAMPTZ,
|
|
106
|
+
PRIMARY KEY (parent_run_id, child_run_id),
|
|
107
|
+
UNIQUE (child_run_id)
|
|
108
|
+
)`,
|
|
109
|
+
`CREATE INDEX IF NOT EXISTS baton_run_links_readiness_idx ON baton_run_links(parent_run_id, readiness, created_at, child_run_id)`,
|
|
110
|
+
`CREATE TABLE IF NOT EXISTS baton_run_steering (
|
|
111
|
+
entry_id TEXT PRIMARY KEY,
|
|
112
|
+
run_id TEXT NOT NULL REFERENCES baton_runs(run_id),
|
|
113
|
+
sequence BIGINT NOT NULL,
|
|
114
|
+
idempotency_key TEXT NOT NULL,
|
|
115
|
+
digest TEXT NOT NULL,
|
|
116
|
+
prompt_json TEXT NOT NULL,
|
|
117
|
+
consumed_operation_id TEXT,
|
|
118
|
+
discarded_reason TEXT,
|
|
119
|
+
UNIQUE (run_id, sequence),
|
|
120
|
+
UNIQUE (run_id, idempotency_key)
|
|
121
|
+
)`,
|
|
122
|
+
`CREATE INDEX IF NOT EXISTS baton_run_steering_pending_idx
|
|
123
|
+
ON baton_run_steering(run_id, sequence) WHERE consumed_operation_id IS NULL AND discarded_reason IS NULL`,
|
|
124
|
+
`CREATE TABLE IF NOT EXISTS baton_agent_names (
|
|
125
|
+
scope TEXT NOT NULL,
|
|
126
|
+
name TEXT NOT NULL,
|
|
127
|
+
run_id TEXT NOT NULL REFERENCES baton_runs(run_id),
|
|
128
|
+
PRIMARY KEY (scope, name)
|
|
129
|
+
)`,
|
|
130
|
+
`CREATE INDEX IF NOT EXISTS baton_agent_names_run_idx ON baton_agent_names(run_id)`,
|
|
131
|
+
`CREATE TABLE IF NOT EXISTS baton_messages (
|
|
132
|
+
entry_id TEXT PRIMARY KEY,
|
|
133
|
+
target_session_id TEXT NOT NULL,
|
|
134
|
+
sequence BIGINT NOT NULL,
|
|
135
|
+
from_address TEXT NOT NULL,
|
|
136
|
+
from_run_id TEXT NOT NULL,
|
|
137
|
+
to_address TEXT NOT NULL,
|
|
138
|
+
message_id TEXT NOT NULL,
|
|
139
|
+
idempotency_key TEXT NOT NULL,
|
|
140
|
+
digest TEXT NOT NULL,
|
|
141
|
+
bytes BIGINT NOT NULL,
|
|
142
|
+
admitted_at_millis BIGINT NOT NULL,
|
|
143
|
+
prompt_json TEXT NOT NULL,
|
|
144
|
+
correlation_id TEXT NOT NULL,
|
|
145
|
+
causation_id TEXT,
|
|
146
|
+
in_reply_to TEXT,
|
|
147
|
+
metadata_json TEXT NOT NULL,
|
|
148
|
+
delivered_run_id TEXT,
|
|
149
|
+
steering_entry_id TEXT,
|
|
150
|
+
UNIQUE (target_session_id, message_id, idempotency_key),
|
|
151
|
+
UNIQUE (target_session_id, sequence)
|
|
152
|
+
)`,
|
|
153
|
+
`CREATE INDEX IF NOT EXISTS baton_messages_pending_idx
|
|
154
|
+
ON baton_messages(target_session_id, sequence) WHERE delivered_run_id IS NULL`,
|
|
155
|
+
`CREATE INDEX IF NOT EXISTS baton_runs_claim_idx
|
|
156
|
+
ON baton_runs(status, lease_expires_at)
|
|
157
|
+
WHERE status IN ('queued', 'running', 'waiting', 'needs-resolution', 'cancelling')`,
|
|
158
|
+
`CREATE INDEX IF NOT EXISTS baton_lanes_head_idx ON baton_lanes(head_run_id)`,
|
|
159
|
+
`CREATE INDEX IF NOT EXISTS baton_run_operations_status_idx ON baton_run_operations(status)`,
|
|
160
|
+
`CREATE INDEX IF NOT EXISTS baton_run_waits_due_idx ON baton_run_waits(status, due_at)`,
|
|
161
|
+
`CREATE TABLE IF NOT EXISTS baton_fan_outs (
|
|
162
|
+
fan_out_id TEXT PRIMARY KEY,
|
|
163
|
+
parent_run_id TEXT NOT NULL REFERENCES baton_runs(run_id),
|
|
164
|
+
idempotency_key TEXT NOT NULL,
|
|
165
|
+
input_digest TEXT NOT NULL,
|
|
166
|
+
join_json TEXT NOT NULL,
|
|
167
|
+
remainder TEXT NOT NULL,
|
|
168
|
+
concurrency INTEGER NOT NULL,
|
|
169
|
+
status TEXT NOT NULL,
|
|
170
|
+
created_at TIMESTAMPTZ NOT NULL,
|
|
171
|
+
updated_at TIMESTAMPTZ NOT NULL,
|
|
172
|
+
UNIQUE (parent_run_id, idempotency_key)
|
|
173
|
+
)`,
|
|
174
|
+
`CREATE TABLE IF NOT EXISTS baton_fan_out_members (
|
|
175
|
+
fan_out_id TEXT NOT NULL REFERENCES baton_fan_outs(fan_out_id),
|
|
176
|
+
ordinal INTEGER NOT NULL,
|
|
177
|
+
member_key TEXT NOT NULL,
|
|
178
|
+
selection TEXT NOT NULL,
|
|
179
|
+
display_label TEXT,
|
|
180
|
+
prompt_json TEXT NOT NULL,
|
|
181
|
+
origin_json TEXT,
|
|
182
|
+
child_run_id TEXT NOT NULL UNIQUE REFERENCES baton_runs(run_id),
|
|
183
|
+
depth INTEGER NOT NULL,
|
|
184
|
+
status TEXT NOT NULL,
|
|
185
|
+
terminal_event_id TEXT,
|
|
186
|
+
outcome_json TEXT,
|
|
187
|
+
PRIMARY KEY (fan_out_id, ordinal),
|
|
188
|
+
UNIQUE (fan_out_id, member_key)
|
|
189
|
+
)`,
|
|
190
|
+
`CREATE INDEX IF NOT EXISTS baton_fan_out_members_status_idx ON baton_fan_out_members(fan_out_id, status, ordinal)`,
|
|
191
|
+
`CREATE TABLE IF NOT EXISTS baton_tree_roots (
|
|
192
|
+
root_run_id TEXT PRIMARY KEY REFERENCES baton_runs(run_id),
|
|
193
|
+
earliest_position BIGINT NOT NULL DEFAULT 0,
|
|
194
|
+
last_position BIGINT NOT NULL DEFAULT -1
|
|
195
|
+
)`,
|
|
196
|
+
`CREATE TABLE IF NOT EXISTS baton_tree_event_index (
|
|
197
|
+
root_run_id TEXT NOT NULL REFERENCES baton_tree_roots(root_run_id),
|
|
198
|
+
position BIGINT NOT NULL,
|
|
199
|
+
run_id TEXT NOT NULL,
|
|
200
|
+
run_sequence INTEGER NOT NULL,
|
|
201
|
+
event_id TEXT NOT NULL UNIQUE REFERENCES baton_run_events(event_id),
|
|
202
|
+
PRIMARY KEY (root_run_id, position),
|
|
203
|
+
UNIQUE (run_id, run_sequence),
|
|
204
|
+
FOREIGN KEY (run_id, run_sequence) REFERENCES baton_run_events(run_id, sequence)
|
|
205
|
+
)`,
|
|
206
|
+
`CREATE TABLE IF NOT EXISTS baton_program_runs (
|
|
207
|
+
run_id TEXT PRIMARY KEY REFERENCES baton_runs(run_id),
|
|
208
|
+
program_pin TEXT NOT NULL,
|
|
209
|
+
budget_json TEXT NOT NULL,
|
|
210
|
+
deadline_millis BIGINT NOT NULL,
|
|
211
|
+
tool_calls BIGINT NOT NULL DEFAULT 0,
|
|
212
|
+
agent_runs BIGINT NOT NULL DEFAULT 0,
|
|
213
|
+
tokens BIGINT NOT NULL DEFAULT 0,
|
|
214
|
+
log_bytes BIGINT NOT NULL DEFAULT 0,
|
|
215
|
+
active_slots BIGINT NOT NULL DEFAULT 0
|
|
216
|
+
)`,
|
|
217
|
+
`CREATE TABLE IF NOT EXISTS baton_program_operations (
|
|
218
|
+
run_id TEXT NOT NULL REFERENCES baton_program_runs(run_id),
|
|
219
|
+
operation_name TEXT NOT NULL,
|
|
220
|
+
kind TEXT NOT NULL,
|
|
221
|
+
capability TEXT NOT NULL,
|
|
222
|
+
input_digest TEXT NOT NULL,
|
|
223
|
+
input_json TEXT NOT NULL,
|
|
224
|
+
replay_policy TEXT NOT NULL,
|
|
225
|
+
status TEXT NOT NULL,
|
|
226
|
+
result_json TEXT,
|
|
227
|
+
error_json TEXT,
|
|
228
|
+
wait_id TEXT,
|
|
229
|
+
fan_out_id TEXT,
|
|
230
|
+
child_run_ids_json TEXT NOT NULL,
|
|
231
|
+
resolution_idempotency_key TEXT,
|
|
232
|
+
resolution_json TEXT,
|
|
233
|
+
PRIMARY KEY (run_id, operation_name)
|
|
234
|
+
)`,
|
|
235
|
+
`CREATE TABLE IF NOT EXISTS baton_executable_registrations (
|
|
236
|
+
pin TEXT PRIMARY KEY,
|
|
237
|
+
codec TEXT NOT NULL,
|
|
238
|
+
version TEXT NOT NULL,
|
|
239
|
+
payload_json TEXT NOT NULL,
|
|
240
|
+
registration_digest TEXT NOT NULL
|
|
241
|
+
)`,
|
|
242
|
+
`CREATE TABLE IF NOT EXISTS baton_run_registrations (
|
|
243
|
+
run_id TEXT NOT NULL REFERENCES baton_runs(run_id),
|
|
244
|
+
pin TEXT NOT NULL REFERENCES baton_executable_registrations(pin),
|
|
245
|
+
PRIMARY KEY (run_id, pin)
|
|
246
|
+
)`,
|
|
247
|
+
`CREATE INDEX IF NOT EXISTS baton_run_registrations_pin_idx ON baton_run_registrations(pin)`,
|
|
248
|
+
`CREATE TABLE IF NOT EXISTS baton_sessions (
|
|
249
|
+
session_id TEXT PRIMARY KEY,
|
|
250
|
+
leaf_id TEXT,
|
|
251
|
+
next_seq BIGINT NOT NULL DEFAULT 0,
|
|
252
|
+
owner_token TEXT,
|
|
253
|
+
updated_at TIMESTAMPTZ NOT NULL
|
|
254
|
+
)`,
|
|
255
|
+
`CREATE TABLE IF NOT EXISTS baton_session_entries (
|
|
256
|
+
session_id TEXT NOT NULL,
|
|
257
|
+
entry_id TEXT NOT NULL,
|
|
258
|
+
parent_id TEXT,
|
|
259
|
+
seq BIGINT NOT NULL,
|
|
260
|
+
tag TEXT NOT NULL,
|
|
261
|
+
payload_json TEXT NOT NULL,
|
|
262
|
+
created_at TIMESTAMPTZ NOT NULL,
|
|
263
|
+
PRIMARY KEY (session_id, entry_id)
|
|
264
|
+
)`,
|
|
265
|
+
`CREATE UNIQUE INDEX IF NOT EXISTS baton_session_entries_seq_idx ON baton_session_entries(session_id, seq)`,
|
|
266
|
+
`CREATE INDEX IF NOT EXISTS baton_session_entries_parent_idx ON baton_session_entries(session_id, parent_id)`,
|
|
267
|
+
];
|
|
268
|
+
export const schemaChecksum = () => {
|
|
269
|
+
const hasher = new Bun.CryptoHasher("sha256");
|
|
270
|
+
hasher.update(SCHEMA_STATEMENTS.join("\n"));
|
|
271
|
+
hasher.update(`\nversion=${SCHEMA_VERSION}`);
|
|
272
|
+
hasher.update("\ndialect=postgres");
|
|
273
|
+
return hasher.digest("hex");
|
|
274
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import type { PgClient } from "@effect/sql-pg";
|
|
3
|
+
import type { SqlClient } from "effect/unstable/sql";
|
|
4
|
+
import type { SqlError } from "effect/unstable/sql/SqlError";
|
|
5
|
+
import type { RunNotFound, RuntimeUnavailable } from "tenetkit/runtime/driver/errors";
|
|
6
|
+
export declare const cancelSessionRuns: (input: {
|
|
7
|
+
readonly lockRun: (runId: string) => Effect.Effect<void, SqlError, SqlClient.SqlClient>;
|
|
8
|
+
readonly cancelRun: (runId: string, reason?: string) => Effect.Effect<void, RunNotFound | RuntimeUnavailable | SqlError, SqlClient.SqlClient | PgClient.PgClient>;
|
|
9
|
+
readonly sessionId: string;
|
|
10
|
+
readonly reason?: string;
|
|
11
|
+
}) => Effect.Effect<string[], RuntimeUnavailable | SqlError, PgClient.PgClient | SqlClient.SqlClient>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { activeSessionRuns, sessionRoots, sessionRuns } from "tenetkit/runtime/driver/sql/session-lifecycle";
|
|
3
|
+
export const cancelSessionRuns = (input) => Effect.gen(function* () {
|
|
4
|
+
const roots = yield* sessionRoots(input.sessionId);
|
|
5
|
+
const runs = yield* sessionRuns(input.sessionId);
|
|
6
|
+
const active = yield* activeSessionRuns(input.sessionId);
|
|
7
|
+
for (const runId of runs)
|
|
8
|
+
yield* input.lockRun(runId);
|
|
9
|
+
for (const runId of roots) {
|
|
10
|
+
yield* input
|
|
11
|
+
.cancelRun(runId, input.reason)
|
|
12
|
+
.pipe(Effect.catchTag("tenetkit/runtime/RunNotFound", () => Effect.void));
|
|
13
|
+
}
|
|
14
|
+
return active;
|
|
15
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { Session } from "tenetkit";
|
|
3
|
+
import { SqlClient } from "effect/unstable/sql";
|
|
4
|
+
import type { SqlError } from "effect/unstable/sql/SqlError";
|
|
5
|
+
import { type EntryRow, type SessionRow } from "tenetkit/runtime/driver/sql/session-store";
|
|
6
|
+
declare const insertEntry: (input: {
|
|
7
|
+
readonly sessionId: string;
|
|
8
|
+
readonly id: string;
|
|
9
|
+
readonly parentId: string | null;
|
|
10
|
+
readonly seq: number;
|
|
11
|
+
readonly tag: string;
|
|
12
|
+
readonly payload: Session.EntryPayload;
|
|
13
|
+
}) => Effect.Effect<void, SqlError, SqlClient.SqlClient>;
|
|
14
|
+
declare const advanceSession: (input: {
|
|
15
|
+
readonly sessionId: string;
|
|
16
|
+
readonly leafId: string | null;
|
|
17
|
+
readonly nextSeq: number;
|
|
18
|
+
readonly ownerToken?: string;
|
|
19
|
+
}) => Effect.Effect<void, SqlError, SqlClient.SqlClient>;
|
|
20
|
+
export declare const PostgresSessionStorage: {
|
|
21
|
+
readonly encodePayload: (payload: Session.EntryPayload) => string;
|
|
22
|
+
readonly entryPayloadEquivalence: (self: Session.EntryPayload, that: Session.EntryPayload) => boolean;
|
|
23
|
+
readonly storeError: (message: string) => Session.SessionStoreError;
|
|
24
|
+
readonly toEntry: (row: EntryRow) => Session.Entry;
|
|
25
|
+
readonly lockSession: (sessionId: string) => Effect.Effect<SessionRow, Session.SessionStoreError | SqlError, SqlClient.SqlClient>;
|
|
26
|
+
readonly loadEntries: (sessionId: string) => Effect.Effect<ReadonlyArray<EntryRow>, SqlError, SqlClient.SqlClient>;
|
|
27
|
+
readonly pathFromRows: (rows: ReadonlyArray<EntryRow>, leaf: string | null) => ReadonlyArray<Session.Entry> | Session.SessionStoreError;
|
|
28
|
+
readonly requireActive: (rows: ReadonlyArray<EntryRow>, leaf: string | null, entryId: string, reason?: "stale-leaf" | "checkpoint-not-on-active-path") => Session.SessionConflict | undefined;
|
|
29
|
+
readonly insertEntry: typeof insertEntry;
|
|
30
|
+
readonly advanceSession: typeof advanceSession;
|
|
31
|
+
};
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { Session } from "tenetkit";
|
|
3
|
+
import { SqlClient } from "effect/unstable/sql";
|
|
4
|
+
import { SessionStorage } from "tenetkit/runtime/driver/sql/session-store";
|
|
5
|
+
const { encodePayload, entryPayloadEquivalence, pathFromRows, requireActive, storeError, toEntry } = SessionStorage;
|
|
6
|
+
const lockSession = (sessionId) => Effect.gen(function* () {
|
|
7
|
+
const sql = yield* SqlClient.SqlClient;
|
|
8
|
+
yield* sql `
|
|
9
|
+
INSERT INTO baton_sessions (session_id, leaf_id, next_seq, owner_token, updated_at)
|
|
10
|
+
VALUES (${sessionId}, NULL, 0, NULL, NOW())
|
|
11
|
+
ON CONFLICT (session_id) DO NOTHING
|
|
12
|
+
`;
|
|
13
|
+
const rows = yield* sql `
|
|
14
|
+
SELECT leaf_id, next_seq, owner_token FROM baton_sessions
|
|
15
|
+
WHERE session_id = ${sessionId}
|
|
16
|
+
FOR UPDATE
|
|
17
|
+
`;
|
|
18
|
+
const row = rows[0];
|
|
19
|
+
return row === undefined ? yield* storeError(`Session ${sessionId} could not be initialized`) : row;
|
|
20
|
+
});
|
|
21
|
+
const loadEntries = (sessionId) => Effect.gen(function* () {
|
|
22
|
+
const sql = yield* SqlClient.SqlClient;
|
|
23
|
+
return yield* sql `
|
|
24
|
+
SELECT entry_id, parent_id, seq, tag, payload_json FROM baton_session_entries
|
|
25
|
+
WHERE session_id = ${sessionId} ORDER BY seq
|
|
26
|
+
`;
|
|
27
|
+
});
|
|
28
|
+
const insertEntry = (input) => Effect.gen(function* () {
|
|
29
|
+
const sql = yield* SqlClient.SqlClient;
|
|
30
|
+
yield* sql `
|
|
31
|
+
INSERT INTO baton_session_entries (session_id, entry_id, parent_id, seq, tag, payload_json, created_at)
|
|
32
|
+
VALUES (${input.sessionId}, ${input.id}, ${input.parentId}, ${input.seq}, ${input.tag},
|
|
33
|
+
${encodePayload(input.payload)}, NOW())
|
|
34
|
+
`;
|
|
35
|
+
});
|
|
36
|
+
const advanceSession = (input) => Effect.gen(function* () {
|
|
37
|
+
const sql = yield* SqlClient.SqlClient;
|
|
38
|
+
if (input.ownerToken === undefined) {
|
|
39
|
+
yield* sql `
|
|
40
|
+
UPDATE baton_sessions SET leaf_id = ${input.leafId}, next_seq = ${input.nextSeq}, updated_at = NOW()
|
|
41
|
+
WHERE session_id = ${input.sessionId}
|
|
42
|
+
`;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
yield* sql `
|
|
46
|
+
UPDATE baton_sessions SET leaf_id = ${input.leafId}, next_seq = ${input.nextSeq},
|
|
47
|
+
owner_token = ${input.ownerToken}, updated_at = NOW()
|
|
48
|
+
WHERE session_id = ${input.sessionId}
|
|
49
|
+
`;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
export const PostgresSessionStorage = {
|
|
53
|
+
encodePayload,
|
|
54
|
+
entryPayloadEquivalence,
|
|
55
|
+
storeError,
|
|
56
|
+
toEntry,
|
|
57
|
+
lockSession,
|
|
58
|
+
loadEntries,
|
|
59
|
+
pathFromRows,
|
|
60
|
+
requireActive,
|
|
61
|
+
insertEntry,
|
|
62
|
+
advanceSession,
|
|
63
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { Session } from "tenetkit";
|
|
3
|
+
import { SqlClient } from "effect/unstable/sql";
|
|
4
|
+
import type { SqlError } from "effect/unstable/sql/SqlError";
|
|
5
|
+
import type { CompletedSessionEntry } from "tenetkit/runtime/driver/model-response-commit";
|
|
6
|
+
import type { InterruptedSessionEntry } from "tenetkit/runtime/driver/agent-event";
|
|
7
|
+
import { type HandoffSessionEntry } from "tenetkit/runtime/driver/handoff-session";
|
|
8
|
+
import type { RunFn } from "./store-ops.js";
|
|
9
|
+
/** Append or verify one exact completed assistant projection in the caller's PostgreSQL transaction. */
|
|
10
|
+
export declare const appendCompletedSessionEntry: (input: CompletedSessionEntry) => Effect.Effect<Session.Entry, Session.SessionConflict | Session.SessionStoreError | SqlError, SqlClient.SqlClient>;
|
|
11
|
+
/** Verify an exact completed assistant projection in the caller's PostgreSQL transaction. */
|
|
12
|
+
export declare const verifyCompletedSessionEntry: (input: CompletedSessionEntry) => Effect.Effect<void, Session.SessionConflict | Session.SessionStoreError | SqlError, SqlClient.SqlClient>;
|
|
13
|
+
/** Append or verify one exact nonempty interrupted assistant projection in the caller's transaction. */
|
|
14
|
+
export declare const appendInterruptedSessionEntry: (input: InterruptedSessionEntry) => Effect.Effect<Session.Entry, Session.SessionConflict | Session.SessionStoreError | SqlError, SqlClient.SqlClient>;
|
|
15
|
+
export declare const verifyInterruptedSessionEntry: (input: InterruptedSessionEntry) => Effect.Effect<void, Session.SessionConflict | Session.SessionStoreError | SqlError, SqlClient.SqlClient>;
|
|
16
|
+
/** Append or verify one exact handoff projection in the caller's PostgreSQL transaction. */
|
|
17
|
+
export declare const appendHandoffSessionEntry: (input: HandoffSessionEntry) => Effect.Effect<Session.HandoffEntry, Session.SessionConflict | Session.SessionStoreError | SqlError, SqlClient.SqlClient>;
|
|
18
|
+
export declare const verifyHandoffSessionEntry: (input: HandoffSessionEntry) => Effect.Effect<void, Session.SessionConflict | Session.SessionStoreError | SqlError, SqlClient.SqlClient>;
|
|
19
|
+
/** Dialect-native durable PostgreSQL Session authority bound to one session identity. */
|
|
20
|
+
export declare const makePostgresSessionStore: (options: {
|
|
21
|
+
readonly sessionId: string;
|
|
22
|
+
readonly run: RunFn;
|
|
23
|
+
readonly runNoTxn: RunFn;
|
|
24
|
+
}) => Session.Interface;
|