@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.
Files changed (133) hide show
  1. package/README.md +9 -0
  2. package/README.zh-CN.md +7 -0
  3. package/dist/config-types.d.ts +1 -1
  4. package/dist/config.d.ts +14 -0
  5. package/dist/config.js +148 -45
  6. package/dist/elicitation.js +2 -2
  7. package/dist/http/idempotency.d.ts +1 -0
  8. package/dist/http/idempotency.js +3 -0
  9. package/dist/http/principal-gate.d.ts +12 -0
  10. package/dist/http/principal-gate.js +52 -0
  11. package/dist/http/route-ctx.d.ts +116 -0
  12. package/dist/http/route-ctx.js +2 -0
  13. package/dist/http/routes/approvals-assistant.d.ts +11 -0
  14. package/dist/http/routes/approvals-assistant.js +530 -0
  15. package/dist/http/routes/attachments.d.ts +4 -0
  16. package/dist/http/routes/attachments.js +106 -0
  17. package/dist/http/routes/capabilities.d.ts +4 -0
  18. package/dist/http/routes/capabilities.js +111 -0
  19. package/dist/http/routes/fleet.d.ts +4 -0
  20. package/dist/http/routes/fleet.js +147 -0
  21. package/dist/http/routes/images.d.ts +20 -0
  22. package/dist/http/routes/images.js +572 -0
  23. package/dist/http/routes/leader.d.ts +4 -0
  24. package/dist/http/routes/leader.js +48 -0
  25. package/dist/http/routes/memory-policy.d.ts +4 -0
  26. package/dist/http/routes/memory-policy.js +105 -0
  27. package/dist/http/routes/notify-wake.d.ts +4 -0
  28. package/dist/http/routes/notify-wake.js +133 -0
  29. package/dist/http/routes/observability.d.ts +4 -0
  30. package/dist/http/routes/observability.js +63 -0
  31. package/dist/http/routes/runs.d.ts +19 -0
  32. package/dist/http/routes/runs.js +967 -0
  33. package/dist/http/routes/session-sync.d.ts +36 -0
  34. package/dist/http/routes/session-sync.js +513 -0
  35. package/dist/http/routes/sessions-list.d.ts +4 -0
  36. package/dist/http/routes/sessions-list.js +117 -0
  37. package/dist/http/routes/sessions.d.ts +17 -0
  38. package/dist/http/routes/sessions.js +746 -0
  39. package/dist/http/routes/side-query.d.ts +4 -0
  40. package/dist/http/routes/side-query.js +88 -0
  41. package/dist/http/routes/tasks.d.ts +4 -0
  42. package/dist/http/routes/tasks.js +632 -0
  43. package/dist/http/routes/trace-usage.d.ts +4 -0
  44. package/dist/http/routes/trace-usage.js +239 -0
  45. package/dist/http/routes/workflows.d.ts +5 -0
  46. package/dist/http/routes/workflows.js +337 -0
  47. package/dist/http/run-meta.d.ts +11 -0
  48. package/dist/http/run-meta.js +16 -0
  49. package/dist/http/send.d.ts +7 -0
  50. package/dist/http/send.js +34 -0
  51. package/dist/http/server.d.ts +12 -12
  52. package/dist/http/server.js +289 -5502
  53. package/dist/http/sse-log.d.ts +25 -0
  54. package/dist/http/sse-log.js +59 -0
  55. package/dist/http/wire-types.d.ts +6 -0
  56. package/dist/http/workspace-content.d.ts +3 -0
  57. package/dist/http/workspace-content.js +20 -0
  58. package/dist/leader/endpoint.js +4 -4
  59. package/dist/main.js +5 -5
  60. package/dist/plugins/approval-store-sql.d.ts +52 -0
  61. package/dist/plugins/approval-store-sql.js +119 -0
  62. package/dist/plugins/breaker-state-sql.d.ts +29 -0
  63. package/dist/plugins/breaker-state-sql.js +104 -0
  64. package/dist/plugins/file-snapshot-store-sql.d.ts +38 -0
  65. package/dist/plugins/file-snapshot-store-sql.js +210 -0
  66. package/dist/plugins/image-index-sql.d.ts +33 -0
  67. package/dist/plugins/image-index-sql.js +328 -0
  68. package/dist/plugins/outcome-ledger-sql.d.ts +70 -0
  69. package/dist/plugins/outcome-ledger-sql.js +158 -0
  70. package/dist/plugins/pg-approval-store.d.ts +1 -27
  71. package/dist/plugins/pg-approval-store.js +1 -83
  72. package/dist/plugins/pg-breaker-state.d.ts +1 -19
  73. package/dist/plugins/pg-breaker-state.js +1 -88
  74. package/dist/plugins/pg-file-snapshot-store.d.ts +1 -27
  75. package/dist/plugins/pg-file-snapshot-store.js +1 -190
  76. package/dist/plugins/pg-image-index.d.ts +1 -21
  77. package/dist/plugins/pg-image-index.js +1 -217
  78. package/dist/plugins/pg-outcome-ledger.d.ts +2 -22
  79. package/dist/plugins/pg-outcome-ledger.js +1 -104
  80. package/dist/plugins/pg-resume-anchor-store.d.ts +1 -13
  81. package/dist/plugins/pg-resume-anchor-store.js +1 -22
  82. package/dist/plugins/pg-run-store.d.ts +1 -75
  83. package/dist/plugins/pg-run-store.js +1 -287
  84. package/dist/plugins/pg-session-policy-store.d.ts +1 -11
  85. package/dist/plugins/pg-session-policy-store.js +1 -90
  86. package/dist/plugins/pg-tool-result-store.d.ts +1 -15
  87. package/dist/plugins/pg-tool-result-store.js +1 -52
  88. package/dist/plugins/pg-workflow-journal-store.d.ts +1 -20
  89. package/dist/plugins/pg-workflow-journal-store.js +1 -34
  90. package/dist/plugins/pg-workflow-run-store.d.ts +1 -55
  91. package/dist/plugins/pg-workflow-run-store.js +1 -220
  92. package/dist/plugins/remote-env-host.js +4 -3
  93. package/dist/plugins/resume-anchor-store-sql.d.ts +23 -0
  94. package/dist/plugins/resume-anchor-store-sql.js +38 -0
  95. package/dist/plugins/run-store-sql.d.ts +89 -0
  96. package/dist/plugins/run-store-sql.js +397 -0
  97. package/dist/plugins/session-policy-store-sql.d.ts +22 -0
  98. package/dist/plugins/session-policy-store-sql.js +109 -0
  99. package/dist/plugins/tidb-approval-store.d.ts +1 -39
  100. package/dist/plugins/tidb-approval-store.js +1 -71
  101. package/dist/plugins/tidb-breaker-state.d.ts +1 -17
  102. package/dist/plugins/tidb-breaker-state.js +1 -74
  103. package/dist/plugins/tidb-file-snapshot-store.d.ts +1 -27
  104. package/dist/plugins/tidb-file-snapshot-store.js +1 -192
  105. package/dist/plugins/tidb-image-index.d.ts +1 -19
  106. package/dist/plugins/tidb-image-index.js +1 -149
  107. package/dist/plugins/tidb-outcome-ledger.d.ts +1 -57
  108. package/dist/plugins/tidb-outcome-ledger.js +1 -97
  109. package/dist/plugins/tidb-resume-anchor-store.d.ts +1 -13
  110. package/dist/plugins/tidb-resume-anchor-store.js +1 -22
  111. package/dist/plugins/tidb-run-store.d.ts +1 -75
  112. package/dist/plugins/tidb-run-store.js +1 -306
  113. package/dist/plugins/tidb-session-policy-store.d.ts +1 -11
  114. package/dist/plugins/tidb-session-policy-store.js +1 -86
  115. package/dist/plugins/tidb-tool-result-store.d.ts +1 -13
  116. package/dist/plugins/tidb-tool-result-store.js +1 -38
  117. package/dist/plugins/tidb-workflow-journal-store.d.ts +1 -20
  118. package/dist/plugins/tidb-workflow-journal-store.js +1 -34
  119. package/dist/plugins/tidb-workflow-run-store.d.ts +1 -61
  120. package/dist/plugins/tidb-workflow-run-store.js +1 -231
  121. package/dist/plugins/tool-result-store-sql.d.ts +25 -0
  122. package/dist/plugins/tool-result-store-sql.js +69 -0
  123. package/dist/plugins/workflow-journal-store-sql.d.ts +30 -0
  124. package/dist/plugins/workflow-journal-store-sql.js +53 -0
  125. package/dist/plugins/workflow-run-store-sql.d.ts +85 -0
  126. package/dist/plugins/workflow-run-store-sql.js +299 -0
  127. package/dist/question.js +2 -2
  128. package/dist/run-local.js +1 -1
  129. package/dist/tool-approval.js +2 -2
  130. package/dist/trace/ledger-sink.js +1 -1
  131. package/dist/trace/project.d.ts +1 -0
  132. package/dist/trace/project.js +3 -0
  133. package/package.json +1 -1
