@sema-agent/server 1.315.0 → 1.317.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 +9 -0
- package/README.zh-CN.md +7 -0
- package/dist/config-types.d.ts +1 -1
- package/dist/config.d.ts +14 -0
- package/dist/config.js +148 -45
- package/dist/elicitation.js +2 -2
- package/dist/http/idempotency.d.ts +1 -0
- package/dist/http/idempotency.js +3 -0
- package/dist/http/principal-gate.d.ts +12 -0
- package/dist/http/principal-gate.js +52 -0
- package/dist/http/route-ctx.d.ts +116 -0
- package/dist/http/route-ctx.js +2 -0
- package/dist/http/routes/approvals-assistant.d.ts +11 -0
- package/dist/http/routes/approvals-assistant.js +530 -0
- package/dist/http/routes/attachments.d.ts +4 -0
- package/dist/http/routes/attachments.js +106 -0
- package/dist/http/routes/capabilities.d.ts +4 -0
- package/dist/http/routes/capabilities.js +111 -0
- package/dist/http/routes/fleet.d.ts +4 -0
- package/dist/http/routes/fleet.js +147 -0
- package/dist/http/routes/images.d.ts +20 -0
- package/dist/http/routes/images.js +572 -0
- package/dist/http/routes/leader.d.ts +4 -0
- package/dist/http/routes/leader.js +48 -0
- package/dist/http/routes/memory-policy.d.ts +4 -0
- package/dist/http/routes/memory-policy.js +105 -0
- package/dist/http/routes/notify-wake.d.ts +4 -0
- package/dist/http/routes/notify-wake.js +133 -0
- package/dist/http/routes/observability.d.ts +4 -0
- package/dist/http/routes/observability.js +63 -0
- package/dist/http/routes/runs.d.ts +19 -0
- package/dist/http/routes/runs.js +967 -0
- package/dist/http/routes/session-sync.d.ts +36 -0
- package/dist/http/routes/session-sync.js +513 -0
- package/dist/http/routes/sessions-list.d.ts +4 -0
- package/dist/http/routes/sessions-list.js +117 -0
- package/dist/http/routes/sessions.d.ts +17 -0
- package/dist/http/routes/sessions.js +746 -0
- package/dist/http/routes/side-query.d.ts +4 -0
- package/dist/http/routes/side-query.js +88 -0
- package/dist/http/routes/tasks.d.ts +4 -0
- package/dist/http/routes/tasks.js +632 -0
- package/dist/http/routes/trace-usage.d.ts +4 -0
- package/dist/http/routes/trace-usage.js +239 -0
- package/dist/http/routes/workflows.d.ts +5 -0
- package/dist/http/routes/workflows.js +337 -0
- package/dist/http/run-meta.d.ts +11 -0
- package/dist/http/run-meta.js +16 -0
- package/dist/http/send.d.ts +7 -0
- package/dist/http/send.js +34 -0
- package/dist/http/server.d.ts +12 -12
- package/dist/http/server.js +289 -5502
- package/dist/http/sse-log.d.ts +25 -0
- package/dist/http/sse-log.js +59 -0
- package/dist/http/wire-types.d.ts +6 -0
- package/dist/http/workspace-content.d.ts +3 -0
- package/dist/http/workspace-content.js +20 -0
- package/dist/leader/endpoint.js +4 -4
- package/dist/main.js +5 -5
- package/dist/plugins/approval-store-sql.d.ts +52 -0
- package/dist/plugins/approval-store-sql.js +119 -0
- package/dist/plugins/breaker-state-sql.d.ts +29 -0
- package/dist/plugins/breaker-state-sql.js +104 -0
- package/dist/plugins/file-snapshot-store-sql.d.ts +38 -0
- package/dist/plugins/file-snapshot-store-sql.js +210 -0
- package/dist/plugins/image-index-sql.d.ts +33 -0
- package/dist/plugins/image-index-sql.js +328 -0
- package/dist/plugins/outcome-ledger-sql.d.ts +70 -0
- package/dist/plugins/outcome-ledger-sql.js +158 -0
- package/dist/plugins/pg-approval-store.d.ts +1 -27
- package/dist/plugins/pg-approval-store.js +1 -83
- package/dist/plugins/pg-breaker-state.d.ts +1 -19
- package/dist/plugins/pg-breaker-state.js +1 -88
- package/dist/plugins/pg-file-snapshot-store.d.ts +1 -27
- package/dist/plugins/pg-file-snapshot-store.js +1 -190
- package/dist/plugins/pg-image-index.d.ts +1 -21
- package/dist/plugins/pg-image-index.js +1 -217
- package/dist/plugins/pg-outcome-ledger.d.ts +2 -22
- package/dist/plugins/pg-outcome-ledger.js +1 -104
- package/dist/plugins/pg-resume-anchor-store.d.ts +1 -13
- package/dist/plugins/pg-resume-anchor-store.js +1 -22
- package/dist/plugins/pg-run-store.d.ts +1 -75
- package/dist/plugins/pg-run-store.js +1 -287
- package/dist/plugins/pg-session-policy-store.d.ts +1 -11
- package/dist/plugins/pg-session-policy-store.js +1 -90
- package/dist/plugins/pg-tool-result-store.d.ts +1 -15
- package/dist/plugins/pg-tool-result-store.js +1 -52
- package/dist/plugins/pg-workflow-journal-store.d.ts +1 -20
- package/dist/plugins/pg-workflow-journal-store.js +1 -34
- package/dist/plugins/pg-workflow-run-store.d.ts +1 -55
- package/dist/plugins/pg-workflow-run-store.js +1 -220
- package/dist/plugins/remote-env-host.js +4 -3
- package/dist/plugins/resume-anchor-store-sql.d.ts +23 -0
- package/dist/plugins/resume-anchor-store-sql.js +38 -0
- package/dist/plugins/run-store-sql.d.ts +89 -0
- package/dist/plugins/run-store-sql.js +397 -0
- package/dist/plugins/session-policy-store-sql.d.ts +22 -0
- package/dist/plugins/session-policy-store-sql.js +109 -0
- package/dist/plugins/tidb-approval-store.d.ts +1 -39
- package/dist/plugins/tidb-approval-store.js +1 -71
- package/dist/plugins/tidb-breaker-state.d.ts +1 -17
- package/dist/plugins/tidb-breaker-state.js +1 -74
- package/dist/plugins/tidb-file-snapshot-store.d.ts +1 -27
- package/dist/plugins/tidb-file-snapshot-store.js +1 -192
- package/dist/plugins/tidb-image-index.d.ts +1 -19
- package/dist/plugins/tidb-image-index.js +1 -149
- package/dist/plugins/tidb-outcome-ledger.d.ts +1 -57
- package/dist/plugins/tidb-outcome-ledger.js +1 -97
- package/dist/plugins/tidb-resume-anchor-store.d.ts +1 -13
- package/dist/plugins/tidb-resume-anchor-store.js +1 -22
- package/dist/plugins/tidb-run-store.d.ts +1 -75
- package/dist/plugins/tidb-run-store.js +1 -306
- package/dist/plugins/tidb-session-policy-store.d.ts +1 -11
- package/dist/plugins/tidb-session-policy-store.js +1 -86
- package/dist/plugins/tidb-tool-result-store.d.ts +1 -13
- package/dist/plugins/tidb-tool-result-store.js +1 -38
- package/dist/plugins/tidb-workflow-journal-store.d.ts +1 -20
- package/dist/plugins/tidb-workflow-journal-store.js +1 -34
- package/dist/plugins/tidb-workflow-run-store.d.ts +1 -61
- package/dist/plugins/tidb-workflow-run-store.js +1 -231
- package/dist/plugins/tool-result-store-sql.d.ts +25 -0
- package/dist/plugins/tool-result-store-sql.js +69 -0
- package/dist/plugins/workflow-journal-store-sql.d.ts +30 -0
- package/dist/plugins/workflow-journal-store-sql.js +53 -0
- package/dist/plugins/workflow-run-store-sql.d.ts +85 -0
- package/dist/plugins/workflow-run-store-sql.js +299 -0
- package/dist/question.js +2 -2
- package/dist/run-local.js +1 -1
- package/dist/tool-approval.js +2 -2
- package/dist/trace/ledger-sink.js +1 -1
- package/dist/trace/project.d.ts +1 -0
- package/dist/trace/project.js +3 -0
- package/package.json +1 -1
|
@@ -1,288 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import { escapeLike } from "./sql-escape.js";
|
|
3
|
-
import { pgSafeJsonStringify, pgSanitizeText } from "./pg-safe-json.js";
|
|
4
|
-
import { parseJsonLenient as parseJson, toIso as iso } from "./sql-row-helpers.js";
|
|
5
|
-
function isDupKey(err) {
|
|
6
|
-
return Boolean(err) && err.code === "23505";
|
|
7
|
-
}
|
|
8
|
-
export class PgRunStore {
|
|
9
|
-
pool;
|
|
10
|
-
constructor(pool) {
|
|
11
|
-
this.pool = pool;
|
|
12
|
-
}
|
|
13
|
-
async tx(fn) {
|
|
14
|
-
const c = await this.pool.connect();
|
|
15
|
-
try {
|
|
16
|
-
await c.query("BEGIN");
|
|
17
|
-
const out = await fn(c);
|
|
18
|
-
await c.query("COMMIT");
|
|
19
|
-
return out;
|
|
20
|
-
}
|
|
21
|
-
catch (err) {
|
|
22
|
-
try {
|
|
23
|
-
await c.query("ROLLBACK");
|
|
24
|
-
}
|
|
25
|
-
catch {
|
|
26
|
-
}
|
|
27
|
-
throw err;
|
|
28
|
-
}
|
|
29
|
-
finally {
|
|
30
|
-
c.release();
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
async createRun(taskId, sessionId, owner, instanceId, meta = {}) {
|
|
34
|
-
const c = await this.pool.connect();
|
|
35
|
-
try {
|
|
36
|
-
await c.query("BEGIN");
|
|
37
|
-
const now = new Date();
|
|
38
|
-
try {
|
|
39
|
-
await c.query("INSERT INTO task_active (session_id, task_id, since) VALUES ($1,$2,$3)", [sessionId, taskId, now]);
|
|
40
|
-
}
|
|
41
|
-
catch (err) {
|
|
42
|
-
if (isDupKey(err)) {
|
|
43
|
-
await c.query("ROLLBACK");
|
|
44
|
-
const active = await c.query("SELECT task_id FROM task_active WHERE session_id = $1", [sessionId]);
|
|
45
|
-
return { ok: false, activeTaskId: String(active.rows[0]?.task_id ?? "") };
|
|
46
|
-
}
|
|
47
|
-
throw err;
|
|
48
|
-
}
|
|
49
|
-
await c.query("INSERT INTO task_run (task_id, session_id, owner, status, instance_id, job_id, source, objective_preview, created_at, updated_at) " +
|
|
50
|
-
"VALUES ($1,$2,$3,'running',$4,$5,$6,$7,$8,$9)", [taskId, sessionId, owner, instanceId, meta.jobId ?? null, meta.source ?? null, meta.objectivePreview == null ? null : pgSanitizeText(meta.objectivePreview), now, now]);
|
|
51
|
-
await c.query("COMMIT");
|
|
52
|
-
return { ok: true };
|
|
53
|
-
}
|
|
54
|
-
catch (err) {
|
|
55
|
-
try {
|
|
56
|
-
await c.query("ROLLBACK");
|
|
57
|
-
}
|
|
58
|
-
catch {
|
|
59
|
-
}
|
|
60
|
-
throw err;
|
|
61
|
-
}
|
|
62
|
-
finally {
|
|
63
|
-
c.release();
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
async requestCancel(taskId, owner) {
|
|
67
|
-
const r = await this.pool.query("UPDATE task_run SET cancel_requested = 1 WHERE task_id = $1 AND owner IS NOT DISTINCT FROM $2 AND status = 'running'", [taskId, owner]);
|
|
68
|
-
return (r.rowCount ?? 0) > 0;
|
|
69
|
-
}
|
|
70
|
-
async isCancelRequested(taskId, owner) {
|
|
71
|
-
const r = await this.pool.query("SELECT cancel_requested FROM task_run WHERE task_id = $1 AND owner IS NOT DISTINCT FROM $2", [taskId, owner]);
|
|
72
|
-
return Boolean(r.rows[0]?.cancel_requested);
|
|
73
|
-
}
|
|
74
|
-
async requestPreempt(taskId, owner) {
|
|
75
|
-
const r = await this.pool.query("UPDATE task_run SET preempt_requested = 1 WHERE task_id = $1 AND owner IS NOT DISTINCT FROM $2 AND status = 'running'", [taskId, owner]);
|
|
76
|
-
return (r.rowCount ?? 0) > 0;
|
|
77
|
-
}
|
|
78
|
-
async isPreemptRequested(taskId, owner) {
|
|
79
|
-
const r = await this.pool.query("SELECT preempt_requested FROM task_run WHERE task_id = $1 AND owner IS NOT DISTINCT FROM $2", [taskId, owner]);
|
|
80
|
-
return Boolean(r.rows[0]?.preempt_requested);
|
|
81
|
-
}
|
|
82
|
-
async heartbeat(taskId, owner) {
|
|
83
|
-
await this.pool.query("UPDATE task_run SET updated_at = $1 WHERE task_id = $2 AND owner IS NOT DISTINCT FROM $3 AND status = 'running'", [new Date(), taskId, owner]);
|
|
84
|
-
}
|
|
85
|
-
async appendEvent(taskId, seq, type, data) {
|
|
86
|
-
await this.pool.query("INSERT INTO task_event (task_id, seq, type, data, ts) VALUES ($1,$2,$3,$4::jsonb,$5)", [
|
|
87
|
-
taskId,
|
|
88
|
-
seq,
|
|
89
|
-
type,
|
|
90
|
-
data == null ? null : pgSafeJsonStringify(data),
|
|
91
|
-
new Date(),
|
|
92
|
-
]);
|
|
93
|
-
}
|
|
94
|
-
async maxSeq(taskId) {
|
|
95
|
-
const r = await this.pool.query("SELECT MAX(seq) AS m FROM task_event WHERE task_id = $1", [taskId]);
|
|
96
|
-
const m = r.rows[0]?.m;
|
|
97
|
-
return m == null ? 0 : Number(m);
|
|
98
|
-
}
|
|
99
|
-
async setTerminal(taskId, status, result, error) {
|
|
100
|
-
const errorCode = result?.errorCode ?? null;
|
|
101
|
-
await this.tx(async (c) => {
|
|
102
|
-
await c.query("UPDATE task_run SET status = $1, result = $2::jsonb, error = $3, error_code = $4, updated_at = $5 WHERE task_id = $6 AND status IN ('running','suspended','needs_review')", [
|
|
103
|
-
status,
|
|
104
|
-
result == null ? null : pgSafeJsonStringify(result),
|
|
105
|
-
error == null ? null : pgSanitizeText(error),
|
|
106
|
-
errorCode == null ? null : pgSanitizeText(errorCode),
|
|
107
|
-
new Date(),
|
|
108
|
-
taskId,
|
|
109
|
-
]);
|
|
110
|
-
await c.query("DELETE FROM task_active WHERE task_id = $1", [taskId]);
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
async setSuspended(taskId) {
|
|
114
|
-
await this.pool.query("UPDATE task_run SET status = 'suspended', updated_at = $1 WHERE task_id = $2 AND status IN ('running','suspended')", [new Date(), taskId]);
|
|
115
|
-
}
|
|
116
|
-
async setNeedsReview(taskId) {
|
|
117
|
-
await this.pool.query("UPDATE task_run SET status = 'needs_review', updated_at = $1 WHERE task_id = $2 AND status IN ('running','needs_review')", [new Date(), taskId]);
|
|
118
|
-
}
|
|
119
|
-
async markResuming(taskId) {
|
|
120
|
-
const r = await this.pool.query("UPDATE task_run SET status = 'running', cancel_requested = 0, preempt_requested = 0, updated_at = $1 WHERE task_id = $2 AND status IN ('suspended','needs_review')", [new Date(), taskId]);
|
|
121
|
-
return (r.rowCount ?? 0) === 1;
|
|
122
|
-
}
|
|
123
|
-
async getActiveTaskId(sessionId) {
|
|
124
|
-
const r = await this.pool.query("SELECT task_id FROM task_active WHERE session_id = $1", [sessionId]);
|
|
125
|
-
return r.rows[0] ? String(r.rows[0].task_id) : undefined;
|
|
126
|
-
}
|
|
127
|
-
rowToRun(r) {
|
|
128
|
-
return {
|
|
129
|
-
taskId: String(r.task_id),
|
|
130
|
-
sessionId: String(r.session_id),
|
|
131
|
-
owner: r.owner ?? null,
|
|
132
|
-
status: r.status,
|
|
133
|
-
result: parseJson(r.result),
|
|
134
|
-
error: r.error ?? null,
|
|
135
|
-
errorCode: r.error_code ?? null,
|
|
136
|
-
jobId: r.job_id ?? null,
|
|
137
|
-
source: r.source ?? null,
|
|
138
|
-
instanceId: r.instance_id ?? null,
|
|
139
|
-
objectivePreview: r.objective_preview ?? null,
|
|
140
|
-
createdAt: iso(r.created_at),
|
|
141
|
-
updatedAt: iso(r.updated_at),
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
async getRun(taskId) {
|
|
145
|
-
const r = await this.pool.query("SELECT task_id, session_id, owner, status, result, error, error_code, job_id, source, instance_id, objective_preview, created_at, updated_at FROM task_run WHERE task_id = $1", [taskId]);
|
|
146
|
-
return r.rows[0] ? this.rowToRun(r.rows[0]) : undefined;
|
|
147
|
-
}
|
|
148
|
-
async listRuns(opts) {
|
|
149
|
-
if (opts.cursor && Number.isNaN(Date.parse(opts.cursor.createdAt)))
|
|
150
|
-
return [];
|
|
151
|
-
const where = [];
|
|
152
|
-
const params = [];
|
|
153
|
-
const p = (v) => {
|
|
154
|
-
params.push(v);
|
|
155
|
-
return `$${params.length}`;
|
|
156
|
-
};
|
|
157
|
-
if (opts.status)
|
|
158
|
-
where.push(`status = ${p(opts.status)}`);
|
|
159
|
-
if (opts.jobId)
|
|
160
|
-
where.push(`job_id = ${p(opts.jobId)}`);
|
|
161
|
-
if (opts.source)
|
|
162
|
-
where.push(`source = ${p(opts.source)}`);
|
|
163
|
-
if (opts.owner)
|
|
164
|
-
where.push(`owner = ${p(opts.owner)}`);
|
|
165
|
-
if (opts.cursor) {
|
|
166
|
-
const a = p(new Date(opts.cursor.createdAt));
|
|
167
|
-
const b = p(new Date(opts.cursor.createdAt));
|
|
168
|
-
const t = p(opts.cursor.taskId);
|
|
169
|
-
where.push(`(created_at < ${a} OR (created_at = ${b} AND task_id < ${t}))`);
|
|
170
|
-
}
|
|
171
|
-
const sql = "SELECT task_id, session_id, owner, status, result, error, error_code, job_id, source, objective_preview, created_at, updated_at FROM task_run" +
|
|
172
|
-
(where.length ? " WHERE " + where.join(" AND ") : "") +
|
|
173
|
-
` ORDER BY created_at DESC, task_id DESC LIMIT ${p(opts.limit)}`;
|
|
174
|
-
const r = await this.pool.query(sql, params);
|
|
175
|
-
return r.rows.map((row) => this.rowToRun(row));
|
|
176
|
-
}
|
|
177
|
-
async listSessions(opts) {
|
|
178
|
-
const params = [];
|
|
179
|
-
const p = (v) => {
|
|
180
|
-
params.push(v);
|
|
181
|
-
return `$${params.length}`;
|
|
182
|
-
};
|
|
183
|
-
const innerWhere = opts.owner ? ` WHERE owner = ${p(opts.owner)}` : "";
|
|
184
|
-
const outer = ["rn = 1"];
|
|
185
|
-
if (opts.q)
|
|
186
|
-
outer.push(`EXISTS (SELECT 1 FROM task_run tr WHERE tr.session_id = t.session_id AND LOWER(tr.objective_preview) LIKE LOWER(${p(`%${escapeLike(opts.q)}%`)}) ESCAPE '\\')`);
|
|
187
|
-
if (opts.cursor) {
|
|
188
|
-
const a = p(new Date(opts.cursor.lastActivityAt));
|
|
189
|
-
const b = p(new Date(opts.cursor.lastActivityAt));
|
|
190
|
-
const sid = p(opts.cursor.sessionId);
|
|
191
|
-
outer.push(`(last_activity < ${a} OR (last_activity = ${b} AND session_id < ${sid}))`);
|
|
192
|
-
}
|
|
193
|
-
const sql = "SELECT session_id, owner, task_id, last_activity, first_activity, run_count, objective_preview, status FROM (" +
|
|
194
|
-
"SELECT session_id, owner, task_id, objective_preview, status," +
|
|
195
|
-
" ROW_NUMBER() OVER (PARTITION BY session_id ORDER BY created_at DESC, task_id DESC) AS rn," +
|
|
196
|
-
" MAX(created_at) OVER (PARTITION BY session_id) AS last_activity," +
|
|
197
|
-
" MIN(created_at) OVER (PARTITION BY session_id) AS first_activity," +
|
|
198
|
-
" COUNT(*) OVER (PARTITION BY session_id) AS run_count" +
|
|
199
|
-
" FROM task_run" + innerWhere + ") t WHERE " + outer.join(" AND ") +
|
|
200
|
-
` ORDER BY last_activity DESC, session_id DESC LIMIT ${p(opts.limit)}`;
|
|
201
|
-
const r = await this.pool.query(sql, params);
|
|
202
|
-
return r.rows.map((row) => ({
|
|
203
|
-
sessionId: String(row.session_id),
|
|
204
|
-
owner: row.owner ?? null,
|
|
205
|
-
lastActivityAt: iso(row.last_activity),
|
|
206
|
-
firstActivityAt: iso(row.first_activity),
|
|
207
|
-
runCount: Number(row.run_count),
|
|
208
|
-
objectivePreview: row.objective_preview ?? null,
|
|
209
|
-
lastStatus: String(row.status),
|
|
210
|
-
lastRunId: row.task_id ?? null,
|
|
211
|
-
title: null,
|
|
212
|
-
}));
|
|
213
|
-
}
|
|
214
|
-
async deleteBySession(sessionId, owner) {
|
|
215
|
-
return this.tx(async (c) => {
|
|
216
|
-
const active = await c.query("SELECT task_id FROM task_active WHERE session_id = $1 FOR UPDATE", [sessionId]);
|
|
217
|
-
if (active.rows[0])
|
|
218
|
-
return { active: String(active.rows[0].task_id) };
|
|
219
|
-
await c.query("DELETE FROM task_event te USING task_run tr WHERE te.task_id = tr.task_id AND tr.session_id = $1 AND tr.owner IS NOT DISTINCT FROM $2", [sessionId, owner]);
|
|
220
|
-
await c.query("DELETE FROM task_active ta USING task_run tr WHERE ta.task_id = tr.task_id AND tr.session_id = $1 AND tr.owner IS NOT DISTINCT FROM $2", [sessionId, owner]);
|
|
221
|
-
const res = await c.query("DELETE FROM task_run WHERE session_id = $1 AND owner IS NOT DISTINCT FROM $2", [sessionId, owner]);
|
|
222
|
-
return { removed: res.rowCount ?? 0 };
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
async sourceSummary(sinceMs) {
|
|
226
|
-
const r = await this.pool.query("SELECT source, status, COUNT(*) AS c FROM task_run WHERE created_at >= $1 GROUP BY source, status", [new Date(sinceMs)]);
|
|
227
|
-
return r.rows.map((row) => ({ source: row.source ?? null, status: String(row.status), count: Number(row.c) }));
|
|
228
|
-
}
|
|
229
|
-
async usageScan(fromMs, toMs, opts) {
|
|
230
|
-
const limit = Math.min(opts?.limit ?? USAGE_SCAN_LIMIT, USAGE_SCAN_LIMIT);
|
|
231
|
-
const where = ["created_at >= $1", "created_at < $2"];
|
|
232
|
-
const params = [new Date(fromMs), new Date(toMs)];
|
|
233
|
-
if (opts?.owner !== undefined) {
|
|
234
|
-
where.push("owner = $3");
|
|
235
|
-
params.push(opts.owner);
|
|
236
|
-
}
|
|
237
|
-
const r = await this.pool.query(`SELECT owner, created_at, status, result FROM task_run WHERE ${where.join(" AND ")} ORDER BY created_at LIMIT ${limit + 1}`, params);
|
|
238
|
-
const truncated = r.rows.length > limit;
|
|
239
|
-
const page = truncated ? r.rows.slice(0, limit) : r.rows;
|
|
240
|
-
return {
|
|
241
|
-
truncated,
|
|
242
|
-
rows: page.map((row) => ({
|
|
243
|
-
owner: row.owner ?? null,
|
|
244
|
-
createdAtMs: new Date(row.created_at).getTime(),
|
|
245
|
-
status: String(row.status),
|
|
246
|
-
...(row.result != null ? { stats: projectUsageStats(row.result) } : {}),
|
|
247
|
-
})),
|
|
248
|
-
};
|
|
249
|
-
}
|
|
250
|
-
async retainedFrom(taskId) {
|
|
251
|
-
const r = await this.pool.query("SELECT MIN(seq) AS m FROM task_event WHERE task_id = $1", [taskId]);
|
|
252
|
-
const m = r.rows[0]?.m;
|
|
253
|
-
return m == null ? 0 : Number(m);
|
|
254
|
-
}
|
|
255
|
-
async getEvents(taskId, afterSeq) {
|
|
256
|
-
const r = await this.pool.query("SELECT seq, type, data, ts FROM task_event WHERE task_id = $1 AND seq > $2 ORDER BY seq ASC", [taskId, afterSeq]);
|
|
257
|
-
return r.rows.map((row) => ({ seq: Number(row.seq), type: String(row.type), data: parseJson(row.data), ts: iso(row.ts) }));
|
|
258
|
-
}
|
|
259
|
-
async reapStale(olderThanMs) {
|
|
260
|
-
const cutoff = new Date(Date.now() - olderThanMs);
|
|
261
|
-
return this.tx(async (c) => {
|
|
262
|
-
const res = await c.query("UPDATE task_run SET status = 'failed', error = 'run stalled (instance lost?)', updated_at = $1 WHERE status = 'running' AND updated_at < $2", [new Date(), cutoff]);
|
|
263
|
-
await c.query("DELETE FROM task_active ta USING task_run tr WHERE ta.task_id = tr.task_id AND tr.status NOT IN ('running','suspended','needs_review')");
|
|
264
|
-
return res.rowCount ?? 0;
|
|
265
|
-
});
|
|
266
|
-
}
|
|
267
|
-
async reapSuspended(olderThanMs) {
|
|
268
|
-
const cutoff = new Date(Date.now() - olderThanMs);
|
|
269
|
-
return this.tx(async (c) => {
|
|
270
|
-
const res = await c.query("UPDATE task_run AS tr SET status = 'failed', error = 'approval expired before decision', error_code = 'approval.expired', updated_at = $1 " +
|
|
271
|
-
"WHERE tr.status = 'suspended' AND tr.updated_at < $2 " +
|
|
272
|
-
"AND NOT EXISTS (SELECT 1 FROM checkpoint c WHERE c.session_id = tr.session_id AND c.status = 'pending')", [new Date(), cutoff]);
|
|
273
|
-
await c.query("DELETE FROM task_active ta USING task_run tr WHERE ta.task_id = tr.task_id AND tr.status NOT IN ('running','suspended','needs_review')");
|
|
274
|
-
return res.rowCount ?? 0;
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
async failSuspendedWithExpiredCheckpoint() {
|
|
278
|
-
return this.tx(async (c) => {
|
|
279
|
-
const res = await c.query("UPDATE task_run AS tr SET status = 'failed', error = 'approval expired before decision', error_code = 'approval.expired', updated_at = $1 " +
|
|
280
|
-
"WHERE tr.status IN ('suspended','needs_review') " +
|
|
281
|
-
"AND EXISTS (SELECT 1 FROM checkpoint ce WHERE ce.session_id = tr.session_id AND ce.status = 'expired') " +
|
|
282
|
-
"AND NOT EXISTS (SELECT 1 FROM checkpoint cp WHERE cp.session_id = tr.session_id AND cp.status = 'pending')", [new Date()]);
|
|
283
|
-
await c.query("DELETE FROM task_active ta USING task_run tr WHERE ta.task_id = tr.task_id AND tr.status NOT IN ('running','suspended','needs_review')");
|
|
284
|
-
return res.rowCount ?? 0;
|
|
285
|
-
});
|
|
286
|
-
}
|
|
287
|
-
}
|
|
1
|
+
export { PgRunStore } from "./run-store-sql.js";
|
|
288
2
|
//# sourceMappingURL=pg-run-store.js.map
|
|
@@ -1,12 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import type { Pool } from "pg";
|
|
3
|
-
export declare class PgSessionPolicyStore implements SessionPolicyStore {
|
|
4
|
-
private readonly pool;
|
|
5
|
-
constructor(pool: Pool);
|
|
6
|
-
getRules(sessionId: string, principal?: string): Promise<StoredSessionRules | null>;
|
|
7
|
-
listBySession(sessionId: string): Promise<SessionRulesRecord[]>;
|
|
8
|
-
putRules(sessionId: string, principal: string | undefined, rules: SessionPermissionRules, opts?: PutRulesOptions): Promise<StoredSessionRules>;
|
|
9
|
-
deleteBySession(sessionId: string): Promise<void>;
|
|
10
|
-
private tx;
|
|
11
|
-
}
|
|
1
|
+
export { PgSessionPolicyStore } from "./session-policy-store-sql.js";
|
|
12
2
|
//# sourceMappingURL=pg-session-policy-store.d.ts.map
|
|
@@ -1,91 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import { loosenReasons, SessionPolicyError, normalizeRules, stripRev } from "@sema-agent/core";
|
|
3
|
-
import { pgHasUnstorable } from "./pg-safe-json.js";
|
|
4
|
-
const policyKey = (sessionId, principal) => createHash("sha256").update(JSON.stringify([sessionId, principal ?? null])).digest("hex");
|
|
5
|
-
const parseRules = (v) => (typeof v === "string" ? JSON.parse(v) : v);
|
|
6
|
-
const isDupKey = (e) => e?.code === "23505";
|
|
7
|
-
export class PgSessionPolicyStore {
|
|
8
|
-
pool;
|
|
9
|
-
constructor(pool) {
|
|
10
|
-
this.pool = pool;
|
|
11
|
-
}
|
|
12
|
-
async getRules(sessionId, principal) {
|
|
13
|
-
const r = await this.pool.query("SELECT rules, rev FROM session_policy WHERE policy_key = $1", [policyKey(sessionId, principal)]);
|
|
14
|
-
if (!r.rows[0])
|
|
15
|
-
return null;
|
|
16
|
-
return { ...parseRules(r.rows[0].rules), rev: Number(r.rows[0].rev) };
|
|
17
|
-
}
|
|
18
|
-
async listBySession(sessionId) {
|
|
19
|
-
const r = await this.pool.query("SELECT principal, rules, rev FROM session_policy WHERE session_id = $1", [sessionId]);
|
|
20
|
-
return r.rows.map((row) => ({
|
|
21
|
-
principal: row.principal == null ? undefined : String(row.principal),
|
|
22
|
-
rules: { ...parseRules(row.rules), rev: Number(row.rev) },
|
|
23
|
-
}));
|
|
24
|
-
}
|
|
25
|
-
async putRules(sessionId, principal, rules, opts) {
|
|
26
|
-
const key = policyKey(sessionId, principal);
|
|
27
|
-
for (let attempt = 0;; attempt++) {
|
|
28
|
-
try {
|
|
29
|
-
return await this.tx(async (c) => {
|
|
30
|
-
const r = await c.query("SELECT rules, rev FROM session_policy WHERE policy_key = $1 FOR UPDATE", [key]);
|
|
31
|
-
const prior = r.rows[0] ? { rules: parseRules(r.rows[0].rules), rev: Number(r.rows[0].rev) } : undefined;
|
|
32
|
-
const priorRev = prior?.rev ?? 0;
|
|
33
|
-
if (opts?.expectedRev !== undefined && priorRev !== opts.expectedRev) {
|
|
34
|
-
throw new SessionPolicyError("conflict", `session rules rev mismatch (expected ${opts.expectedRev}, have ${priorRev})`);
|
|
35
|
-
}
|
|
36
|
-
const clean = normalizeRules(stripRev(rules));
|
|
37
|
-
if (prior && opts?.operator !== true) {
|
|
38
|
-
const loosens = loosenReasons(prior.rules, clean);
|
|
39
|
-
if (loosens.length > 0) {
|
|
40
|
-
throw new SessionPolicyError("loosen_forbidden", `a non-operator session-rule write may only tighten; refused: ${loosens.join("; ")}`);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
const nextRev = priorRev + 1;
|
|
44
|
-
if (pgHasUnstorable(clean)) {
|
|
45
|
-
throw new SessionPolicyError("loosen_forbidden", "rules contain unstorable bytes (NUL / lone surrogate) — refused; strip them at the source (authorization rules are never rewritten by the store)");
|
|
46
|
-
}
|
|
47
|
-
const json = JSON.stringify(clean);
|
|
48
|
-
const now = new Date();
|
|
49
|
-
if (prior) {
|
|
50
|
-
const u = await c.query("UPDATE session_policy SET principal = $1, rules = $2::jsonb, rev = $3, updated_at = $4 WHERE policy_key = $5 AND rev = $6", [principal ?? null, json, nextRev, now, key, priorRev]);
|
|
51
|
-
if ((u.rowCount ?? 0) !== 1)
|
|
52
|
-
throw new SessionPolicyError("conflict", `session rules rev mismatch (expected ${opts?.expectedRev ?? priorRev}, have ${priorRev})`);
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
await c.query("INSERT INTO session_policy (policy_key, session_id, principal, rules, rev, created_at, updated_at) VALUES ($1,$2,$3,$4::jsonb,$5,$6,$7)", [key, sessionId, principal ?? null, json, nextRev, now, now]);
|
|
56
|
-
}
|
|
57
|
-
return structuredClone({ ...clean, rev: nextRev });
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
catch (e) {
|
|
61
|
-
if (isDupKey(e) && attempt < 4)
|
|
62
|
-
continue;
|
|
63
|
-
throw e;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
async deleteBySession(sessionId) {
|
|
68
|
-
await this.pool.query("DELETE FROM session_policy WHERE session_id = $1", [sessionId]);
|
|
69
|
-
}
|
|
70
|
-
async tx(fn) {
|
|
71
|
-
const c = await this.pool.connect();
|
|
72
|
-
try {
|
|
73
|
-
await c.query("BEGIN");
|
|
74
|
-
const out = await fn(c);
|
|
75
|
-
await c.query("COMMIT");
|
|
76
|
-
return out;
|
|
77
|
-
}
|
|
78
|
-
catch (err) {
|
|
79
|
-
try {
|
|
80
|
-
await c.query("ROLLBACK");
|
|
81
|
-
}
|
|
82
|
-
catch {
|
|
83
|
-
}
|
|
84
|
-
throw err;
|
|
85
|
-
}
|
|
86
|
-
finally {
|
|
87
|
-
c.release();
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
1
|
+
export { PgSessionPolicyStore } from "./session-policy-store-sql.js";
|
|
91
2
|
//# sourceMappingURL=pg-session-policy-store.js.map
|
|
@@ -1,16 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import type { Pool, PoolClient } from "pg";
|
|
3
|
-
export declare const PG_TOOL_RESULT_SCHEMA: string[];
|
|
4
|
-
export declare function ensureSchema(pool: Pool | PoolClient): Promise<void>;
|
|
5
|
-
export declare class PgToolResultStore implements ToolResultStore {
|
|
6
|
-
private readonly pool;
|
|
7
|
-
constructor(pool: Pool);
|
|
8
|
-
put(ref: string, content: string): Promise<void>;
|
|
9
|
-
get(ref: string, opts?: {
|
|
10
|
-
offset?: number;
|
|
11
|
-
limit?: number;
|
|
12
|
-
}): Promise<ToolResultSlice | undefined>;
|
|
13
|
-
reapOlderThan(cutoffMs: number): Promise<number>;
|
|
14
|
-
deleteBySession(sessionId: string): Promise<number>;
|
|
15
|
-
}
|
|
1
|
+
export { PgToolResultStore, PG_TOOL_RESULT_SCHEMA, ensureSchema } from "./tool-result-store-sql.js";
|
|
16
2
|
//# sourceMappingURL=pg-tool-result-store.d.ts.map
|
|
@@ -1,53 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import { pgSanitizeText } from "./pg-safe-json.js";
|
|
3
|
-
export const PG_TOOL_RESULT_SCHEMA = [
|
|
4
|
-
`CREATE TABLE IF NOT EXISTS tool_result (
|
|
5
|
-
ref VARCHAR(190) NOT NULL,
|
|
6
|
-
content TEXT NOT NULL,
|
|
7
|
-
created_at TIMESTAMPTZ(3) NOT NULL,
|
|
8
|
-
PRIMARY KEY (ref)
|
|
9
|
-
)`,
|
|
10
|
-
`CREATE INDEX IF NOT EXISTS idx_tool_result_created ON tool_result (created_at)`,
|
|
11
|
-
];
|
|
12
|
-
export async function ensureSchema(pool) {
|
|
13
|
-
for (const stmt of PG_TOOL_RESULT_SCHEMA)
|
|
14
|
-
await pool.query(stmt);
|
|
15
|
-
}
|
|
16
|
-
export class PgToolResultStore {
|
|
17
|
-
pool;
|
|
18
|
-
constructor(pool) {
|
|
19
|
-
this.pool = pool;
|
|
20
|
-
}
|
|
21
|
-
async put(ref, content) {
|
|
22
|
-
const safe = pgSanitizeText(Buffer.from(content, "utf8").toString("utf8"));
|
|
23
|
-
await this.pool.query("INSERT INTO tool_result (ref, content, created_at) VALUES ($1,$2,$3) ON CONFLICT (ref) DO NOTHING", [ref, safe, new Date()]);
|
|
24
|
-
}
|
|
25
|
-
async get(ref, opts = {}) {
|
|
26
|
-
const offset = Math.max(0, Math.floor(opts.offset ?? 0));
|
|
27
|
-
const hasLimit = opts.limit !== undefined && Number.isFinite(opts.limit);
|
|
28
|
-
const limit = hasLimit ? Math.max(0, Math.floor(opts.limit)) : 0;
|
|
29
|
-
const sql = hasLimit
|
|
30
|
-
? "SELECT SUBSTRING(content FROM $1::int FOR $2::int) AS slice, CHAR_LENGTH(content) AS total FROM tool_result WHERE ref = $3"
|
|
31
|
-
: "SELECT SUBSTRING(content FROM $1::int) AS slice, CHAR_LENGTH(content) AS total FROM tool_result WHERE ref = $2";
|
|
32
|
-
const params = hasLimit ? [offset + 1, limit, ref] : [offset + 1, ref];
|
|
33
|
-
const res = await this.pool.query(sql, params);
|
|
34
|
-
if (res.rows.length === 0)
|
|
35
|
-
return undefined;
|
|
36
|
-
return { content: String(res.rows[0].slice ?? ""), offset, totalChars: Number(res.rows[0].total) };
|
|
37
|
-
}
|
|
38
|
-
async reapOlderThan(cutoffMs) {
|
|
39
|
-
try {
|
|
40
|
-
const res = await this.pool.query("DELETE FROM tool_result WHERE created_at < $1", [new Date(cutoffMs)]);
|
|
41
|
-
return res.rowCount ?? 0;
|
|
42
|
-
}
|
|
43
|
-
catch {
|
|
44
|
-
return 0;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
async deleteBySession(sessionId) {
|
|
48
|
-
const prefix = `${escapeLike(`tr_${sessionId}_`)}%`;
|
|
49
|
-
const res = await this.pool.query("DELETE FROM tool_result WHERE ref LIKE $1 ESCAPE '\\'", [prefix]);
|
|
50
|
-
return res.rowCount ?? 0;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
1
|
+
export { PgToolResultStore, PG_TOOL_RESULT_SCHEMA, ensureSchema } from "./tool-result-store-sql.js";
|
|
53
2
|
//# sourceMappingURL=pg-tool-result-store.js.map
|
|
@@ -1,21 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import { type WorkflowJournalEntry, type WorkflowJournalStore } from "@sema-agent/core";
|
|
3
|
-
export declare class PgWorkflowJournalStore implements WorkflowJournalStore {
|
|
4
|
-
private readonly pool;
|
|
5
|
-
constructor(pool: Pool);
|
|
6
|
-
append(runId: string, scope: string, entry: WorkflowJournalEntry): Promise<void>;
|
|
7
|
-
load(runId: string, scope: string): Promise<WorkflowJournalEntry[]>;
|
|
8
|
-
locator(runId: string, _scope: string): string;
|
|
9
|
-
loadPage(runId: string, scope: string, opts: {
|
|
10
|
-
offset: number;
|
|
11
|
-
limit: number;
|
|
12
|
-
maxResultBytes: number;
|
|
13
|
-
}): Promise<Array<{
|
|
14
|
-
callKey: string;
|
|
15
|
-
resultJson: string | null;
|
|
16
|
-
resultBytes: number;
|
|
17
|
-
}>>;
|
|
18
|
-
deleteByRun(runId: string): Promise<number>;
|
|
19
|
-
reapExpired(now: number, maxAgeMs: number): Promise<number>;
|
|
20
|
-
}
|
|
1
|
+
export { PgWorkflowJournalStore } from "./workflow-journal-store-sql.js";
|
|
21
2
|
//# sourceMappingURL=pg-workflow-journal-store.d.ts.map
|
|
@@ -1,35 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import { oversizeJournalResult } from "./workflow-journal-limits.js";
|
|
3
|
-
export class PgWorkflowJournalStore {
|
|
4
|
-
pool;
|
|
5
|
-
constructor(pool) {
|
|
6
|
-
this.pool = pool;
|
|
7
|
-
}
|
|
8
|
-
async append(runId, scope, entry) {
|
|
9
|
-
const serialized = JSON.stringify(entry.result);
|
|
10
|
-
if (oversizeJournalResult(serialized))
|
|
11
|
-
return;
|
|
12
|
-
await this.pool.query("INSERT INTO workflow_journal (run_id, ordinal, scope, call_key, result, created_at) VALUES ($1,$2,$3,$4,$5,$6) " +
|
|
13
|
-
"ON CONFLICT (run_id, ordinal) DO UPDATE SET call_key = EXCLUDED.call_key, result = EXCLUDED.result", [runId, callKeyOrdinal(entry.callKey), scope, entry.callKey, serialized, Date.now()]);
|
|
14
|
-
}
|
|
15
|
-
async load(runId, scope) {
|
|
16
|
-
const r = await this.pool.query("SELECT call_key, result FROM workflow_journal WHERE run_id = $1 AND scope = $2 ORDER BY ordinal ASC", [runId, scope]);
|
|
17
|
-
return r.rows.map((row) => ({ callKey: String(row.call_key), result: JSON.parse(String(row.result)) }));
|
|
18
|
-
}
|
|
19
|
-
locator(runId, _scope) {
|
|
20
|
-
return `/v1/workflows/${runId}/journal`;
|
|
21
|
-
}
|
|
22
|
-
async loadPage(runId, scope, opts) {
|
|
23
|
-
const r = await this.pool.query("SELECT call_key, CASE WHEN OCTET_LENGTH(result) > $3 THEN NULL ELSE result END AS result_json, OCTET_LENGTH(result) AS result_bytes FROM workflow_journal WHERE run_id = $1 AND scope = $2 ORDER BY ordinal ASC LIMIT $4 OFFSET $5", [runId, scope, opts.maxResultBytes, opts.limit, opts.offset]);
|
|
24
|
-
return r.rows.map((row) => ({ callKey: String(row.call_key), resultJson: row.result_json === null ? null : String(row.result_json), resultBytes: Number(row.result_bytes) }));
|
|
25
|
-
}
|
|
26
|
-
async deleteByRun(runId) {
|
|
27
|
-
const r = await this.pool.query("DELETE FROM workflow_journal WHERE run_id = $1", [runId]);
|
|
28
|
-
return r.rowCount ?? 0;
|
|
29
|
-
}
|
|
30
|
-
async reapExpired(now, maxAgeMs) {
|
|
31
|
-
const r = await this.pool.query("DELETE FROM workflow_journal WHERE created_at < $1", [now - maxAgeMs]);
|
|
32
|
-
return r.rowCount ?? 0;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
1
|
+
export { PgWorkflowJournalStore } from "./workflow-journal-store-sql.js";
|
|
35
2
|
//# sourceMappingURL=pg-workflow-journal-store.js.map
|
|
@@ -1,56 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import { summarizeWorkflowRun, type WorkflowRunStore } from "@sema-agent/core";
|
|
3
|
-
import { type WorkflowCompletionInbox, type WorkflowCompletionInboxEntry } from "../orchestration/workflow-completion-inbox.js";
|
|
4
|
-
import type { WorkflowNotifyJournalStore, WorkflowNotifyJournalEntry } from "../orchestration/workflow-notify-journal.js";
|
|
5
|
-
import { type InboxWarn } from "./tidb-workflow-run-store.js";
|
|
6
|
-
type WorkflowRun = Parameters<WorkflowRunStore["put"]>[1];
|
|
7
|
-
export declare class PgWorkflowRunStore implements WorkflowRunStore {
|
|
8
|
-
private readonly pool;
|
|
9
|
-
constructor(pool: Pool);
|
|
10
|
-
put(id: string, run: WorkflowRun): Promise<void>;
|
|
11
|
-
get(id: string): Promise<WorkflowRun | null>;
|
|
12
|
-
update(id: string, scope: string, run: WorkflowRun, expect?: {
|
|
13
|
-
rev: number;
|
|
14
|
-
}): Promise<boolean>;
|
|
15
|
-
listByScope(scope: string, opts?: {
|
|
16
|
-
status?: WorkflowRun["status"];
|
|
17
|
-
limit?: number;
|
|
18
|
-
session?: string;
|
|
19
|
-
}): Promise<ReturnType<typeof summarizeWorkflowRun>[]>;
|
|
20
|
-
reapAllScopes(now: number, opts: {
|
|
21
|
-
maxAgeMs?: number;
|
|
22
|
-
keep?: number;
|
|
23
|
-
}): Promise<number>;
|
|
24
|
-
reap(scope: string, now: number, opts?: {
|
|
25
|
-
maxAgeMs?: number;
|
|
26
|
-
keep?: number;
|
|
27
|
-
}): Promise<number>;
|
|
28
|
-
}
|
|
29
|
-
export declare class PgWorkflowCompletionInbox implements WorkflowCompletionInbox {
|
|
30
|
-
private readonly pool;
|
|
31
|
-
private readonly onWarn?;
|
|
32
|
-
constructor(pool: Pool, onWarn?: InboxWarn | undefined);
|
|
33
|
-
private sweepFences;
|
|
34
|
-
enqueue(entry: WorkflowCompletionInboxEntry): Promise<void>;
|
|
35
|
-
pending(sessionId: string): Promise<WorkflowCompletionInboxEntry[]>;
|
|
36
|
-
ack(sessionId: string, runId: string): Promise<void>;
|
|
37
|
-
purge(sessionId: string, purgedOwner?: string | null): Promise<void>;
|
|
38
|
-
markTerminalServed(sessionId: string, runId: string): Promise<void>;
|
|
39
|
-
}
|
|
40
|
-
export declare class PgWorkflowNotifyJournalStore implements WorkflowNotifyJournalStore {
|
|
41
|
-
private readonly pool;
|
|
42
|
-
constructor(pool: Pool);
|
|
43
|
-
record(input: {
|
|
44
|
-
runId: string;
|
|
45
|
-
scope: string;
|
|
46
|
-
sourceTaskId?: string;
|
|
47
|
-
principal?: string;
|
|
48
|
-
createdAt: number;
|
|
49
|
-
}): Promise<void>;
|
|
50
|
-
ack(runId: string, ackedAt: number): Promise<void>;
|
|
51
|
-
listPending(): Promise<WorkflowNotifyJournalEntry[]>;
|
|
52
|
-
reapAcked(before: number): Promise<number>;
|
|
53
|
-
get(runId: string): Promise<WorkflowNotifyJournalEntry | null>;
|
|
54
|
-
}
|
|
55
|
-
export {};
|
|
1
|
+
export { PgWorkflowRunStore, PgWorkflowCompletionInbox, PgWorkflowNotifyJournalStore } from "./workflow-run-store-sql.js";
|
|
56
2
|
//# sourceMappingURL=pg-workflow-run-store.d.ts.map
|