@sema-agent/server 1.314.0 → 1.316.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/dist/approval-hmac.d.ts +17 -0
- package/dist/approval-hmac.js +27 -0
- package/dist/config-center/apply-effective.d.ts +22 -0
- package/dist/config-center/apply-effective.js +283 -0
- package/dist/config-center/http-client.d.ts +23 -0
- package/dist/config-center/http-client.js +109 -0
- package/dist/config-center/restart-signal.d.ts +12 -0
- package/dist/config-center/restart-signal.js +70 -0
- package/dist/config-center/skills-mcp.d.ts +13 -0
- package/dist/config-center/skills-mcp.js +113 -0
- package/dist/config-center/types.d.ts +143 -0
- package/dist/config-center/types.js +2 -0
- package/dist/fleet/fleet-bus.js +92 -83
- package/dist/hooks/hook-runner.js +18 -9
- 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 +67 -0
- package/dist/http/route-ctx.js +2 -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/images.d.ts +20 -0
- package/dist/http/routes/images.js +572 -0
- package/dist/http/routes/memory-policy.d.ts +4 -0
- package/dist/http/routes/memory-policy.js +105 -0
- package/dist/http/routes/observability.d.ts +4 -0
- package/dist/http/routes/observability.js +63 -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/send.d.ts +6 -0
- package/dist/http/send.js +19 -0
- package/dist/http/server.d.ts +101 -76
- package/dist/http/server.js +129 -2410
- package/dist/http/sse-log.d.ts +25 -0
- package/dist/http/sse-log.js +59 -0
- package/dist/http/workspace-content.d.ts +3 -0
- package/dist/http/workspace-content.js +20 -0
- package/dist/index.d.ts +1 -1
- package/dist/leader/leader.js +5 -2
- package/dist/leader/wire.js +169 -165
- package/dist/main.js +462 -451
- 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/checkpoint-store-sql.d.ts +67 -0
- package/dist/plugins/checkpoint-store-sql.js +224 -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-bake-store-sql.d.ts +53 -0
- package/dist/plugins/image-bake-store-sql.js +463 -0
- package/dist/plugins/image-index-sql.d.ts +33 -0
- package/dist/plugins/image-index-sql.js +328 -0
- package/dist/plugins/k8s-bg-scripts.d.ts +19 -0
- package/dist/plugins/k8s-bg-scripts.js +129 -0
- package/dist/plugins/k8s-exec-protocol.d.ts +20 -0
- package/dist/plugins/k8s-exec-protocol.js +87 -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-checkpoint-store.d.ts +1 -33
- package/dist/plugins/pg-checkpoint-store.js +1 -189
- package/dist/plugins/pg-cost-quota.js +3 -143
- 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-bake.d.ts +1 -40
- package/dist/plugins/pg-image-bake.js +1 -420
- 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-rate-limiter.d.ts +2 -32
- package/dist/plugins/pg-rate-limiter.js +4 -147
- 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-k8s.d.ts +5 -38
- package/dist/plugins/remote-env-k8s.js +7 -213
- 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/sql-driver.d.ts +25 -0
- package/dist/plugins/sql-driver.js +59 -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-checkpoint-store.d.ts +1 -49
- package/dist/plugins/tidb-checkpoint-store.js +1 -191
- 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-bake.d.ts +1 -38
- package/dist/plugins/tidb-image-bake.js +1 -348
- 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/plugins/write-behind-counter.d.ts +14 -3
- package/dist/plugins/write-behind-counter.js +39 -12
- package/dist/principal-jwt.d.ts +44 -0
- package/dist/principal-jwt.js +95 -0
- package/dist/security.d.ts +2 -58
- package/dist/security.js +3 -118
- package/dist/sema-registry.d.ts +5 -200
- package/dist/sema-registry.js +4 -567
- package/package.json +1 -1
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
function mysqlResult(r) {
|
|
2
|
+
if (Array.isArray(r))
|
|
3
|
+
return { rows: r, affected: 0 };
|
|
4
|
+
const h = r;
|
|
5
|
+
return { rows: [], affected: Number(h?.affectedRows ?? 0) };
|
|
6
|
+
}
|
|
7
|
+
async function mysqlQuery(q, sql, params) {
|
|
8
|
+
const [r] = (await q.query(sql, params ?? []));
|
|
9
|
+
return mysqlResult(r);
|
|
10
|
+
}
|
|
11
|
+
export function mysqlDriver(pool) {
|
|
12
|
+
return {
|
|
13
|
+
dialect: "tidb",
|
|
14
|
+
query: (sql, params) => mysqlQuery(pool, sql, params),
|
|
15
|
+
async connect() {
|
|
16
|
+
const c = await pool.getConnection();
|
|
17
|
+
return {
|
|
18
|
+
query: (sql, params) => mysqlQuery(c, sql, params),
|
|
19
|
+
begin: () => c.beginTransaction(),
|
|
20
|
+
beginPessimistic: async () => {
|
|
21
|
+
await c.query("BEGIN PESSIMISTIC");
|
|
22
|
+
},
|
|
23
|
+
commit: () => c.commit(),
|
|
24
|
+
rollback: () => c.rollback(),
|
|
25
|
+
release: () => c.release(),
|
|
26
|
+
};
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
async function pgQuery(q, sql, params) {
|
|
31
|
+
const res = await q.query(sql, params ?? []);
|
|
32
|
+
return { rows: (res.rows ?? []), affected: res.rowCount ?? 0 };
|
|
33
|
+
}
|
|
34
|
+
export function pgDriver(pool) {
|
|
35
|
+
return {
|
|
36
|
+
dialect: "pg",
|
|
37
|
+
query: (sql, params) => pgQuery(pool, sql, params),
|
|
38
|
+
async connect() {
|
|
39
|
+
const c = await pool.connect();
|
|
40
|
+
return {
|
|
41
|
+
query: (sql, params) => pgQuery(c, sql, params),
|
|
42
|
+
begin: async () => {
|
|
43
|
+
await c.query("BEGIN");
|
|
44
|
+
},
|
|
45
|
+
beginPessimistic: async () => {
|
|
46
|
+
await c.query("BEGIN");
|
|
47
|
+
},
|
|
48
|
+
commit: async () => {
|
|
49
|
+
await c.query("COMMIT");
|
|
50
|
+
},
|
|
51
|
+
rollback: async () => {
|
|
52
|
+
await c.query("ROLLBACK");
|
|
53
|
+
},
|
|
54
|
+
release: () => c.release(),
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=sql-driver.js.map
|
|
@@ -1,40 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export type ApprovalStatus = "pending" | "approved" | "denied" | "expired";
|
|
3
|
-
export interface ApprovalRow {
|
|
4
|
-
id: string;
|
|
5
|
-
taskId: string | null;
|
|
6
|
-
sessionId: string | null;
|
|
7
|
-
owner: string | null;
|
|
8
|
-
scope: string | null;
|
|
9
|
-
toolName: string;
|
|
10
|
-
args: unknown;
|
|
11
|
-
status: ApprovalStatus;
|
|
12
|
-
reason: string | null;
|
|
13
|
-
decidedBy: string | null;
|
|
14
|
-
createdAt: string;
|
|
15
|
-
decidedAt: string | null;
|
|
16
|
-
}
|
|
17
|
-
export declare class TiDBApprovalStore {
|
|
18
|
-
private readonly pool;
|
|
19
|
-
constructor(pool: Pool);
|
|
20
|
-
createPending(id: string, scope: string | null, ctx: {
|
|
21
|
-
taskId?: string | null;
|
|
22
|
-
sessionId?: string | null;
|
|
23
|
-
owner?: string | null;
|
|
24
|
-
toolName: string;
|
|
25
|
-
args: unknown;
|
|
26
|
-
}): Promise<void>;
|
|
27
|
-
getStatus(id: string, scope: string | null): Promise<{
|
|
28
|
-
status: ApprovalStatus;
|
|
29
|
-
reason: string | null;
|
|
30
|
-
decidedBy: string | null;
|
|
31
|
-
} | undefined>;
|
|
32
|
-
decide(id: string, scope: string | null, decision: "approved" | "denied" | "expired", reason: string | null, decidedBy: string | null): Promise<boolean>;
|
|
33
|
-
listPending(scope: string | null, owner?: string): Promise<ApprovalRow[]>;
|
|
34
|
-
get(id: string, scope: string | null): Promise<ApprovalRow | undefined>;
|
|
35
|
-
getById(id: string): Promise<ApprovalRow | undefined>;
|
|
36
|
-
listPendingAll(): Promise<ApprovalRow[]>;
|
|
37
|
-
expireStale(olderThanMs: number): Promise<number>;
|
|
38
|
-
}
|
|
39
|
-
export declare function mapRow(r: Record<string, unknown>): ApprovalRow;
|
|
1
|
+
export { TiDBApprovalStore, mapRow, type ApprovalRow, type ApprovalStatus, } from "./approval-store-sql.js";
|
|
40
2
|
//# sourceMappingURL=tidb-approval-store.d.ts.map
|
|
@@ -1,72 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export class TiDBApprovalStore {
|
|
3
|
-
pool;
|
|
4
|
-
constructor(pool) {
|
|
5
|
-
this.pool = pool;
|
|
6
|
-
}
|
|
7
|
-
async createPending(id, scope, ctx) {
|
|
8
|
-
await this.pool.query("INSERT INTO approval (id, task_id, session_id, owner, scope, tool_name, args, status, created_at) " +
|
|
9
|
-
"VALUES (?,?,?,?,?,?,?,'pending',?)", [
|
|
10
|
-
id,
|
|
11
|
-
ctx.taskId ?? null,
|
|
12
|
-
ctx.sessionId ?? null,
|
|
13
|
-
ctx.owner ?? null,
|
|
14
|
-
scope,
|
|
15
|
-
ctx.toolName,
|
|
16
|
-
ctx.args == null ? null : JSON.stringify(ctx.args),
|
|
17
|
-
new Date(),
|
|
18
|
-
]);
|
|
19
|
-
}
|
|
20
|
-
async getStatus(id, scope) {
|
|
21
|
-
const [rows] = await this.pool.query("SELECT status, reason, decided_by FROM approval WHERE id = ? AND scope <=> ?", [id, scope]);
|
|
22
|
-
const r = rows[0];
|
|
23
|
-
if (!r)
|
|
24
|
-
return undefined;
|
|
25
|
-
return { status: r.status, reason: r.reason ?? null, decidedBy: r.decided_by ?? null };
|
|
26
|
-
}
|
|
27
|
-
async decide(id, scope, decision, reason, decidedBy) {
|
|
28
|
-
const [res] = await this.pool.query("UPDATE approval SET status = ?, reason = ?, decided_by = ?, decided_at = ? WHERE id = ? AND scope <=> ? AND status = 'pending'", [decision, reason, decidedBy, new Date(), id, scope]);
|
|
29
|
-
return res.affectedRows === 1;
|
|
30
|
-
}
|
|
31
|
-
async listPending(scope, owner) {
|
|
32
|
-
const [rows] = owner
|
|
33
|
-
? await this.pool.query("SELECT * FROM approval WHERE status = 'pending' AND scope <=> ? AND owner = ? ORDER BY created_at ASC", [scope, owner])
|
|
34
|
-
: await this.pool.query("SELECT * FROM approval WHERE status = 'pending' AND scope <=> ? ORDER BY created_at ASC", [scope]);
|
|
35
|
-
return rows.map(mapRow);
|
|
36
|
-
}
|
|
37
|
-
async get(id, scope) {
|
|
38
|
-
const [rows] = await this.pool.query("SELECT * FROM approval WHERE id = ? AND scope <=> ?", [id, scope]);
|
|
39
|
-
return rows[0] ? mapRow(rows[0]) : undefined;
|
|
40
|
-
}
|
|
41
|
-
async getById(id) {
|
|
42
|
-
const [rows] = await this.pool.query("SELECT * FROM approval WHERE id = ?", [id]);
|
|
43
|
-
return rows[0] ? mapRow(rows[0]) : undefined;
|
|
44
|
-
}
|
|
45
|
-
async listPendingAll() {
|
|
46
|
-
const [rows] = await this.pool.query("SELECT * FROM approval WHERE status = 'pending' ORDER BY created_at ASC");
|
|
47
|
-
return rows.map(mapRow);
|
|
48
|
-
}
|
|
49
|
-
async expireStale(olderThanMs) {
|
|
50
|
-
const cutoff = new Date(Date.now() - olderThanMs);
|
|
51
|
-
const [res] = await this.pool.query("UPDATE approval SET status = 'expired', reason = 'timed out before decision', decided_at = ? " +
|
|
52
|
-
"WHERE status = 'pending' AND created_at < ?", [new Date(), cutoff]);
|
|
53
|
-
return res.affectedRows;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
export function mapRow(r) {
|
|
57
|
-
return {
|
|
58
|
-
id: String(r.id),
|
|
59
|
-
taskId: r.task_id ?? null,
|
|
60
|
-
sessionId: r.session_id ?? null,
|
|
61
|
-
owner: r.owner ?? null,
|
|
62
|
-
scope: r.scope ?? null,
|
|
63
|
-
toolName: String(r.tool_name),
|
|
64
|
-
args: parseJson(r.args),
|
|
65
|
-
status: r.status,
|
|
66
|
-
reason: r.reason ?? null,
|
|
67
|
-
decidedBy: r.decided_by ?? null,
|
|
68
|
-
createdAt: iso(r.created_at),
|
|
69
|
-
decidedAt: iso(r.decided_at),
|
|
70
|
-
};
|
|
71
|
-
}
|
|
1
|
+
export { TiDBApprovalStore, mapRow, } from "./approval-store-sql.js";
|
|
72
2
|
//# sourceMappingURL=tidb-approval-store.js.map
|
|
@@ -1,18 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import type { BreakerSnapshot, BreakerState } from "@sema-agent/core";
|
|
3
|
-
export declare class TiDBBreakerState implements BreakerState {
|
|
4
|
-
private readonly pool;
|
|
5
|
-
private readonly onWriteFail?;
|
|
6
|
-
private cache;
|
|
7
|
-
private timer?;
|
|
8
|
-
private readonly pending;
|
|
9
|
-
constructor(pool: Pool, onWriteFail?: ((streak: number) => void) | undefined);
|
|
10
|
-
private writeFailStreak;
|
|
11
|
-
get(key: string): BreakerSnapshot | undefined;
|
|
12
|
-
set(key: string, snap: BreakerSnapshot): void;
|
|
13
|
-
private writeThrough;
|
|
14
|
-
refresh(): Promise<void>;
|
|
15
|
-
startRefresh(intervalMs?: number): this;
|
|
16
|
-
stop(): void;
|
|
17
|
-
}
|
|
1
|
+
export { TiDBBreakerState } from "./breaker-state-sql.js";
|
|
18
2
|
//# sourceMappingURL=tidb-breaker-state.d.ts.map
|
|
@@ -1,75 +1,2 @@
|
|
|
1
|
-
export
|
|
2
|
-
pool;
|
|
3
|
-
onWriteFail;
|
|
4
|
-
cache = new Map();
|
|
5
|
-
timer;
|
|
6
|
-
pending = new Set();
|
|
7
|
-
constructor(pool, onWriteFail) {
|
|
8
|
-
this.pool = pool;
|
|
9
|
-
this.onWriteFail = onWriteFail;
|
|
10
|
-
}
|
|
11
|
-
writeFailStreak = 0;
|
|
12
|
-
get(key) {
|
|
13
|
-
return this.cache.get(key);
|
|
14
|
-
}
|
|
15
|
-
set(key, snap) {
|
|
16
|
-
this.cache.set(key, snap);
|
|
17
|
-
this.pending.add(key);
|
|
18
|
-
void this.writeThrough(key, snap);
|
|
19
|
-
}
|
|
20
|
-
async writeThrough(key, snap) {
|
|
21
|
-
try {
|
|
22
|
-
await this.pool.query("INSERT INTO circuit_breaker (breaker_key, phase, failures, opened_at, updated_at) VALUES (?,?,?,?,?) " +
|
|
23
|
-
"ON DUPLICATE KEY UPDATE phase=VALUES(phase), failures=VALUES(failures), opened_at=VALUES(opened_at), updated_at=VALUES(updated_at)", [key, snap.phase, snap.failures, snap.openedAt != null ? new Date(snap.openedAt) : null, new Date()]);
|
|
24
|
-
this.pending.delete(key);
|
|
25
|
-
if (this.writeFailStreak > 0) {
|
|
26
|
-
this.writeFailStreak = 0;
|
|
27
|
-
try {
|
|
28
|
-
this.onWriteFail?.(0);
|
|
29
|
-
}
|
|
30
|
-
catch { }
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
catch {
|
|
34
|
-
try {
|
|
35
|
-
this.onWriteFail?.(++this.writeFailStreak);
|
|
36
|
-
}
|
|
37
|
-
catch { }
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
async refresh() {
|
|
41
|
-
try {
|
|
42
|
-
const pendingAtStart = new Set(this.pending);
|
|
43
|
-
const guarded = (key) => this.pending.has(key) || pendingAtStart.has(key);
|
|
44
|
-
const [rows] = await this.pool.query("SELECT breaker_key, phase, failures, opened_at FROM circuit_breaker");
|
|
45
|
-
const seen = new Set();
|
|
46
|
-
for (const r of rows) {
|
|
47
|
-
const key = String(r.breaker_key);
|
|
48
|
-
seen.add(key);
|
|
49
|
-
if (guarded(key))
|
|
50
|
-
continue;
|
|
51
|
-
this.cache.set(key, {
|
|
52
|
-
phase: r.phase,
|
|
53
|
-
failures: Number(r.failures),
|
|
54
|
-
openedAt: r.opened_at != null ? new Date(r.opened_at).getTime() : undefined,
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
for (const key of this.cache.keys())
|
|
58
|
-
if (!seen.has(key) && !guarded(key))
|
|
59
|
-
this.cache.delete(key);
|
|
60
|
-
}
|
|
61
|
-
catch {
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
startRefresh(intervalMs = 5_000) {
|
|
65
|
-
this.timer ??= setInterval(() => void this.refresh(), intervalMs);
|
|
66
|
-
this.timer.unref?.();
|
|
67
|
-
return this;
|
|
68
|
-
}
|
|
69
|
-
stop() {
|
|
70
|
-
if (this.timer)
|
|
71
|
-
clearInterval(this.timer);
|
|
72
|
-
this.timer = undefined;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
1
|
+
export { TiDBBreakerState } from "./breaker-state-sql.js";
|
|
75
2
|
//# sourceMappingURL=tidb-breaker-state.js.map
|
|
@@ -1,50 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import { type Checkpoint, type CheckpointStore, type CheckpointSummary, type CheckpointToken, type ResumeOutcome, type ResolveExpectation, type ReopenReason, type RiskDescriptor } from "@sema-agent/core";
|
|
3
|
-
export declare const TERMINAL_BACKSTOP_MS: number;
|
|
4
|
-
export declare const TERMINAL_GRACE_MS = 3600000;
|
|
5
|
-
export declare function tokenFingerprint(token: string): string;
|
|
6
|
-
export interface PendingCheckpoint {
|
|
7
|
-
sessionId: string;
|
|
8
|
-
scope: string;
|
|
9
|
-
toolName: string | null;
|
|
10
|
-
toolCallId: string | null;
|
|
11
|
-
boundCallId: string | null;
|
|
12
|
-
boundInputHash: string | null;
|
|
13
|
-
taskId: string | null;
|
|
14
|
-
input: unknown;
|
|
15
|
-
createdAt: number;
|
|
16
|
-
deadline: number | null;
|
|
17
|
-
riskDescriptor: RiskDescriptor | null;
|
|
18
|
-
}
|
|
19
|
-
export declare function boundedToolInput(args: unknown): unknown;
|
|
20
|
-
export declare class TiDBCheckpointStore implements CheckpointStore {
|
|
21
|
-
private readonly pool;
|
|
22
|
-
private readonly logger?;
|
|
23
|
-
constructor(pool: Pool, logger?: {
|
|
24
|
-
info?(msg: string, meta?: unknown): void;
|
|
25
|
-
} | undefined);
|
|
26
|
-
put(token: CheckpointToken, cp: Checkpoint): Promise<void>;
|
|
27
|
-
get(token: CheckpointToken): Promise<Checkpoint | null>;
|
|
28
|
-
resolve(token: CheckpointToken, scope: string, outcome: ResumeOutcome, expect?: ResolveExpectation): Promise<boolean>;
|
|
29
|
-
reopen(token: CheckpointToken, scope: string, reason: ReopenReason): Promise<boolean>;
|
|
30
|
-
setPendingSteer(token: CheckpointToken, scope: string, steer: {
|
|
31
|
-
text: string;
|
|
32
|
-
trusted: boolean;
|
|
33
|
-
}): Promise<boolean>;
|
|
34
|
-
expire(token: CheckpointToken, scope: string): Promise<boolean>;
|
|
35
|
-
reap(scope: string, cutoff: number): Promise<number>;
|
|
36
|
-
reapExpired(cutoff: number): Promise<number>;
|
|
37
|
-
listExpiredApprovalGates(cutoff: number, limit?: number): Promise<Array<{
|
|
38
|
-
sessionId: string;
|
|
39
|
-
scope: string;
|
|
40
|
-
}>>;
|
|
41
|
-
listPending(scope?: string): Promise<PendingCheckpoint[]>;
|
|
42
|
-
listByScope(scope: string): Promise<CheckpointSummary[]>;
|
|
43
|
-
findPendingTokenBySession(sessionId: string, scope?: string): Promise<CheckpointToken | null>;
|
|
44
|
-
peekPendingScope(sessionId: string): Promise<string | null | undefined>;
|
|
45
|
-
putCtx(sessionId: string, ctx: unknown): Promise<void>;
|
|
46
|
-
getCtx<T = unknown>(sessionId: string): Promise<T | null>;
|
|
47
|
-
reapCtx(cutoff: number): Promise<number>;
|
|
48
|
-
deleteBySession(sessionId: string, owner: string | null): Promise<number>;
|
|
49
|
-
}
|
|
1
|
+
export { TiDBCheckpointStore, SqlCheckpointStore, TERMINAL_BACKSTOP_MS, TERMINAL_GRACE_MS, tokenFingerprint, boundedToolInput, type PendingCheckpoint, } from "./checkpoint-store-sql.js";
|
|
50
2
|
//# sourceMappingURL=tidb-checkpoint-store.d.ts.map
|
|
@@ -1,192 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import { CheckpointError, validatePendingSteer, checkpointVersionOf, winnerFromOutcome, summarizeCheckpoint, MAX_SUPPORTED_CHECKPOINT_VERSION } from "@sema-agent/core";
|
|
3
|
-
import { redactDeep } from "../trace/redact.js";
|
|
4
|
-
import { parseJsonStrict as parseJson } from "./sql-row-helpers.js";
|
|
5
|
-
const MAX_TOOL_INPUT_CHARS = 8192;
|
|
6
|
-
export const TERMINAL_BACKSTOP_MS = Math.max(60_000, Number(process.env.APPROVAL_TERMINAL_BACKSTOP_MS) || 30 * 86_400_000);
|
|
7
|
-
export const TERMINAL_GRACE_MS = 3_600_000;
|
|
8
|
-
export function tokenFingerprint(token) {
|
|
9
|
-
return "sha256:" + createHash("sha256").update(token).digest("hex").slice(0, 12);
|
|
10
|
-
}
|
|
11
|
-
export function boundedToolInput(args) {
|
|
12
|
-
if (args === undefined)
|
|
13
|
-
return null;
|
|
14
|
-
const redacted = redactDeep(args);
|
|
15
|
-
const json = JSON.stringify(redacted);
|
|
16
|
-
if (json === undefined)
|
|
17
|
-
return null;
|
|
18
|
-
if (json.length > MAX_TOOL_INPUT_CHARS)
|
|
19
|
-
return { truncated: true, bytes: json.length };
|
|
20
|
-
return redacted;
|
|
21
|
-
}
|
|
22
|
-
const DUP_ENTRY = 1062;
|
|
23
|
-
export class TiDBCheckpointStore {
|
|
24
|
-
pool;
|
|
25
|
-
logger;
|
|
26
|
-
constructor(pool, logger) {
|
|
27
|
-
this.pool = pool;
|
|
28
|
-
this.logger = logger;
|
|
29
|
-
}
|
|
30
|
-
async put(token, cp) {
|
|
31
|
-
const pa = cp.pendingAction;
|
|
32
|
-
const version = checkpointVersionOf(cp);
|
|
33
|
-
const toolInput = boundedToolInput(pa?.args);
|
|
34
|
-
try {
|
|
35
|
-
await this.pool.query("INSERT INTO checkpoint (token, scope, session_id, version, status, tool_name, tool_call_id, tool_input, checkpoint, deadline, created_at, terminal_at, gate_kind, bound_input_hash, risk_descriptor) " +
|
|
36
|
-
"VALUES (?,?,?,?,'pending',?,?,?,?,?,?,?,?,?,?)", [
|
|
37
|
-
token,
|
|
38
|
-
cp.scope,
|
|
39
|
-
cp.sessionId,
|
|
40
|
-
version,
|
|
41
|
-
pa?.toolName ?? null,
|
|
42
|
-
pa?.toolCallId ?? null,
|
|
43
|
-
toolInput === null ? null : JSON.stringify(toolInput),
|
|
44
|
-
JSON.stringify(cp),
|
|
45
|
-
cp.deadline ?? null,
|
|
46
|
-
cp.createdAt,
|
|
47
|
-
Math.max(cp.createdAt + TERMINAL_BACKSTOP_MS, (cp.deadline ?? 0) + TERMINAL_GRACE_MS),
|
|
48
|
-
cp.gate?.kind ?? null,
|
|
49
|
-
pa?.boundInputHash ?? null,
|
|
50
|
-
((g) => (g?.riskDescriptor ? JSON.stringify(g.riskDescriptor) : null))(cp.gate),
|
|
51
|
-
]);
|
|
52
|
-
}
|
|
53
|
-
catch (e) {
|
|
54
|
-
if (e?.errno === DUP_ENTRY) {
|
|
55
|
-
throw new CheckpointError("checkpoint.already_exists", `checkpoint token already exists`);
|
|
56
|
-
}
|
|
57
|
-
throw e;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
async get(token) {
|
|
61
|
-
const [rows] = await this.pool.query("SELECT version, status, checkpoint, outcome, reopen_reason, rev, pending_steer FROM checkpoint WHERE token = ?", [token]);
|
|
62
|
-
const r = rows[0];
|
|
63
|
-
if (!r)
|
|
64
|
-
return null;
|
|
65
|
-
const version = Number(r.version);
|
|
66
|
-
if (version > MAX_SUPPORTED_CHECKPOINT_VERSION) {
|
|
67
|
-
throw new Error(`checkpoint format version ${version} is newer than this build supports (max ${MAX_SUPPORTED_CHECKPOINT_VERSION}) — upgrade the service to resume it`);
|
|
68
|
-
}
|
|
69
|
-
const cp = parseJson(r.checkpoint);
|
|
70
|
-
cp.status = r.status;
|
|
71
|
-
const outcomeRaw = parseJson(r.outcome);
|
|
72
|
-
if (outcomeRaw)
|
|
73
|
-
cp.resolvedOutcome = winnerFromOutcome(outcomeRaw);
|
|
74
|
-
cp.reopenReason = r.reopen_reason ?? undefined;
|
|
75
|
-
cp.rev = r.rev == null ? 0 : Number(r.rev);
|
|
76
|
-
const steerRaw = parseJson(r.pending_steer);
|
|
77
|
-
if (steerRaw && cp.state)
|
|
78
|
-
cp.state.pendingSteer = steerRaw;
|
|
79
|
-
this.logger?.info?.("checkpoint_get", {
|
|
80
|
-
tokenFp: tokenFingerprint(token),
|
|
81
|
-
status: cp.status,
|
|
82
|
-
version,
|
|
83
|
-
hasWorkspaceHandle: !!cp.state?.workspaceHandle,
|
|
84
|
-
snapshotId: cp.state?.workspaceHandle?.snapshotId,
|
|
85
|
-
});
|
|
86
|
-
return cp;
|
|
87
|
-
}
|
|
88
|
-
async resolve(token, scope, outcome, expect) {
|
|
89
|
-
const params = [JSON.stringify(outcome), Date.now(), token, scope];
|
|
90
|
-
if (expect)
|
|
91
|
-
params.push(expect.rev);
|
|
92
|
-
const [res] = await this.pool.query("UPDATE checkpoint SET status = 'resolved', outcome = ?, decided_at = ?, rev = rev + 1, reopen_reason = NULL WHERE token = ? AND scope = ? AND status = 'pending'" +
|
|
93
|
-
(expect ? " AND rev = ?" : ""), params);
|
|
94
|
-
return res.affectedRows === 1;
|
|
95
|
-
}
|
|
96
|
-
async reopen(token, scope, reason) {
|
|
97
|
-
const [res] = await this.pool.query("UPDATE checkpoint SET status = 'pending', reopen_reason = ?, rev = rev + 1 WHERE token = ? AND scope = ? AND status = 'resolved'", [reason, token, scope]);
|
|
98
|
-
return res.affectedRows === 1;
|
|
99
|
-
}
|
|
100
|
-
async setPendingSteer(token, scope, steer) {
|
|
101
|
-
const clean = validatePendingSteer(steer);
|
|
102
|
-
const [res] = await this.pool.query("UPDATE checkpoint SET pending_steer = ? WHERE token = ? AND scope = ? AND status = 'pending'", [JSON.stringify(clean), token, scope]);
|
|
103
|
-
return res.affectedRows > 0;
|
|
104
|
-
}
|
|
105
|
-
async expire(token, scope) {
|
|
106
|
-
const [res] = await this.pool.query("UPDATE checkpoint SET status = 'expired', decided_at = ? WHERE token = ? AND scope = ? AND status = 'pending'", [Date.now(), token, scope]);
|
|
107
|
-
return res.affectedRows === 1;
|
|
108
|
-
}
|
|
109
|
-
async reap(scope, cutoff) {
|
|
110
|
-
const [res] = await this.pool.query("UPDATE checkpoint SET status = 'expired', decided_at = ? WHERE scope = ? AND status = 'pending' AND deadline IS NOT NULL AND deadline <= ?", [Date.now(), scope, cutoff]);
|
|
111
|
-
return res.affectedRows;
|
|
112
|
-
}
|
|
113
|
-
async reapExpired(cutoff) {
|
|
114
|
-
const [res] = await this.pool.query("UPDATE checkpoint SET status = 'expired', decided_at = ? " +
|
|
115
|
-
"WHERE status = 'pending' AND ((deadline IS NOT NULL AND deadline <= ? AND (gate_kind IS NULL OR gate_kind NOT IN ('human','irreversible_ask') OR COALESCE(tool_name,'') = 'AskUserQuestion')) OR (terminal_at IS NOT NULL AND terminal_at <= ?))", [Date.now(), cutoff, cutoff]);
|
|
116
|
-
return res.affectedRows;
|
|
117
|
-
}
|
|
118
|
-
async listExpiredApprovalGates(cutoff, limit = 100) {
|
|
119
|
-
const [rows] = await this.pool.query("SELECT session_id, scope FROM checkpoint WHERE status = 'pending' AND gate_kind IN ('human','irreversible_ask') " +
|
|
120
|
-
"AND COALESCE(tool_name,'') <> 'AskUserQuestion' AND deadline IS NOT NULL AND deadline <= ? ORDER BY deadline ASC LIMIT ?", [cutoff, limit]);
|
|
121
|
-
return rows.map((r) => ({ sessionId: String(r.session_id), scope: String(r.scope) }));
|
|
122
|
-
}
|
|
123
|
-
async listPending(scope) {
|
|
124
|
-
const base = "SELECT c.session_id, c.scope, c.tool_name, c.tool_call_id, c.tool_input, c.bound_input_hash, c.risk_descriptor, c.created_at, c.deadline, ta.task_id " +
|
|
125
|
-
"FROM checkpoint c LEFT JOIN task_active ta ON ta.session_id = c.session_id WHERE c.status='pending'";
|
|
126
|
-
const [rows] = scope
|
|
127
|
-
? await this.pool.query(`${base} AND c.scope=? ORDER BY c.created_at ASC`, [scope])
|
|
128
|
-
: await this.pool.query(`${base} ORDER BY c.created_at ASC`);
|
|
129
|
-
const out = rows.map((r) => {
|
|
130
|
-
const toolCallId = r.tool_call_id ?? null;
|
|
131
|
-
return {
|
|
132
|
-
sessionId: String(r.session_id),
|
|
133
|
-
scope: String(r.scope),
|
|
134
|
-
toolName: r.tool_name ?? null,
|
|
135
|
-
toolCallId,
|
|
136
|
-
boundCallId: toolCallId,
|
|
137
|
-
boundInputHash: r.bound_input_hash ?? null,
|
|
138
|
-
taskId: r.task_id ?? null,
|
|
139
|
-
input: r.tool_input ?? null,
|
|
140
|
-
createdAt: Number(r.created_at),
|
|
141
|
-
deadline: r.deadline == null ? null : Number(r.deadline),
|
|
142
|
-
riskDescriptor: parseJson(r.risk_descriptor),
|
|
143
|
-
};
|
|
144
|
-
});
|
|
145
|
-
return out.sort((a, b) => (b.riskDescriptor?.severity ?? 0) - (a.riskDescriptor?.severity ?? 0) || a.createdAt - b.createdAt);
|
|
146
|
-
}
|
|
147
|
-
async listByScope(scope) {
|
|
148
|
-
const [rows] = await this.pool.query("SELECT checkpoint, status FROM checkpoint WHERE status = 'pending' AND scope = ? ORDER BY created_at ASC LIMIT 500", [scope]);
|
|
149
|
-
const out = [];
|
|
150
|
-
for (const r of rows) {
|
|
151
|
-
const cp = parseJson(r.checkpoint);
|
|
152
|
-
if (!cp)
|
|
153
|
-
continue;
|
|
154
|
-
cp.status = r.status;
|
|
155
|
-
out.push(summarizeCheckpoint(cp));
|
|
156
|
-
}
|
|
157
|
-
return out;
|
|
158
|
-
}
|
|
159
|
-
async findPendingTokenBySession(sessionId, scope) {
|
|
160
|
-
const [rows] = scope
|
|
161
|
-
? await this.pool.query("SELECT token FROM checkpoint WHERE session_id=? AND scope=? AND status='pending' LIMIT 1", [sessionId, scope])
|
|
162
|
-
: await this.pool.query("SELECT token FROM checkpoint WHERE session_id=? AND status='pending' LIMIT 1", [sessionId]);
|
|
163
|
-
return rows[0] ? String(rows[0].token) : null;
|
|
164
|
-
}
|
|
165
|
-
async peekPendingScope(sessionId) {
|
|
166
|
-
const [rows] = await this.pool.query("SELECT scope FROM checkpoint WHERE session_id=? AND status='pending' LIMIT 1", [sessionId]);
|
|
167
|
-
if (!rows[0])
|
|
168
|
-
return undefined;
|
|
169
|
-
return rows[0].scope ?? null;
|
|
170
|
-
}
|
|
171
|
-
async putCtx(sessionId, ctx) {
|
|
172
|
-
await this.pool.query("INSERT INTO checkpoint_ctx (session_id, ctx, updated_at) VALUES (?,?,?) " +
|
|
173
|
-
"ON DUPLICATE KEY UPDATE ctx = VALUES(ctx), updated_at = VALUES(updated_at)", [sessionId, JSON.stringify(ctx), Date.now()]);
|
|
174
|
-
}
|
|
175
|
-
async getCtx(sessionId) {
|
|
176
|
-
const [rows] = await this.pool.query("SELECT ctx FROM checkpoint_ctx WHERE session_id=?", [sessionId]);
|
|
177
|
-
return rows[0] ? parseJson(rows[0].ctx) : null;
|
|
178
|
-
}
|
|
179
|
-
async reapCtx(cutoff) {
|
|
180
|
-
const [res] = await this.pool.query("DELETE FROM checkpoint_ctx WHERE updated_at < ? " +
|
|
181
|
-
"AND session_id NOT IN (SELECT session_id FROM checkpoint WHERE status='pending') " +
|
|
182
|
-
"AND session_id NOT IN (SELECT session_id FROM task_active)", [cutoff]);
|
|
183
|
-
return res.affectedRows;
|
|
184
|
-
}
|
|
185
|
-
async deleteBySession(sessionId, owner) {
|
|
186
|
-
const ownerGuard = "EXISTS (SELECT 1 FROM session_meta sm WHERE sm.session_id = ? AND sm.owner <=> ?)";
|
|
187
|
-
const [res] = await this.pool.query(`DELETE FROM checkpoint WHERE session_id = ? AND ${ownerGuard}`, [sessionId, sessionId, owner]);
|
|
188
|
-
await this.pool.query(`DELETE FROM checkpoint_ctx WHERE session_id = ? AND ${ownerGuard}`, [sessionId, sessionId, owner]);
|
|
189
|
-
return res.affectedRows;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
1
|
+
export { TiDBCheckpointStore, SqlCheckpointStore, TERMINAL_BACKSTOP_MS, TERMINAL_GRACE_MS, tokenFingerprint, boundedToolInput, } from "./checkpoint-store-sql.js";
|
|
192
2
|
//# sourceMappingURL=tidb-checkpoint-store.js.map
|
|
@@ -1,28 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import type { Pool } from "mysql2/promise";
|
|
3
|
-
import { type BlobBackend } from "./blob-backend.js";
|
|
4
|
-
export declare class TiDBFileSnapshotStore implements FileSnapshotStore {
|
|
5
|
-
private readonly pool;
|
|
6
|
-
private readonly bounds;
|
|
7
|
-
private readonly inFlight;
|
|
8
|
-
private readonly blobs;
|
|
9
|
-
onSkippedVanished: ((count: number) => void | Promise<void>) | undefined;
|
|
10
|
-
constructor(pool: Pool, blobBackend?: BlobBackend, bounds?: FileSnapshotBounds);
|
|
11
|
-
private putBlobRow;
|
|
12
|
-
putBlob(hash: string, bytes: Uint8Array): Promise<FileSnapshotResult>;
|
|
13
|
-
snapshot(scope: string, key: string, env: ExecutionEnv, root: string, signal?: AbortSignal): Promise<FileSnapshotResult>;
|
|
14
|
-
importManifest(scope: string, key: string, manifest: Map<string, string>, srcGetBlob: (hash: string) => Promise<Uint8Array | undefined>): Promise<FileSnapshotResult>;
|
|
15
|
-
restore(scope: string, key: string, env: ExecutionEnv, root: string, signal?: AbortSignal): Promise<FileSnapshotResult>;
|
|
16
|
-
has(scope: string, key: string): Promise<boolean>;
|
|
17
|
-
listKeys(scope: string): Promise<string[]>;
|
|
18
|
-
exportManifest(scope: string, key: string): Promise<Map<string, string> | null>;
|
|
19
|
-
getBlob(hash: string): Promise<Uint8Array | undefined>;
|
|
20
|
-
hasBlobs(hashes: string[]): Promise<Set<string>>;
|
|
21
|
-
blobSizes(hashes: string[]): Promise<Map<string, number>>;
|
|
22
|
-
reap(scope: string, keepKeys: string[]): Promise<number>;
|
|
23
|
-
deleteBySession(scope: string): Promise<number>;
|
|
24
|
-
private gcOrphanBlobs;
|
|
25
|
-
sweepOrphanBlobs(): Promise<number>;
|
|
26
|
-
private tx;
|
|
27
|
-
}
|
|
1
|
+
export { TiDBFileSnapshotStore } from "./file-snapshot-store-sql.js";
|
|
28
2
|
//# sourceMappingURL=tidb-file-snapshot-store.d.ts.map
|