@@ -1,18 +1,2 @@
1
- import type { Pool } from "mysql2/promise";
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 class TiDBBreakerState {
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,28 +1,2 @@
1
- import { type FileSnapshotBounds, type FileSnapshotStore, type FileSnapshotResult, type ExecutionEnv } from "@sema-agent/core";
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
@@ -1,193 +1,2 @@
1
- import { captureManifest, applyManifest, DEFAULT_SNAPSHOT_BOUNDS } from "@sema-agent/core";
2
- import { createHash } from "node:crypto";
3
- import { SqlBlobBackend, sqlBlobSizes } from "./blob-backend.js";
4
- export class TiDBFileSnapshotStore {
5
- pool;
6
- bounds;
7
- inFlight = new Set();
8
- blobs;
9
- onSkippedVanished = undefined;
10
- constructor(pool, blobBackend, bounds = DEFAULT_SNAPSHOT_BOUNDS) {
11
- this.pool = pool;
12
- this.bounds = bounds;
13
- this.blobs = blobBackend ?? new SqlBlobBackend("tidb", pool);
14
- }
15
- async putBlobRow(hash, bytes) {
16
- await this.blobs.putBlob(hash, bytes);
17
- }
18
- async putBlob(hash, bytes) {
19
- if (createHash("sha256").update(bytes).digest("hex") !== hash) {
20
- return { ok: false, error: { code: "read_failed", message: `putBlob ${hash} fails content-address integrity — nothing stored` } };
21
- }
22
- try {
23
- await this.putBlobRow(hash, bytes);
24
- return { ok: true };
25
- }
26
- catch (err) {
27
- return { ok: false, error: { code: "restore_failed", message: `putBlob ${hash} write/upload failed: ${err.message}` } };
28
- }
29
- }
30
- async snapshot(scope, key, env, root, signal) {
31
- const flightKey = `${scope}\x00${key}`;
32
- if (this.inFlight.has(flightKey))
33
- return { ok: true };
34
- this.inFlight.add(flightKey);
35
- try {
36
- if (await this.has(scope, key))
37
- return { ok: true };
38
- let cap;
39
- try {
40
- cap = await captureManifest(env, root, this.bounds, signal, async (hash, bytes) => {
41
- await this.putBlobRow(hash, bytes);
42
- });
43
- }
44
- catch (err) {
45
- return { ok: false, error: { code: "restore_failed", message: `snapshot blob write failed: ${err.message}` } };
46
- }
47
- if (!cap.ok)
48
- return { ok: false, error: cap.error };
49
- if (cap.skippedVanished > 0 && this.onSkippedVanished) {
50
- try {
51
- void Promise.resolve(this.onSkippedVanished(cap.skippedVanished)).catch(() => { });
52
- }
53
- catch { }
54
- }
55
- await this.tx(async (conn) => {
56
- const [exists] = await conn.query("SELECT 1 FROM snapshot_manifest WHERE scope = ? AND snap_key = ? LIMIT 1", [scope, key]);
57
- if (exists[0])
58
- return;
59
- for (const [relPath, hash] of cap.value) {
60
- await conn.query("INSERT INTO snapshot_manifest (scope, snap_key, rel_path, blob_hash) VALUES (?,?,?,?)", [scope, key, relPath, hash]);
61
- }
62
- });
63
- return { ok: true };
64
- }
65
- catch (err) {
66
- return { ok: false, error: { code: "restore_failed", message: `snapshot persist failed: ${err.message}` } };
67
- }
68
- finally {
69
- this.inFlight.delete(flightKey);
70
- }
71
- }
72
- async importManifest(scope, key, manifest, srcGetBlob) {
73
- const flightKey = `${scope}\x00${key}`;
74
- if (this.inFlight.has(flightKey))
75
- return { ok: true };
76
- this.inFlight.add(flightKey);
77
- try {
78
- if (await this.has(scope, key))
79
- return { ok: true };
80
- for (const hash of new Set(manifest.values())) {
81
- let bytes;
82
- try {
83
- bytes = await srcGetBlob(hash);
84
- }
85
- catch (err) {
86
- return { ok: false, error: { code: "read_failed", message: `source blob ${hash} fetch failed: ${err.message}` } };
87
- }
88
- if (!bytes)
89
- return { ok: false, error: { code: "read_failed", message: `missing source blob ${hash}` } };
90
- if (createHash("sha256").update(bytes).digest("hex") !== hash) {
91
- return { ok: false, error: { code: "read_failed", message: `source blob ${hash} fails content-address integrity` } };
92
- }
93
- await this.putBlobRow(hash, bytes);
94
- }
95
- await this.tx(async (conn) => {
96
- const [exists] = await conn.query("SELECT 1 FROM snapshot_manifest WHERE scope = ? AND snap_key = ? LIMIT 1", [scope, key]);
97
- if (exists[0])
98
- return;
99
- for (const [relPath, hash] of manifest) {
100
- await conn.query("INSERT INTO snapshot_manifest (scope, snap_key, rel_path, blob_hash) VALUES (?,?,?,?)", [scope, key, relPath, hash]);
101
- }
102
- });
103
- return { ok: true };
104
- }
105
- catch (err) {
106
- return { ok: false, error: { code: "restore_failed", message: `import persist failed: ${err.message}` } };
107
- }
108
- finally {
109
- this.inFlight.delete(flightKey);
110
- }
111
- }
112
- async restore(scope, key, env, root, signal) {
113
- try {
114
- const [rows] = await this.pool.query("SELECT rel_path, blob_hash FROM snapshot_manifest WHERE scope = ? AND snap_key = ?", [scope, key]);
115
- if (rows.length === 0)
116
- return { ok: false, error: { code: "not_found", message: `no file snapshot for ${scope}/${key}` } };
117
- const manifest = new Map(rows.map((r) => [String(r.rel_path), String(r.blob_hash)]));
118
- return await applyManifest(env, root, this.bounds, signal, manifest, (hash) => this.blobs.getBlob(hash));
119
- }
120
- catch (err) {
121
- return { ok: false, error: { code: "restore_failed", message: `restore blob read failed: ${err.message}` } };
122
- }
123
- }
124
- async has(scope, key) {
125
- const [rows] = await this.pool.query("SELECT 1 FROM snapshot_manifest WHERE scope = ? AND snap_key = ? LIMIT 1", [scope, key]);
126
- return Boolean(rows[0]);
127
- }
128
- async listKeys(scope) {
129
- const [rows] = await this.pool.query("SELECT DISTINCT snap_key FROM snapshot_manifest WHERE scope = ?", [scope]);
130
- return rows.map((r) => String(r.snap_key));
131
- }
132
- async exportManifest(scope, key) {
133
- const [rows] = await this.pool.query("SELECT rel_path, blob_hash FROM snapshot_manifest WHERE scope = ? AND snap_key = ?", [scope, key]);
134
- if (rows.length === 0)
135
- return null;
136
- return new Map(rows.map((r) => [String(r.rel_path), String(r.blob_hash)]));
137
- }
138
- async getBlob(hash) {
139
- return this.blobs.getBlob(hash);
140
- }
141
- async hasBlobs(hashes) {
142
- return this.blobs.hasBlobs(hashes);
143
- }
144
- async blobSizes(hashes) {
145
- return sqlBlobSizes("tidb", this.pool, hashes);
146
- }
147
- async reap(scope, keepKeys) {
148
- return this.tx(async (conn) => {
149
- const [keys] = await conn.query("SELECT DISTINCT snap_key FROM snapshot_manifest WHERE scope = ?", [scope]);
150
- const drop = keys.map((k) => String(k.snap_key)).filter((k) => !keepKeys.includes(k));
151
- for (const k of drop)
152
- await conn.query("DELETE FROM snapshot_manifest WHERE scope = ? AND snap_key = ?", [scope, k]);
153
- return drop.length;
154
- });
155
- }
156
- async deleteBySession(scope) {
157
- const [r] = await this.pool.query("DELETE FROM snapshot_manifest WHERE scope = ?", [scope]);
158
- return r.affectedRows;
159
- }
160
- async gcOrphanBlobs() {
161
- const [rows] = await this.pool
162
- .query("SELECT blob_hash FROM snapshot_blob WHERE blob_hash NOT IN (SELECT blob_hash FROM snapshot_manifest)")
163
- .catch(() => [[]]);
164
- const orphans = rows.map((r) => String(r.blob_hash));
165
- if (orphans.length === 0)
166
- return 0;
167
- return this.blobs.deleteBlobs(orphans);
168
- }
169
- async sweepOrphanBlobs() {
170
- return this.gcOrphanBlobs();
171
- }
172
- async tx(fn) {
173
- const conn = await this.pool.getConnection();
174
- try {
175
- await conn.beginTransaction();
176
- const out = await fn(conn);
177
- await conn.commit();
178
- return out;
179
- }
180
- catch (err) {
181
- try {
182
- await conn.rollback();
183
- }
184
- catch {
185
- }
186
- throw err;
187
- }
188
- finally {
189
- conn.release();
190
- }
191
- }
192
- }
1
+ export { TiDBFileSnapshotStore } from "./file-snapshot-store-sql.js";
193
2
  //# sourceMappingURL=tidb-file-snapshot-store.js.map
@@ -1,22 +1,4 @@
1
- import type { Pool } from "mysql2/promise";
2
- import { type ImageStatus, type ImageIndexEntry, type ImageIndexUpsert, type ImageViewer, type ImageListFilter } from "./store-contracts.js";
1
+ export { TiDBImageIndex } from "./image-index-sql.js";
3
2
  export type { ImageNestedBuildMode, ImageCapabilities, ImagePodContract, ImageStatus, ImageVisibility, ImageIndexEntry, ImageIndexUpsert, ImageViewer, ImageListFilter, ImageRow, } from "./store-contracts.js";
4
3
  export { mapImageRow as mapRow } from "./store-contracts.js";
5
- export declare class TiDBImageIndex {
6
- private readonly pool;
7
- constructor(pool: Pool);
8
- static idFor(repo: string, digest: string): string;
9
- upsert(e: ImageIndexUpsert): Promise<string>;
10
- registerBuilding(e: ImageIndexUpsert): Promise<string>;
11
- getById(id: string): Promise<ImageIndexEntry | null>;
12
- getByDigest(digest: string): Promise<ImageIndexEntry | null>;
13
- latestPublished(profile: string, viewer: ImageViewer): Promise<ImageIndexEntry | null>;
14
- list(filter: ImageListFilter): Promise<{
15
- entries: ImageIndexEntry[];
16
- nextCursor: string | null;
17
- }>;
18
- setStatus(id: string, status: ImageStatus, opts?: {
19
- supersedes?: string | null;
20
- }): Promise<void>;
21
- }
22
4
  //# sourceMappingURL=tidb-image-index.d.ts.map
@@ -1,151 +1,3 @@
1
- import { createHash } from "node:crypto";
2
- import { mapImageRow as mapRow, } from "./store-contracts.js";
1
+ export { TiDBImageIndex } from "./image-index-sql.js";
3
2
  export { mapImageRow as mapRow } from "./store-contracts.js";
4
- const MAX_LIMIT = 200;
5
- const DEFAULT_LIMIT = 50;
6
- function visibilityClause(viewer) {
7
- if (viewer.operator)
8
- return { sql: "1=1", params: [] };
9
- if (viewer.tenantId)
10
- return { sql: "(visibility='public' OR tenant_id=?)", params: [viewer.tenantId] };
11
- return { sql: "visibility='public'", params: [] };
12
- }
13
- function encodeCursor(e) {
14
- return Buffer.from(`${e.createdAt}|${e.id}`, "utf8").toString("base64url");
15
- }
16
- function decodeCursor(c) {
17
- try {
18
- const [createdAt, id] = Buffer.from(c, "base64url").toString("utf8").split("|");
19
- if (!createdAt || !id)
20
- return null;
21
- return { createdAt, id };
22
- }
23
- catch {
24
- return null;
25
- }
26
- }
27
- export class TiDBImageIndex {
28
- pool;
29
- constructor(pool) {
30
- this.pool = pool;
31
- }
32
- static idFor(repo, digest) {
33
- return createHash("sha256").update(`${repo}@${digest}`).digest("hex").slice(0, 64);
34
- }
35
- async upsert(e) {
36
- const id = TiDBImageIndex.idFor(e.repo, e.digest);
37
- const now = new Date();
38
- await this.pool.query(`INSERT INTO sandbox_image_index
39
- (id, profile, bands, repo, tag, digest, toolchain_versions, capabilities, pod_contract, size_bytes,
40
- status, visibility, tenant_id, manifest_sha, recipe_git_sha, generator_version, build_date, supersedes,
41
- signed, created_at, updated_at)
42
- VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
43
- ON DUPLICATE KEY UPDATE
44
- profile=VALUES(profile), bands=VALUES(bands), tag=VALUES(tag), toolchain_versions=VALUES(toolchain_versions),
45
- capabilities=VALUES(capabilities), pod_contract=VALUES(pod_contract), size_bytes=VALUES(size_bytes),
46
- status=VALUES(status), visibility=VALUES(visibility), tenant_id=VALUES(tenant_id),
47
- manifest_sha=VALUES(manifest_sha), recipe_git_sha=VALUES(recipe_git_sha),
48
- generator_version=VALUES(generator_version), build_date=VALUES(build_date), supersedes=VALUES(supersedes),
49
- signed=VALUES(signed), updated_at=VALUES(updated_at)`, [
50
- id, e.profile, JSON.stringify(e.bands ?? []), e.repo, e.tag, e.digest,
51
- JSON.stringify(e.toolchainVersions ?? {}), JSON.stringify(e.capabilities ?? {}),
52
- JSON.stringify(e.podContract ?? {}), e.sizeBytes,
53
- e.status, e.visibility, e.tenantId ?? null, e.manifestSha ?? null, e.recipeGitSha ?? null,
54
- e.generatorVersion ?? null, e.buildDate ? new Date(e.buildDate) : null, e.supersedes ?? null,
55
- e.signed ? 1 : 0, now, now,
56
- ]);
57
- return id;
58
- }
59
- async registerBuilding(e) {
60
- const id = TiDBImageIndex.idFor(e.repo, e.digest);
61
- const now = new Date();
62
- await this.pool.query(`INSERT INTO sandbox_image_index
63
- (id, profile, bands, repo, tag, digest, toolchain_versions, capabilities, pod_contract, size_bytes,
64
- status, visibility, tenant_id, manifest_sha, recipe_git_sha, generator_version, build_date, supersedes,
65
- signed, created_at, updated_at)
66
- VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
67
- ON DUPLICATE KEY UPDATE
68
- profile=VALUES(profile), bands=VALUES(bands), tag=VALUES(tag), toolchain_versions=VALUES(toolchain_versions),
69
- capabilities=VALUES(capabilities), pod_contract=VALUES(pod_contract), size_bytes=VALUES(size_bytes),
70
- status=IF(sandbox_image_index.status='published', sandbox_image_index.status, VALUES(status)),
71
- visibility=IF(sandbox_image_index.status='published', sandbox_image_index.visibility, VALUES(visibility)),
72
- tenant_id=IF(sandbox_image_index.status='published', sandbox_image_index.tenant_id, VALUES(tenant_id)),
73
- manifest_sha=VALUES(manifest_sha), recipe_git_sha=VALUES(recipe_git_sha),
74
- generator_version=VALUES(generator_version), build_date=VALUES(build_date), supersedes=VALUES(supersedes),
75
- signed=IF(sandbox_image_index.status='published', sandbox_image_index.signed, VALUES(signed)), updated_at=VALUES(updated_at)`, [
76
- id, e.profile, JSON.stringify(e.bands ?? []), e.repo, e.tag, e.digest,
77
- JSON.stringify(e.toolchainVersions ?? {}), JSON.stringify(e.capabilities ?? {}),
78
- JSON.stringify(e.podContract ?? {}), e.sizeBytes,
79
- e.status, e.visibility, e.tenantId ?? null, e.manifestSha ?? null, e.recipeGitSha ?? null,
80
- e.generatorVersion ?? null, e.buildDate ? new Date(e.buildDate) : null, e.supersedes ?? null,
81
- e.signed ? 1 : 0, now, now,
82
- ]);
83
- return id;
84
- }
85
- async getById(id) {
86
- const [rows] = await this.pool.query(`SELECT * FROM sandbox_image_index WHERE id=? LIMIT 1`, [id]);
87
- return rows[0] ? mapRow(rows[0]) : null;
88
- }
89
- async getByDigest(digest) {
90
- const [rows] = await this.pool.query(`SELECT * FROM sandbox_image_index WHERE digest=? ORDER BY updated_at DESC LIMIT 1`, [digest]);
91
- return rows[0] ? mapRow(rows[0]) : null;
92
- }
93
- async latestPublished(profile, viewer) {
94
- const vis = visibilityClause(viewer);
95
- const [rows] = await this.pool.query(`SELECT * FROM sandbox_image_index
96
- WHERE profile=? AND status='published' AND ${vis.sql}
97
- ORDER BY (build_date IS NULL), build_date DESC, created_at DESC LIMIT 1`, [profile, ...vis.params]);
98
- return rows[0] ? mapRow(rows[0]) : null;
99
- }
100
- async list(filter) {
101
- const limit = Math.min(Math.max(1, filter.limit ?? DEFAULT_LIMIT), MAX_LIMIT);
102
- const vis = visibilityClause(filter);
103
- const where = [vis.sql];
104
- const params = [...vis.params];
105
- if (filter.profile) {
106
- where.push("profile=?");
107
- params.push(filter.profile);
108
- }
109
- if (filter.status) {
110
- where.push("status=?");
111
- params.push(filter.status);
112
- }
113
- if (filter.capability) {
114
- where.push("JSON_EXTRACT(capabilities, ?) = true");
115
- params.push(`$.${filter.capability}`);
116
- }
117
- if (filter.cursor) {
118
- const c = decodeCursor(filter.cursor);
119
- if (c) {
120
- where.push("(created_at < ? OR (created_at = ? AND id < ?))");
121
- params.push(new Date(c.createdAt), new Date(c.createdAt), c.id);
122
- }
123
- }
124
- const sql = `SELECT * FROM sandbox_image_index WHERE ${where.join(" AND ")} ` +
125
- `ORDER BY created_at DESC, id DESC LIMIT ?`;
126
- const [rows] = await this.pool.query(sql, [...params, limit + 1]);
127
- let entries = rows.map(mapRow);
128
- let nextCursor = null;
129
- if (entries.length > limit) {
130
- entries = entries.slice(0, limit);
131
- const last = entries[entries.length - 1];
132
- nextCursor = encodeCursor({ createdAt: last.createdAt, id: last.id });
133
- }
134
- if (filter.latestOnly) {
135
- const seen = new Set();
136
- entries = entries.filter((e) => (seen.has(e.profile) ? false : (seen.add(e.profile), true)));
137
- }
138
- return { entries, nextCursor };
139
- }
140
- async setStatus(id, status, opts) {
141
- const sets = ["status=?", "updated_at=?"];
142
- const params = [status, new Date()];
143
- if (opts && "supersedes" in opts) {
144
- sets.push("supersedes=?");
145
- params.push(opts.supersedes ?? null);
146
- }
147
- params.push(id);
148
- await this.pool.query(`UPDATE sandbox_image_index SET ${sets.join(", ")} WHERE id=?`, params);
149
- }
150
- }
151
3
  //# sourceMappingURL=tidb-image-index.js.map
@@ -1,58 +1,2 @@
1
- import type { Pool } from "mysql2/promise";
2
- import type { TaskOutcome as CoreTaskOutcome } from "@sema-agent/core";
3
- export interface MechanicalOutcome {
4
- route?: "single" | "fanout";
5
- workerCount?: number;
6
- oraclePassed?: number;
7
- oracleTotal?: number;
8
- assembleExit?: number;
9
- lintExit?: number;
10
- mergeOk?: boolean;
11
- replanTriggers?: string[];
12
- costMicroUsd?: number;
13
- turns?: number;
14
- }
15
- export interface LlmAssistedOutcome {
16
- stuckEvents?: number;
17
- verifier?: {
18
- verdict: string;
19
- confidence: number;
20
- };
21
- }
22
- export interface SignatureInputs {
23
- taskType?: string;
24
- toolset?: string[];
25
- targetLang?: string;
26
- moduleCount?: number;
27
- tag?: string;
28
- }
29
- export type RunStatus = "completed-graded" | "infra-aborted";
30
- export interface TaskOutcome {
31
- taskId?: string;
32
- model: string;
33
- runStatus?: RunStatus;
34
- signatureInputs: SignatureInputs;
35
- mechanical: MechanicalOutcome;
36
- llmAssisted?: LlmAssistedOutcome;
37
- core?: unknown;
38
- }
39
- export declare function taskSignature(s: SignatureInputs): string;
40
- export declare function deriveOutcome(m: MechanicalOutcome, runStatus?: RunStatus): "pass" | "partial" | "fail" | "aborted";
41
- export declare function coreOutcomeToLedgerRow(o: CoreTaskOutcome): TaskOutcome;
42
- export declare class TiDBOutcomeLedger {
43
- private readonly pool;
44
- constructor(pool: Pool);
45
- record(o: TaskOutcome): Promise<string>;
46
- recordCore(o: CoreTaskOutcome): Promise<void>;
47
- summary(opts?: {
48
- taskSignature?: string;
49
- includeAborted?: boolean;
50
- }): Promise<Array<{
51
- taskSignature: string;
52
- model: string;
53
- n: number;
54
- passRate: number;
55
- meanCostMicroUsd: number;
56
- }>>;
57
- }
1
+ export { TiDBOutcomeLedger, taskSignature, deriveOutcome, coreOutcomeToLedgerRow, type MechanicalOutcome, type LlmAssistedOutcome, type SignatureInputs, type RunStatus, type TaskOutcome, } from "./outcome-ledger-sql.js";
58
2
  //# sourceMappingURL=tidb-outcome-ledger.d.ts.map
@@ -1,98 +1,2 @@
1
- import { randomUUID } from "node:crypto";
2
- import { createHash } from "node:crypto";
3
- export function taskSignature(s) {
4
- if (s.tag)
5
- return `tag:${s.tag}`;
6
- const canon = JSON.stringify({
7
- taskType: s.taskType ?? "",
8
- toolset: [...(s.toolset ?? [])].sort(),
9
- targetLang: s.targetLang ?? "",
10
- moduleCount: s.moduleCount ?? 0,
11
- });
12
- return `h:${createHash("sha256").update(canon).digest("hex").slice(0, 16)}`;
13
- }
14
- export function deriveOutcome(m, runStatus = "completed-graded") {
15
- if (runStatus === "infra-aborted")
16
- return "aborted";
17
- const oracleGreen = m.oracleTotal != null && m.oracleTotal > 0 && m.oraclePassed === m.oracleTotal;
18
- const buildGreen = (m.assembleExit == null || m.assembleExit === 0) && (m.lintExit == null || m.lintExit === 0);
19
- const mergeGreen = m.mergeOk !== false;
20
- if (oracleGreen && buildGreen && mergeGreen)
21
- return "pass";
22
- const anyGreen = oracleGreen || (m.oraclePassed != null && m.oraclePassed > 0) || m.mergeOk === true;
23
- return anyGreen ? "partial" : "fail";
24
- }
25
- export function coreOutcomeToLedgerRow(o) {
26
- const passed = typeof o.oracle?.oraclePassed === "number" ? o.oracle.oraclePassed : o.oracle?.green ? 1 : 0;
27
- const total = typeof o.oracle?.oracleTotal === "number" ? o.oracle.oracleTotal : 1;
28
- return {
29
- taskId: o.runId.slice(0, 64),
30
- model: (o.model ?? "unknown").slice(0, 190),
31
- signatureInputs: {
32
- tag: o.taskSignature.slice(0, 186),
33
- ...(o.signatureInputs?.toolset ? { toolset: o.signatureInputs.toolset } : {}),
34
- ...(o.signatureInputs?.targetLang ? { targetLang: o.signatureInputs.targetLang } : {}),
35
- ...(o.signatureInputs?.moduleCount !== undefined ? { moduleCount: o.signatureInputs.moduleCount } : {}),
36
- },
37
- mechanical: {
38
- oraclePassed: passed,
39
- oracleTotal: total,
40
- ...(o.costMicroUsd !== undefined ? { costMicroUsd: o.costMicroUsd } : {}),
41
- ...(o.turns !== undefined ? { turns: o.turns } : {}),
42
- },
43
- core: o,
44
- };
45
- }
46
- export class TiDBOutcomeLedger {
47
- pool;
48
- constructor(pool) {
49
- this.pool = pool;
50
- }
51
- async record(o) {
52
- const id = randomUUID().replace(/-/g, "").slice(0, 32);
53
- const sig = taskSignature(o.signatureInputs);
54
- const m = o.mechanical;
55
- const runStatus = o.runStatus ?? "completed-graded";
56
- await this.pool.query(`INSERT INTO outcome_ledger
57
- (id, task_signature, model, task_id, run_status, route, worker_count, oracle_passed, oracle_total,
58
- assemble_exit, lint_exit, merge_ok, replan_triggers, cost_micro_usd, turns, outcome,
59
- llm_assisted, signature_inputs, core_outcome, created_at)
60
- VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`, [
61
- id, sig, o.model, o.taskId ?? null, runStatus, m.route ?? null, m.workerCount ?? null,
62
- m.oraclePassed ?? null, m.oracleTotal ?? null, m.assembleExit ?? null, m.lintExit ?? null,
63
- m.mergeOk == null ? null : m.mergeOk ? 1 : 0,
64
- m.replanTriggers ? JSON.stringify(m.replanTriggers) : null,
65
- m.costMicroUsd ?? null, m.turns ?? null, deriveOutcome(m, runStatus),
66
- o.llmAssisted ? JSON.stringify(o.llmAssisted) : null,
67
- JSON.stringify(o.signatureInputs), o.core != null ? JSON.stringify(o.core) : null, new Date(),
68
- ]);
69
- return id;
70
- }
71
- async recordCore(o) {
72
- await this.record(coreOutcomeToLedgerRow(o));
73
- }
74
- async summary(opts = {}) {
75
- const clauses = [];
76
- const params = [];
77
- if (!opts.includeAborted)
78
- clauses.push("run_status = 'completed-graded'");
79
- if (opts.taskSignature) {
80
- clauses.push("task_signature = ?");
81
- params.push(opts.taskSignature);
82
- }
83
- const where = clauses.length ? `WHERE ${clauses.join(" AND ")}` : "";
84
- const [rows] = await this.pool.query(`SELECT task_signature, model, COUNT(*) n,
85
- AVG(outcome = 'pass') pass_rate, AVG(cost_micro_usd) mean_cost
86
- FROM outcome_ledger ${where}
87
- GROUP BY task_signature, model
88
- ORDER BY task_signature, model`, params);
89
- return rows.map((r) => ({
90
- taskSignature: String(r.task_signature),
91
- model: String(r.model),
92
- n: Number(r.n),
93
- passRate: Number(r.pass_rate),
94
- meanCostMicroUsd: Number(r.mean_cost ?? 0),
95
- }));
96
- }
97
- }
1
+ export { TiDBOutcomeLedger, taskSignature, deriveOutcome, coreOutcomeToLedgerRow, } from "./outcome-ledger-sql.js";
98
2
  //# sourceMappingURL=tidb-outcome-ledger.js.map
@@ -1,14 +1,2 @@
1
- import type { Pool } from "mysql2/promise";
2
- export declare class TiDBResumeAnchorStore {
3
- private readonly pool;
4
- constructor(pool: Pool);
5
- put(sessionId: string, eventId: string, entryId: string, owner: string | null): Promise<void>;
6
- resolve(sessionId: string, eventId: string, owner: string | null): Promise<string | undefined>;
7
- listBySession(sessionId: string): Promise<Array<{
8
- eventId: string;
9
- entryId: string;
10
- owner: string | null;
11
- }>>;
12
- deleteBySession(sessionId: string): Promise<number>;
13
- }
1
+ export { TiDBResumeAnchorStore } from "./resume-anchor-store-sql.js";
14
2
  //# sourceMappingURL=tidb-resume-anchor-store.d.ts.map