@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,23 +1,2 @@
|
|
|
1
|
-
export
|
|
2
|
-
pool;
|
|
3
|
-
constructor(pool) {
|
|
4
|
-
this.pool = pool;
|
|
5
|
-
}
|
|
6
|
-
async put(sessionId, eventId, entryId, owner) {
|
|
7
|
-
await this.pool.query("INSERT INTO resume_anchor (session_id, event_id, entry_id, owner, created_at) VALUES (?,?,?,?,?) " +
|
|
8
|
-
"ON DUPLICATE KEY UPDATE entry_id = VALUES(entry_id), owner = VALUES(owner)", [sessionId, eventId, entryId, owner, new Date()]);
|
|
9
|
-
}
|
|
10
|
-
async resolve(sessionId, eventId, owner) {
|
|
11
|
-
const [rows] = await this.pool.query("SELECT entry_id FROM resume_anchor WHERE session_id = ? AND event_id = ? AND owner <=> ?", [sessionId, eventId, owner]);
|
|
12
|
-
return rows[0] ? String(rows[0].entry_id) : undefined;
|
|
13
|
-
}
|
|
14
|
-
async listBySession(sessionId) {
|
|
15
|
-
const [rows] = await this.pool.query("SELECT event_id, entry_id, owner FROM resume_anchor WHERE session_id = ?", [sessionId]);
|
|
16
|
-
return rows.map((r) => ({ eventId: String(r.event_id), entryId: String(r.entry_id), owner: r.owner == null ? null : String(r.owner) }));
|
|
17
|
-
}
|
|
18
|
-
async deleteBySession(sessionId) {
|
|
19
|
-
const [r] = await this.pool.query("DELETE FROM resume_anchor WHERE session_id = ?", [sessionId]);
|
|
20
|
-
return r.affectedRows;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
1
|
+
export { TiDBResumeAnchorStore } from "./resume-anchor-store-sql.js";
|
|
23
2
|
//# sourceMappingURL=tidb-resume-anchor-store.js.map
|
|
@@ -1,77 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
import { type UsageRow } from "../usage-analytics.js";
|
|
3
|
-
import type { Pool } from "mysql2/promise";
|
|
4
|
-
import type { RunRecord, SessionSummary, RunEvent } from "./store-contracts.js";
|
|
1
|
+
export { TiDBRunStore } from "./run-store-sql.js";
|
|
5
2
|
export type { RunRecord, SessionSummary, RunEvent } from "./store-contracts.js";
|
|
6
|
-
export declare class TiDBRunStore {
|
|
7
|
-
private readonly pool;
|
|
8
|
-
constructor(pool: Pool);
|
|
9
|
-
createRun(taskId: string, sessionId: string, owner: string | null, instanceId: string, meta?: {
|
|
10
|
-
jobId?: string | null;
|
|
11
|
-
source?: string | null;
|
|
12
|
-
objectivePreview?: string | null;
|
|
13
|
-
}): Promise<{
|
|
14
|
-
ok: true;
|
|
15
|
-
} | {
|
|
16
|
-
ok: false;
|
|
17
|
-
activeTaskId: string;
|
|
18
|
-
}>;
|
|
19
|
-
requestCancel(taskId: string, owner: string | null): Promise<boolean>;
|
|
20
|
-
isCancelRequested(taskId: string, owner: string | null): Promise<boolean>;
|
|
21
|
-
requestPreempt(taskId: string, owner: string | null): Promise<boolean>;
|
|
22
|
-
isPreemptRequested(taskId: string, owner: string | null): Promise<boolean>;
|
|
23
|
-
heartbeat(taskId: string, owner: string | null): Promise<void>;
|
|
24
|
-
appendEvent(taskId: string, seq: number, type: string, data: unknown): Promise<void>;
|
|
25
|
-
maxSeq(taskId: string): Promise<number>;
|
|
26
|
-
private tx;
|
|
27
|
-
setTerminal(taskId: string, status: TaskStatus, result: TaskResult | null, error: string | null): Promise<void>;
|
|
28
|
-
setSuspended(taskId: string): Promise<void>;
|
|
29
|
-
setNeedsReview(taskId: string): Promise<void>;
|
|
30
|
-
markResuming(taskId: string): Promise<boolean>;
|
|
31
|
-
getActiveTaskId(sessionId: string): Promise<string | undefined>;
|
|
32
|
-
private rowToRun;
|
|
33
|
-
getRun(taskId: string): Promise<RunRecord | undefined>;
|
|
34
|
-
listRuns(opts: {
|
|
35
|
-
status?: string;
|
|
36
|
-
jobId?: string;
|
|
37
|
-
source?: string;
|
|
38
|
-
owner?: string;
|
|
39
|
-
cursor?: {
|
|
40
|
-
createdAt: string;
|
|
41
|
-
taskId: string;
|
|
42
|
-
};
|
|
43
|
-
limit: number;
|
|
44
|
-
}): Promise<RunRecord[]>;
|
|
45
|
-
listSessions(opts: {
|
|
46
|
-
owner?: string;
|
|
47
|
-
cursor?: {
|
|
48
|
-
lastActivityAt: string;
|
|
49
|
-
sessionId: string;
|
|
50
|
-
};
|
|
51
|
-
limit: number;
|
|
52
|
-
q?: string;
|
|
53
|
-
}): Promise<SessionSummary[]>;
|
|
54
|
-
deleteBySession(sessionId: string, owner: string | null): Promise<{
|
|
55
|
-
removed: number;
|
|
56
|
-
} | {
|
|
57
|
-
active: string;
|
|
58
|
-
}>;
|
|
59
|
-
sourceSummary(sinceMs: number): Promise<Array<{
|
|
60
|
-
source: string | null;
|
|
61
|
-
status: string;
|
|
62
|
-
count: number;
|
|
63
|
-
}>>;
|
|
64
|
-
usageScan(fromMs: number, toMs: number, opts?: {
|
|
65
|
-
owner?: string;
|
|
66
|
-
limit?: number;
|
|
67
|
-
}): Promise<{
|
|
68
|
-
rows: UsageRow[];
|
|
69
|
-
truncated: boolean;
|
|
70
|
-
}>;
|
|
71
|
-
retainedFrom(taskId: string): Promise<number>;
|
|
72
|
-
getEvents(taskId: string, afterSeq: number): Promise<RunEvent[]>;
|
|
73
|
-
reapStale(olderThanMs: number): Promise<number>;
|
|
74
|
-
reapSuspended(olderThanMs: number): Promise<number>;
|
|
75
|
-
failSuspendedWithExpiredCheckpoint(): Promise<number>;
|
|
76
|
-
}
|
|
77
3
|
//# sourceMappingURL=tidb-run-store.d.ts.map
|
|
@@ -1,307 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import { escapeLike } from "./sql-escape.js";
|
|
3
|
-
import { parseJsonLenient as parseJson, toIso as iso } from "./sql-row-helpers.js";
|
|
4
|
-
function isDupKey(err) {
|
|
5
|
-
return Boolean(err) && err.code === "ER_DUP_ENTRY";
|
|
6
|
-
}
|
|
7
|
-
export class TiDBRunStore {
|
|
8
|
-
pool;
|
|
9
|
-
constructor(pool) {
|
|
10
|
-
this.pool = pool;
|
|
11
|
-
}
|
|
12
|
-
async createRun(taskId, sessionId, owner, instanceId, meta = {}) {
|
|
13
|
-
const conn = await this.pool.getConnection();
|
|
14
|
-
try {
|
|
15
|
-
await conn.beginTransaction();
|
|
16
|
-
const now = new Date();
|
|
17
|
-
try {
|
|
18
|
-
await conn.query("INSERT INTO task_active (session_id, task_id, since) VALUES (?,?,?)", [
|
|
19
|
-
sessionId,
|
|
20
|
-
taskId,
|
|
21
|
-
now,
|
|
22
|
-
]);
|
|
23
|
-
}
|
|
24
|
-
catch (err) {
|
|
25
|
-
if (isDupKey(err)) {
|
|
26
|
-
await conn.rollback();
|
|
27
|
-
const [active] = await conn.query("SELECT task_id FROM task_active WHERE session_id = ?", [sessionId]);
|
|
28
|
-
return { ok: false, activeTaskId: String(active[0]?.task_id ?? "") };
|
|
29
|
-
}
|
|
30
|
-
throw err;
|
|
31
|
-
}
|
|
32
|
-
await conn.query("INSERT INTO task_run (task_id, session_id, owner, status, instance_id, job_id, source, objective_preview, created_at, updated_at) " +
|
|
33
|
-
"VALUES (?,?,?,'running',?,?,?,?,?,?)", [taskId, sessionId, owner, instanceId, meta.jobId ?? null, meta.source ?? null, meta.objectivePreview ?? null, now, now]);
|
|
34
|
-
await conn.commit();
|
|
35
|
-
return { ok: true };
|
|
36
|
-
}
|
|
37
|
-
catch (err) {
|
|
38
|
-
try {
|
|
39
|
-
await conn.rollback();
|
|
40
|
-
}
|
|
41
|
-
catch {
|
|
42
|
-
}
|
|
43
|
-
throw err;
|
|
44
|
-
}
|
|
45
|
-
finally {
|
|
46
|
-
conn.release();
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
async requestCancel(taskId, owner) {
|
|
50
|
-
const [r] = await this.pool.query("UPDATE task_run SET cancel_requested = 1 WHERE task_id = ? AND owner <=> ? AND status = 'running'", [taskId, owner]);
|
|
51
|
-
return r.affectedRows > 0;
|
|
52
|
-
}
|
|
53
|
-
async isCancelRequested(taskId, owner) {
|
|
54
|
-
const [rows] = await this.pool.query("SELECT cancel_requested FROM task_run WHERE task_id = ? AND owner <=> ?", [taskId, owner]);
|
|
55
|
-
return Boolean(rows[0]?.cancel_requested);
|
|
56
|
-
}
|
|
57
|
-
async requestPreempt(taskId, owner) {
|
|
58
|
-
const [r] = await this.pool.query("UPDATE task_run SET preempt_requested = 1 WHERE task_id = ? AND owner <=> ? AND status = 'running'", [taskId, owner]);
|
|
59
|
-
return r.affectedRows > 0;
|
|
60
|
-
}
|
|
61
|
-
async isPreemptRequested(taskId, owner) {
|
|
62
|
-
const [rows] = await this.pool.query("SELECT preempt_requested FROM task_run WHERE task_id = ? AND owner <=> ?", [taskId, owner]);
|
|
63
|
-
return Boolean(rows[0]?.preempt_requested);
|
|
64
|
-
}
|
|
65
|
-
async heartbeat(taskId, owner) {
|
|
66
|
-
await this.pool.query("UPDATE task_run SET updated_at = ? WHERE task_id = ? AND owner <=> ? AND status = 'running'", [
|
|
67
|
-
new Date(),
|
|
68
|
-
taskId,
|
|
69
|
-
owner,
|
|
70
|
-
]);
|
|
71
|
-
}
|
|
72
|
-
async appendEvent(taskId, seq, type, data) {
|
|
73
|
-
await this.pool.query("INSERT INTO task_event (task_id, seq, type, data, ts) VALUES (?,?,?,?,?)", [
|
|
74
|
-
taskId,
|
|
75
|
-
seq,
|
|
76
|
-
type,
|
|
77
|
-
data == null ? null : JSON.stringify(data),
|
|
78
|
-
new Date(),
|
|
79
|
-
]);
|
|
80
|
-
}
|
|
81
|
-
async maxSeq(taskId) {
|
|
82
|
-
const [rows] = await this.pool.query("SELECT MAX(seq) AS m FROM task_event WHERE task_id = ?", [taskId]);
|
|
83
|
-
const m = rows[0]?.m;
|
|
84
|
-
return m == null ? 0 : Number(m);
|
|
85
|
-
}
|
|
86
|
-
async tx(fn) {
|
|
87
|
-
const conn = await this.pool.getConnection();
|
|
88
|
-
try {
|
|
89
|
-
await conn.beginTransaction();
|
|
90
|
-
await fn(conn);
|
|
91
|
-
await conn.commit();
|
|
92
|
-
}
|
|
93
|
-
catch (err) {
|
|
94
|
-
try {
|
|
95
|
-
await conn.rollback();
|
|
96
|
-
}
|
|
97
|
-
catch {
|
|
98
|
-
}
|
|
99
|
-
throw err;
|
|
100
|
-
}
|
|
101
|
-
finally {
|
|
102
|
-
conn.release();
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
async setTerminal(taskId, status, result, error) {
|
|
106
|
-
const errorCode = result?.errorCode ?? null;
|
|
107
|
-
await this.tx(async (conn) => {
|
|
108
|
-
await conn.query("UPDATE task_run SET status = ?, result = ?, error = ?, error_code = ?, updated_at = ? WHERE task_id = ? AND status IN ('running','suspended','needs_review')", [status, result == null ? null : JSON.stringify(result), error, errorCode, new Date(), taskId]);
|
|
109
|
-
await conn.query("DELETE FROM task_active WHERE task_id = ?", [taskId]);
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
async setSuspended(taskId) {
|
|
113
|
-
await this.pool.query("UPDATE task_run SET status = 'suspended', updated_at = ? WHERE task_id = ? AND status IN ('running','suspended')", [new Date(), taskId]);
|
|
114
|
-
}
|
|
115
|
-
async setNeedsReview(taskId) {
|
|
116
|
-
await this.pool.query("UPDATE task_run SET status = 'needs_review', updated_at = ? WHERE task_id = ? AND status IN ('running','needs_review')", [new Date(), taskId]);
|
|
117
|
-
}
|
|
118
|
-
async markResuming(taskId) {
|
|
119
|
-
const [res] = await this.pool.query("UPDATE task_run SET status = 'running', cancel_requested = 0, preempt_requested = 0, updated_at = ? WHERE task_id = ? AND status IN ('suspended','needs_review')", [new Date(), taskId]);
|
|
120
|
-
return res.affectedRows === 1;
|
|
121
|
-
}
|
|
122
|
-
async getActiveTaskId(sessionId) {
|
|
123
|
-
const [rows] = await this.pool.query("SELECT task_id FROM task_active WHERE session_id = ?", [sessionId]);
|
|
124
|
-
return rows[0] ? String(rows[0].task_id) : undefined;
|
|
125
|
-
}
|
|
126
|
-
rowToRun(r) {
|
|
127
|
-
return {
|
|
128
|
-
taskId: String(r.task_id),
|
|
129
|
-
sessionId: String(r.session_id),
|
|
130
|
-
owner: r.owner ?? null,
|
|
131
|
-
status: r.status,
|
|
132
|
-
result: parseJson(r.result),
|
|
133
|
-
error: r.error ?? null,
|
|
134
|
-
errorCode: r.error_code ?? null,
|
|
135
|
-
jobId: r.job_id ?? null,
|
|
136
|
-
source: r.source ?? null,
|
|
137
|
-
instanceId: r.instance_id ?? null,
|
|
138
|
-
objectivePreview: r.objective_preview ?? null,
|
|
139
|
-
createdAt: iso(r.created_at),
|
|
140
|
-
updatedAt: iso(r.updated_at),
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
async getRun(taskId) {
|
|
144
|
-
const [rows] = 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 = ?", [taskId]);
|
|
145
|
-
return rows[0] ? this.rowToRun(rows[0]) : undefined;
|
|
146
|
-
}
|
|
147
|
-
async listRuns(opts) {
|
|
148
|
-
if (opts.cursor && Number.isNaN(Date.parse(opts.cursor.createdAt)))
|
|
149
|
-
return [];
|
|
150
|
-
const where = [];
|
|
151
|
-
const params = [];
|
|
152
|
-
if (opts.status) {
|
|
153
|
-
where.push("status = ?");
|
|
154
|
-
params.push(opts.status);
|
|
155
|
-
}
|
|
156
|
-
if (opts.jobId) {
|
|
157
|
-
where.push("job_id = ?");
|
|
158
|
-
params.push(opts.jobId);
|
|
159
|
-
}
|
|
160
|
-
if (opts.source) {
|
|
161
|
-
where.push("source = ?");
|
|
162
|
-
params.push(opts.source);
|
|
163
|
-
}
|
|
164
|
-
if (opts.owner) {
|
|
165
|
-
where.push("owner = ?");
|
|
166
|
-
params.push(opts.owner);
|
|
167
|
-
}
|
|
168
|
-
if (opts.cursor) {
|
|
169
|
-
where.push("(created_at < ? OR (created_at = ? AND task_id < ?))");
|
|
170
|
-
params.push(new Date(opts.cursor.createdAt), new Date(opts.cursor.createdAt), opts.cursor.taskId);
|
|
171
|
-
}
|
|
172
|
-
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" +
|
|
173
|
-
(where.length ? " WHERE " + where.join(" AND ") : "") +
|
|
174
|
-
" ORDER BY created_at DESC, task_id DESC LIMIT ?";
|
|
175
|
-
params.push(opts.limit);
|
|
176
|
-
const [rows] = await this.pool.query(sql, params);
|
|
177
|
-
return rows.map((r) => this.rowToRun(r));
|
|
178
|
-
}
|
|
179
|
-
async listSessions(opts) {
|
|
180
|
-
const params = [];
|
|
181
|
-
let innerWhere = "";
|
|
182
|
-
if (opts.owner) {
|
|
183
|
-
innerWhere = " WHERE owner = ?";
|
|
184
|
-
params.push(opts.owner);
|
|
185
|
-
}
|
|
186
|
-
const outer = ["rn = 1"];
|
|
187
|
-
if (opts.q) {
|
|
188
|
-
outer.push("EXISTS (SELECT 1 FROM task_run tr WHERE tr.session_id = t.session_id AND LOWER(tr.objective_preview) LIKE LOWER(?) ESCAPE '\\\\')");
|
|
189
|
-
params.push(`%${escapeLike(opts.q)}%`);
|
|
190
|
-
}
|
|
191
|
-
if (opts.cursor) {
|
|
192
|
-
outer.push("(last_activity < ? OR (last_activity = ? AND session_id < ?))");
|
|
193
|
-
params.push(new Date(opts.cursor.lastActivityAt), new Date(opts.cursor.lastActivityAt), opts.cursor.sessionId);
|
|
194
|
-
}
|
|
195
|
-
const sql = "SELECT session_id, owner, task_id, last_activity, first_activity, run_count, objective_preview, status FROM (" +
|
|
196
|
-
"SELECT session_id, owner, task_id, objective_preview, status," +
|
|
197
|
-
" ROW_NUMBER() OVER (PARTITION BY session_id ORDER BY created_at DESC, task_id DESC) AS rn," +
|
|
198
|
-
" MAX(created_at) OVER (PARTITION BY session_id) AS last_activity," +
|
|
199
|
-
" MIN(created_at) OVER (PARTITION BY session_id) AS first_activity," +
|
|
200
|
-
" COUNT(*) OVER (PARTITION BY session_id) AS run_count" +
|
|
201
|
-
" FROM task_run" + innerWhere + ") t WHERE " + outer.join(" AND ") +
|
|
202
|
-
" ORDER BY last_activity DESC, session_id DESC LIMIT ?";
|
|
203
|
-
params.push(opts.limit);
|
|
204
|
-
const [rows] = await this.pool.query(sql, params);
|
|
205
|
-
return rows.map((r) => ({
|
|
206
|
-
sessionId: String(r.session_id),
|
|
207
|
-
owner: r.owner ?? null,
|
|
208
|
-
lastActivityAt: iso(r.last_activity),
|
|
209
|
-
firstActivityAt: iso(r.first_activity),
|
|
210
|
-
runCount: Number(r.run_count),
|
|
211
|
-
objectivePreview: r.objective_preview ?? null,
|
|
212
|
-
lastStatus: String(r.status),
|
|
213
|
-
lastRunId: r.task_id ?? null,
|
|
214
|
-
title: null,
|
|
215
|
-
}));
|
|
216
|
-
}
|
|
217
|
-
async deleteBySession(sessionId, owner) {
|
|
218
|
-
let result = { removed: 0 };
|
|
219
|
-
await this.tx(async (conn) => {
|
|
220
|
-
const [active] = await conn.query("SELECT task_id FROM task_active WHERE session_id = ? FOR UPDATE", [sessionId]);
|
|
221
|
-
if (active[0]) {
|
|
222
|
-
result = { active: String(active[0].task_id) };
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
225
|
-
await conn.query("DELETE te FROM task_event te JOIN task_run tr ON te.task_id = tr.task_id WHERE tr.session_id = ? AND tr.owner <=> ?", [sessionId, owner]);
|
|
226
|
-
await conn.query("DELETE ta FROM task_active ta JOIN task_run tr ON ta.task_id = tr.task_id WHERE tr.session_id = ? AND tr.owner <=> ?", [sessionId, owner]);
|
|
227
|
-
const [res] = await conn.query("DELETE FROM task_run WHERE session_id = ? AND owner <=> ?", [sessionId, owner]);
|
|
228
|
-
result = { removed: res.affectedRows };
|
|
229
|
-
});
|
|
230
|
-
return result;
|
|
231
|
-
}
|
|
232
|
-
async sourceSummary(sinceMs) {
|
|
233
|
-
const [rows] = await this.pool.query("SELECT source, status, COUNT(*) AS c FROM task_run WHERE created_at >= ? GROUP BY source, status", [new Date(sinceMs)]);
|
|
234
|
-
return rows.map((r) => ({ source: r.source ?? null, status: String(r.status), count: Number(r.c) }));
|
|
235
|
-
}
|
|
236
|
-
async usageScan(fromMs, toMs, opts) {
|
|
237
|
-
const limit = Math.min(opts?.limit ?? USAGE_SCAN_LIMIT, USAGE_SCAN_LIMIT);
|
|
238
|
-
const where = ["created_at >= ?", "created_at < ?"];
|
|
239
|
-
const params = [new Date(fromMs), new Date(toMs)];
|
|
240
|
-
if (opts?.owner !== undefined) {
|
|
241
|
-
where.push("owner = ?");
|
|
242
|
-
params.push(opts.owner);
|
|
243
|
-
}
|
|
244
|
-
const [rows] = 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);
|
|
245
|
-
const truncated = rows.length > limit;
|
|
246
|
-
const page = truncated ? rows.slice(0, limit) : rows;
|
|
247
|
-
return {
|
|
248
|
-
truncated,
|
|
249
|
-
rows: page.map((r) => ({
|
|
250
|
-
owner: r.owner ?? null,
|
|
251
|
-
createdAtMs: new Date(r.created_at).getTime(),
|
|
252
|
-
status: String(r.status),
|
|
253
|
-
...(r.result != null ? { stats: projectUsageStats(r.result) } : {}),
|
|
254
|
-
})),
|
|
255
|
-
};
|
|
256
|
-
}
|
|
257
|
-
async retainedFrom(taskId) {
|
|
258
|
-
const [rows] = await this.pool.query("SELECT MIN(seq) AS m FROM task_event WHERE task_id = ?", [taskId]);
|
|
259
|
-
const m = rows[0]?.m;
|
|
260
|
-
return m == null ? 0 : Number(m);
|
|
261
|
-
}
|
|
262
|
-
async getEvents(taskId, afterSeq) {
|
|
263
|
-
const [rows] = await this.pool.query("SELECT seq, type, data, ts FROM task_event WHERE task_id = ? AND seq > ? ORDER BY seq ASC", [taskId, afterSeq]);
|
|
264
|
-
return rows.map((r) => ({
|
|
265
|
-
seq: Number(r.seq),
|
|
266
|
-
type: String(r.type),
|
|
267
|
-
data: parseJson(r.data),
|
|
268
|
-
ts: iso(r.ts),
|
|
269
|
-
}));
|
|
270
|
-
}
|
|
271
|
-
async reapStale(olderThanMs) {
|
|
272
|
-
const cutoff = new Date(Date.now() - olderThanMs);
|
|
273
|
-
let reaped = 0;
|
|
274
|
-
await this.tx(async (conn) => {
|
|
275
|
-
const [res] = await conn.query("UPDATE task_run SET status = 'failed', error = 'run stalled (instance lost?)', updated_at = ? " +
|
|
276
|
-
"WHERE status = 'running' AND updated_at < ?", [new Date(), cutoff]);
|
|
277
|
-
reaped = res.affectedRows;
|
|
278
|
-
await conn.query("DELETE ta FROM task_active ta JOIN task_run tr ON ta.task_id = tr.task_id WHERE tr.status NOT IN ('running','suspended','needs_review')");
|
|
279
|
-
});
|
|
280
|
-
return reaped;
|
|
281
|
-
}
|
|
282
|
-
async reapSuspended(olderThanMs) {
|
|
283
|
-
const cutoff = new Date(Date.now() - olderThanMs);
|
|
284
|
-
let reaped = 0;
|
|
285
|
-
await this.tx(async (conn) => {
|
|
286
|
-
const [res] = await conn.query("UPDATE task_run tr SET tr.status = 'failed', tr.error = 'approval expired before decision', tr.error_code = 'approval.expired', tr.updated_at = ? " +
|
|
287
|
-
"WHERE tr.status = 'suspended' AND tr.updated_at < ? " +
|
|
288
|
-
"AND NOT EXISTS (SELECT 1 FROM checkpoint c WHERE c.session_id = tr.session_id AND c.status = 'pending')", [new Date(), cutoff]);
|
|
289
|
-
reaped = res.affectedRows;
|
|
290
|
-
await conn.query("DELETE ta FROM task_active ta JOIN task_run tr ON ta.task_id = tr.task_id WHERE tr.status NOT IN ('running','suspended','needs_review')");
|
|
291
|
-
});
|
|
292
|
-
return reaped;
|
|
293
|
-
}
|
|
294
|
-
async failSuspendedWithExpiredCheckpoint() {
|
|
295
|
-
let reaped = 0;
|
|
296
|
-
await this.tx(async (conn) => {
|
|
297
|
-
const [res] = await conn.query("UPDATE task_run tr SET tr.status = 'failed', tr.error = 'approval expired before decision', tr.error_code = 'approval.expired', tr.updated_at = ? " +
|
|
298
|
-
"WHERE tr.status IN ('suspended','needs_review') " +
|
|
299
|
-
"AND EXISTS (SELECT 1 FROM checkpoint ce WHERE ce.session_id = tr.session_id AND ce.status = 'expired') " +
|
|
300
|
-
"AND NOT EXISTS (SELECT 1 FROM checkpoint cp WHERE cp.session_id = tr.session_id AND cp.status = 'pending')", [new Date()]);
|
|
301
|
-
reaped = res.affectedRows;
|
|
302
|
-
await conn.query("DELETE ta FROM task_active ta JOIN task_run tr ON ta.task_id = tr.task_id WHERE tr.status NOT IN ('running','suspended','needs_review')");
|
|
303
|
-
});
|
|
304
|
-
return reaped;
|
|
305
|
-
}
|
|
306
|
-
}
|
|
1
|
+
export { TiDBRunStore } from "./run-store-sql.js";
|
|
307
2
|
//# sourceMappingURL=tidb-run-store.js.map
|
|
@@ -1,12 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import type { Pool } from "mysql2/promise";
|
|
3
|
-
export declare class TiDBSessionPolicyStore 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 { TiDBSessionPolicyStore } from "./session-policy-store-sql.js";
|
|
12
2
|
//# sourceMappingURL=tidb-session-policy-store.d.ts.map
|
|
@@ -1,87 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import { loosenReasons, SessionPolicyError, normalizeRules, stripRev } from "@sema-agent/core";
|
|
3
|
-
const policyKey = (sessionId, principal) => createHash("sha256").update(JSON.stringify([sessionId, principal ?? null])).digest("hex");
|
|
4
|
-
const parseRules = (v) => (typeof v === "string" ? JSON.parse(v) : v);
|
|
5
|
-
const isDupKey = (e) => e?.code === "ER_DUP_ENTRY" || e?.errno === 1062;
|
|
6
|
-
export class TiDBSessionPolicyStore {
|
|
7
|
-
pool;
|
|
8
|
-
constructor(pool) {
|
|
9
|
-
this.pool = pool;
|
|
10
|
-
}
|
|
11
|
-
async getRules(sessionId, principal) {
|
|
12
|
-
const [rows] = await this.pool.query("SELECT rules, rev FROM session_policy WHERE policy_key = ?", [policyKey(sessionId, principal)]);
|
|
13
|
-
if (!rows[0])
|
|
14
|
-
return null;
|
|
15
|
-
return { ...parseRules(rows[0].rules), rev: Number(rows[0].rev) };
|
|
16
|
-
}
|
|
17
|
-
async listBySession(sessionId) {
|
|
18
|
-
const [rows] = await this.pool.query("SELECT principal, rules, rev FROM session_policy WHERE session_id = ?", [sessionId]);
|
|
19
|
-
return rows.map((r) => ({
|
|
20
|
-
principal: r.principal == null ? undefined : String(r.principal),
|
|
21
|
-
rules: { ...parseRules(r.rules), rev: Number(r.rev) },
|
|
22
|
-
}));
|
|
23
|
-
}
|
|
24
|
-
async putRules(sessionId, principal, rules, opts) {
|
|
25
|
-
const key = policyKey(sessionId, principal);
|
|
26
|
-
for (let attempt = 0;; attempt++) {
|
|
27
|
-
try {
|
|
28
|
-
return await this.tx(async (conn) => {
|
|
29
|
-
const [rows] = await conn.query("SELECT rules, rev FROM session_policy WHERE policy_key = ? FOR UPDATE", [key]);
|
|
30
|
-
const prior = rows[0] ? { rules: parseRules(rows[0].rules), rev: Number(rows[0].rev) } : undefined;
|
|
31
|
-
const priorRev = prior?.rev ?? 0;
|
|
32
|
-
if (opts?.expectedRev !== undefined && priorRev !== opts.expectedRev) {
|
|
33
|
-
throw new SessionPolicyError("conflict", `session rules rev mismatch (expected ${opts.expectedRev}, have ${priorRev})`);
|
|
34
|
-
}
|
|
35
|
-
const clean = normalizeRules(stripRev(rules));
|
|
36
|
-
if (prior && opts?.operator !== true) {
|
|
37
|
-
const loosens = loosenReasons(prior.rules, clean);
|
|
38
|
-
if (loosens.length > 0) {
|
|
39
|
-
throw new SessionPolicyError("loosen_forbidden", `a non-operator session-rule write may only tighten; refused: ${loosens.join("; ")}`);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
const nextRev = priorRev + 1;
|
|
43
|
-
const json = JSON.stringify(clean);
|
|
44
|
-
const now = new Date();
|
|
45
|
-
if (prior) {
|
|
46
|
-
const [r] = await conn.query("UPDATE session_policy SET principal = ?, rules = ?, rev = ?, updated_at = ? WHERE policy_key = ? AND rev = ?", [principal ?? null, json, nextRev, now, key, priorRev]);
|
|
47
|
-
if (r.affectedRows !== 1)
|
|
48
|
-
throw new SessionPolicyError("conflict", `session rules rev mismatch (expected ${opts?.expectedRev ?? priorRev}, have ${priorRev})`);
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
await conn.query("INSERT INTO session_policy (policy_key, session_id, principal, rules, rev, created_at, updated_at) VALUES (?,?,?,?,?,?,?)", [key, sessionId, principal ?? null, json, nextRev, now, now]);
|
|
52
|
-
}
|
|
53
|
-
return structuredClone({ ...clean, rev: nextRev });
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
catch (e) {
|
|
57
|
-
if (isDupKey(e) && attempt < 4)
|
|
58
|
-
continue;
|
|
59
|
-
throw e;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
async deleteBySession(sessionId) {
|
|
64
|
-
await this.pool.query("DELETE FROM session_policy WHERE session_id = ?", [sessionId]);
|
|
65
|
-
}
|
|
66
|
-
async tx(fn) {
|
|
67
|
-
const conn = await this.pool.getConnection();
|
|
68
|
-
try {
|
|
69
|
-
await conn.beginTransaction();
|
|
70
|
-
const out = await fn(conn);
|
|
71
|
-
await conn.commit();
|
|
72
|
-
return out;
|
|
73
|
-
}
|
|
74
|
-
catch (err) {
|
|
75
|
-
try {
|
|
76
|
-
await conn.rollback();
|
|
77
|
-
}
|
|
78
|
-
catch {
|
|
79
|
-
}
|
|
80
|
-
throw err;
|
|
81
|
-
}
|
|
82
|
-
finally {
|
|
83
|
-
conn.release();
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
1
|
+
export { TiDBSessionPolicyStore } from "./session-policy-store-sql.js";
|
|
87
2
|
//# sourceMappingURL=tidb-session-policy-store.js.map
|
|
@@ -1,15 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
import type { Pool } from "mysql2/promise";
|
|
1
|
+
export { TiDBToolResultStore, SqlToolResultStore } from "./tool-result-store-sql.js";
|
|
3
2
|
export { escapeLike } from "./sql-escape.js";
|
|
4
|
-
export declare class TiDBToolResultStore implements ToolResultStore {
|
|
5
|
-
private readonly pool;
|
|
6
|
-
constructor(pool: Pool);
|
|
7
|
-
put(ref: string, content: string): Promise<void>;
|
|
8
|
-
get(ref: string, opts?: {
|
|
9
|
-
offset?: number;
|
|
10
|
-
limit?: number;
|
|
11
|
-
}): Promise<ToolResultSlice | undefined>;
|
|
12
|
-
reapOlderThan(cutoffMs: number): Promise<number>;
|
|
13
|
-
deleteBySession(sessionId: string): Promise<number>;
|
|
14
|
-
}
|
|
15
3
|
//# sourceMappingURL=tidb-tool-result-store.d.ts.map
|
|
@@ -1,40 +1,3 @@
|
|
|
1
|
-
|
|
1
|
+
export { TiDBToolResultStore, SqlToolResultStore } from "./tool-result-store-sql.js";
|
|
2
2
|
export { escapeLike } from "./sql-escape.js";
|
|
3
|
-
export class TiDBToolResultStore {
|
|
4
|
-
pool;
|
|
5
|
-
constructor(pool) {
|
|
6
|
-
this.pool = pool;
|
|
7
|
-
}
|
|
8
|
-
async put(ref, content) {
|
|
9
|
-
const safe = Buffer.from(content, "utf8").toString("utf8");
|
|
10
|
-
await this.pool.query("INSERT IGNORE INTO tool_result (ref, content, created_at) VALUES (?,?,?)", [ref, safe, new Date()]);
|
|
11
|
-
}
|
|
12
|
-
async get(ref, opts = {}) {
|
|
13
|
-
const offset = Math.max(0, Math.floor(opts.offset ?? 0));
|
|
14
|
-
const hasLimit = opts.limit !== undefined && Number.isFinite(opts.limit);
|
|
15
|
-
const limit = hasLimit ? Math.max(0, Math.floor(opts.limit)) : 0;
|
|
16
|
-
const sql = hasLimit
|
|
17
|
-
? "SELECT SUBSTRING(content, ?, ?) AS slice, CHAR_LENGTH(content) AS total FROM tool_result WHERE ref = ?"
|
|
18
|
-
: "SELECT SUBSTRING(content, ?) AS slice, CHAR_LENGTH(content) AS total FROM tool_result WHERE ref = ?";
|
|
19
|
-
const params = hasLimit ? [offset + 1, limit, ref] : [offset + 1, ref];
|
|
20
|
-
const [rows] = await this.pool.query(sql, params);
|
|
21
|
-
if (rows.length === 0)
|
|
22
|
-
return undefined;
|
|
23
|
-
return { content: String(rows[0].slice ?? ""), offset, totalChars: Number(rows[0].total) };
|
|
24
|
-
}
|
|
25
|
-
async reapOlderThan(cutoffMs) {
|
|
26
|
-
try {
|
|
27
|
-
const [res] = await this.pool.query("DELETE FROM tool_result WHERE created_at < ?", [new Date(cutoffMs)]);
|
|
28
|
-
return res.affectedRows;
|
|
29
|
-
}
|
|
30
|
-
catch {
|
|
31
|
-
return 0;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
async deleteBySession(sessionId) {
|
|
35
|
-
const prefix = `${escapeLike(`tr_${sessionId}_`)}%`;
|
|
36
|
-
const [res] = await this.pool.query("DELETE FROM tool_result WHERE ref LIKE ? ESCAPE '\\\\'", [prefix]);
|
|
37
|
-
return res.affectedRows;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
3
|
//# sourceMappingURL=tidb-tool-result-store.js.map
|
|
@@ -1,21 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import { type WorkflowJournalEntry, type WorkflowJournalStore } from "@sema-agent/core";
|
|
3
|
-
export declare class TiDBWorkflowJournalStore 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 { TiDBWorkflowJournalStore } from "./workflow-journal-store-sql.js";
|
|
21
2
|
//# sourceMappingURL=tidb-workflow-journal-store.d.ts.map
|
|
@@ -1,35 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import { oversizeJournalResult } from "./workflow-journal-limits.js";
|
|
3
|
-
export class TiDBWorkflowJournalStore {
|
|
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 (?,?,?,?,?,?) " +
|
|
13
|
-
"ON DUPLICATE KEY UPDATE call_key = VALUES(call_key), result = VALUES(result)", [runId, callKeyOrdinal(entry.callKey), scope, entry.callKey, serialized, Date.now()]);
|
|
14
|
-
}
|
|
15
|
-
async load(runId, scope) {
|
|
16
|
-
const [rows] = await this.pool.query("SELECT call_key, result FROM workflow_journal WHERE run_id = ? AND scope = ? ORDER BY ordinal ASC", [runId, scope]);
|
|
17
|
-
return rows.map((r) => ({ callKey: String(r.call_key), result: JSON.parse(String(r.result)) }));
|
|
18
|
-
}
|
|
19
|
-
locator(runId, _scope) {
|
|
20
|
-
return `/v1/workflows/${runId}/journal`;
|
|
21
|
-
}
|
|
22
|
-
async loadPage(runId, scope, opts) {
|
|
23
|
-
const [rows] = await this.pool.query("SELECT call_key, CASE WHEN LENGTH(result) > ? THEN NULL ELSE result END AS result_json, LENGTH(result) AS result_bytes FROM workflow_journal WHERE run_id = ? AND scope = ? ORDER BY ordinal ASC LIMIT ? OFFSET ?", [opts.maxResultBytes, runId, scope, opts.limit, opts.offset]);
|
|
24
|
-
return rows.map((r) => ({ callKey: String(r.call_key), resultJson: r.result_json === null ? null : String(r.result_json), resultBytes: Number(r.result_bytes) }));
|
|
25
|
-
}
|
|
26
|
-
async deleteByRun(runId) {
|
|
27
|
-
const [r] = await this.pool.query("DELETE FROM workflow_journal WHERE run_id = ?", [runId]);
|
|
28
|
-
return r.affectedRows;
|
|
29
|
-
}
|
|
30
|
-
async reapExpired(now, maxAgeMs) {
|
|
31
|
-
const [r] = await this.pool.query("DELETE FROM workflow_journal WHERE created_at < ?", [now - maxAgeMs]);
|
|
32
|
-
return r.affectedRows;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
1
|
+
export { TiDBWorkflowJournalStore } from "./workflow-journal-store-sql.js";
|
|
35
2
|
//# sourceMappingURL=tidb-workflow-journal-store.js.map
|