@smithers-orchestrator/db 0.16.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/LICENSE +21 -0
- package/package.json +43 -0
- package/src/JsonBounds.ts +6 -0
- package/src/SchemaRegistryEntry.ts +6 -0
- package/src/SqlMessageStorage.js +818 -0
- package/src/SqlMessageStorageEventHistoryQuery.ts +7 -0
- package/src/SqliteWriteRetryOptions.ts +7 -0
- package/src/adapter/AlertRow.ts +29 -0
- package/src/adapter/AlertSeverity.ts +2 -0
- package/src/adapter/AlertStatus.ts +2 -0
- package/src/adapter/ApprovalRow.ts +13 -0
- package/src/adapter/AttemptRow.ts +17 -0
- package/src/adapter/CacheRow.ts +12 -0
- package/src/adapter/DB_ALERT_ALLOWED_SEVERITIES.js +5 -0
- package/src/adapter/DB_ALERT_ALLOWED_STATUSES.js +6 -0
- package/src/adapter/DB_ALERT_ID_MAX_LENGTH.js +1 -0
- package/src/adapter/DB_ALERT_MESSAGE_MAX_LENGTH.js +1 -0
- package/src/adapter/DB_ALERT_POLICY_NAME_MAX_LENGTH.js +1 -0
- package/src/adapter/DB_RUN_ALLOWED_STATUSES.js +10 -0
- package/src/adapter/DB_RUN_ID_MAX_LENGTH.js +1 -0
- package/src/adapter/DB_RUN_WORKFLOW_NAME_MAX_LENGTH.js +1 -0
- package/src/adapter/EventHistoryQuery.ts +7 -0
- package/src/adapter/HumanRequestRow.ts +19 -0
- package/src/adapter/NodeDiffCacheRow.ts +9 -0
- package/src/adapter/NodeRow.ts +10 -0
- package/src/adapter/PendingHumanRequestRow.ts +7 -0
- package/src/adapter/RunAncestryRow.ts +5 -0
- package/src/adapter/RunRow.ts +21 -0
- package/src/adapter/SignalQuery.ts +6 -0
- package/src/adapter/SignalRow.ts +9 -0
- package/src/adapter/SmithersDb.js +2236 -0
- package/src/adapter/StaleRunRecord.ts +7 -0
- package/src/adapter/index.js +27 -0
- package/src/adapter.js +2359 -0
- package/src/assertJsonPayloadWithinBounds.js +94 -0
- package/src/assertMaxBytes.js +23 -0
- package/src/assertMaxJsonDepth.js +40 -0
- package/src/assertMaxStringLength.js +16 -0
- package/src/assertOptionalArrayMaxLength.js +16 -0
- package/src/assertOptionalStringMaxLength.js +11 -0
- package/src/assertPositiveFiniteInteger.js +14 -0
- package/src/assertPositiveFiniteNumber.js +12 -0
- package/src/buildHumanRequestId.js +9 -0
- package/src/cache/nodeDiffCache.js +124 -0
- package/src/ensure.js +18 -0
- package/src/ensureSqlMessageStorage.js +11 -0
- package/src/ensureSqlMessageStorageEffect.js +12 -0
- package/src/frame-codec/FRAME_KEYFRAME_INTERVAL.js +1 -0
- package/src/frame-codec/FrameDelta.ts +6 -0
- package/src/frame-codec/FrameDeltaOp.ts +20 -0
- package/src/frame-codec/FrameEncoding.ts +1 -0
- package/src/frame-codec/JsonPath.ts +3 -0
- package/src/frame-codec/JsonPathSegment.ts +1 -0
- package/src/frame-codec/applyFrameDelta.js +143 -0
- package/src/frame-codec/applyFrameDeltaJson.js +10 -0
- package/src/frame-codec/encodeFrameDelta.js +247 -0
- package/src/frame-codec/index.js +15 -0
- package/src/frame-codec/normalizeFrameEncoding.js +13 -0
- package/src/frame-codec/parseFrameDelta.js +27 -0
- package/src/frame-codec/serializeFrameDelta.js +9 -0
- package/src/frame-codec.js +409 -0
- package/src/getSqlMessageStorage.js +11 -0
- package/src/index.d.ts +5203 -0
- package/src/index.js +20 -0
- package/src/input-bounds.js +12 -0
- package/src/input.js +17 -0
- package/src/internal-schema/index.js +19 -0
- package/src/internal-schema/smithersAlerts.js +27 -0
- package/src/internal-schema/smithersApprovals.js +18 -0
- package/src/internal-schema/smithersAttempts.js +20 -0
- package/src/internal-schema/smithersCache.js +13 -0
- package/src/internal-schema/smithersCron.js +11 -0
- package/src/internal-schema/smithersEvents.js +10 -0
- package/src/internal-schema/smithersFrames.js +14 -0
- package/src/internal-schema/smithersHumanRequests.js +17 -0
- package/src/internal-schema/smithersNodeDiffs.js +12 -0
- package/src/internal-schema/smithersNodes.js +13 -0
- package/src/internal-schema/smithersRalph.js +10 -0
- package/src/internal-schema/smithersRuns.js +22 -0
- package/src/internal-schema/smithersSandboxes.js +16 -0
- package/src/internal-schema/smithersSignals.js +12 -0
- package/src/internal-schema/smithersTimeTravelAudit.js +12 -0
- package/src/internal-schema/smithersToolCalls.js +19 -0
- package/src/internal-schema/smithersVectors.js +12 -0
- package/src/internal-schema.js +245 -0
- package/src/isRetryableSqliteWriteError.js +53 -0
- package/src/loadInputEffect.js +28 -0
- package/src/loadOutputsEffect.js +87 -0
- package/src/output/OutputKey.ts +1 -0
- package/src/output/buildKeyWhere.js +17 -0
- package/src/output/buildOutputRow.js +34 -0
- package/src/output/describeSchemaShape.js +70 -0
- package/src/output/getAgentOutputSchema.js +13 -0
- package/src/output/getKeyColumns.js +19 -0
- package/src/output/index.js +14 -0
- package/src/output/selectOutputRowEffect.js +30 -0
- package/src/output/stripAutoColumns.js +10 -0
- package/src/output/upsertOutputRowEffect.js +38 -0
- package/src/output/validateExistingOutput.js +17 -0
- package/src/output/validateOutput.js +17 -0
- package/src/output-schema-descriptor.js +163 -0
- package/src/output.js +240 -0
- package/src/react-output.js +10 -0
- package/src/runState/ComputeRunStateOptions.ts +4 -0
- package/src/runState/DeriveRunStateInput.ts +10 -0
- package/src/runState/RUN_STATE_HEARTBEAT_STALE_MS.js +1 -0
- package/src/runState/ReasonBlocked.ts +10 -0
- package/src/runState/ReasonUnhealthy.ts +6 -0
- package/src/runState/RunState.ts +12 -0
- package/src/runState/RunStateView.ts +11 -0
- package/src/runState/computeRunState.js +22 -0
- package/src/runState/computeRunStateFromRow.js +102 -0
- package/src/runState/deriveRunState.js +109 -0
- package/src/runState/parseEventMeta.js +18 -0
- package/src/runState/parseTimerMeta.js +16 -0
- package/src/runState-types.ts +23 -0
- package/src/runState.js +7 -0
- package/src/schema-signature.js +22 -0
- package/src/snapshot.js +125 -0
- package/src/sql-message-storage.js +839 -0
- package/src/storage/InMemoryStorage.js +484 -0
- package/src/storage/StorageService.js +7 -0
- package/src/storage/StorageServiceShape.ts +122 -0
- package/src/storage/StorageServiceTypes.ts +150 -0
- package/src/unwrapZodType.js +17 -0
- package/src/utils/camelToSnake.js +6 -0
- package/src/withSqliteWriteRetryEffect.js +110 -0
- package/src/write-retry.js +49 -0
- package/src/zodToCreateTableSQL.js +41 -0
- package/src/zodToTable.js +60 -0
package/src/snapshot.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { eq, getTableName } from "drizzle-orm";
|
|
2
|
+
import { getTableColumns } from "drizzle-orm/utils";
|
|
3
|
+
import { Effect, Option } from "effect";
|
|
4
|
+
import { toSmithersError } from "@smithers-orchestrator/errors/toSmithersError";
|
|
5
|
+
import { SmithersError } from "@smithers-orchestrator/errors/SmithersError";
|
|
6
|
+
/** @typedef {import("@smithers-orchestrator/driver/OutputSnapshot").OutputSnapshot} OutputSnapshot */
|
|
7
|
+
/** @typedef {import("drizzle-orm/bun-sqlite").BunSQLiteDatabase} BunSQLiteDatabase */
|
|
8
|
+
/** @typedef {import("drizzle-orm").Table} _Table */
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {_Table} table
|
|
12
|
+
* @returns {string[]}
|
|
13
|
+
*/
|
|
14
|
+
function getBooleanColumnKeys(table) {
|
|
15
|
+
try {
|
|
16
|
+
const cols = getTableColumns(table);
|
|
17
|
+
const keys = [];
|
|
18
|
+
for (const [key, col] of Object.entries(cols)) {
|
|
19
|
+
const c = /** @type {Record<string, unknown> & { config?: { mode?: string }; mapFromDriverValue?: unknown }} */ (/** @type {unknown} */ (col));
|
|
20
|
+
const mapFn = /** @type {{ toString?: () => string } | undefined} */ (c?.mapFromDriverValue);
|
|
21
|
+
if (c?.columnType === "SQLiteBoolean" || c?.config?.mode === "boolean" || c?.mode === "boolean" || mapFn?.toString?.().includes("Boolean") || (c?.dataType === "boolean")) {
|
|
22
|
+
keys.push(key);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return keys;
|
|
26
|
+
} catch {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* @param {ReadonlyArray<Record<string, unknown>>} rows
|
|
32
|
+
* @param {readonly string[]} boolKeys
|
|
33
|
+
* @returns {Array<Record<string, unknown>>}
|
|
34
|
+
*/
|
|
35
|
+
function coerceBooleanColumns(rows, boolKeys) {
|
|
36
|
+
if (boolKeys.length === 0) return rows.slice();
|
|
37
|
+
return rows.map((row) => {
|
|
38
|
+
if (!row) return row;
|
|
39
|
+
/** @type {Record<string, unknown>} */
|
|
40
|
+
const patched = { ...row };
|
|
41
|
+
for (const key of boolKeys) {
|
|
42
|
+
if (key in patched && typeof patched[key] !== "boolean") {
|
|
43
|
+
patched[key] = Boolean(patched[key]);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return patched;
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* @param {BunSQLiteDatabase<Record<string, unknown>>} db
|
|
51
|
+
* @param {_Table} inputTable
|
|
52
|
+
* @param {string} runId
|
|
53
|
+
* @returns {Effect.Effect<Record<string, unknown> | undefined, SmithersError>}
|
|
54
|
+
*/
|
|
55
|
+
export function loadInputEffect(db, inputTable, runId) {
|
|
56
|
+
const cols = getTableColumns(inputTable);
|
|
57
|
+
const runIdCol = cols.runId;
|
|
58
|
+
if (!runIdCol) {
|
|
59
|
+
throw new SmithersError("DB_MISSING_COLUMNS", "schema.input must include runId column");
|
|
60
|
+
}
|
|
61
|
+
return Effect.tryPromise({
|
|
62
|
+
try: () => db.select().from(inputTable).where(eq(runIdCol, runId)).limit(1),
|
|
63
|
+
catch: (cause) => toSmithersError(cause, "load input", {
|
|
64
|
+
code: "DB_QUERY_FAILED",
|
|
65
|
+
details: { runId },
|
|
66
|
+
}),
|
|
67
|
+
}).pipe(Effect.map((rows) => rows[0]), Effect.annotateLogs({ runId }), Effect.withLogSpan("db:load-input"));
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* @param {BunSQLiteDatabase<Record<string, unknown>>} db
|
|
71
|
+
* @param {_Table} inputTable
|
|
72
|
+
* @param {string} runId
|
|
73
|
+
* @returns {Promise<Record<string, unknown> | undefined>}
|
|
74
|
+
*/
|
|
75
|
+
export function loadInput(db, inputTable, runId) {
|
|
76
|
+
return Effect.runPromise(loadInputEffect(db, inputTable, runId));
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* @param {BunSQLiteDatabase<Record<string, unknown>>} db
|
|
80
|
+
* @param {Record<string, _Table | unknown>} schema
|
|
81
|
+
* @param {string} runId
|
|
82
|
+
* @returns {Effect.Effect<OutputSnapshot, SmithersError>}
|
|
83
|
+
*/
|
|
84
|
+
export function loadOutputsEffect(db, schema, runId) {
|
|
85
|
+
return Effect.gen(function* () {
|
|
86
|
+
/** @type {Record<string, ReadonlyArray<Record<string, unknown>>>} */
|
|
87
|
+
const out = {};
|
|
88
|
+
for (const [key, table] of Object.entries(schema)) {
|
|
89
|
+
if (!table || typeof table !== "object") continue;
|
|
90
|
+
if (key === "input") continue;
|
|
91
|
+
const colsOpt = yield* Effect.try({
|
|
92
|
+
try: () => getTableColumns(/** @type {_Table} */ (table)),
|
|
93
|
+
catch: (cause) => toSmithersError(cause, "get table columns", { code: "DB_QUERY_FAILED", details: { runId, schemaKey: key } }),
|
|
94
|
+
}).pipe(Effect.option);
|
|
95
|
+
if (Option.isNone(colsOpt)) continue;
|
|
96
|
+
const cols = colsOpt.value;
|
|
97
|
+
const runIdCol = cols.runId;
|
|
98
|
+
if (!runIdCol) continue;
|
|
99
|
+
const tableNameOpt = yield* Effect.try({
|
|
100
|
+
try: () => getTableName(/** @type {_Table} */ (table)),
|
|
101
|
+
catch: (cause) => toSmithersError(cause, "get table name", { code: "DB_QUERY_FAILED", details: { runId, schemaKey: key } }),
|
|
102
|
+
}).pipe(Effect.option);
|
|
103
|
+
if (Option.isNone(tableNameOpt)) continue;
|
|
104
|
+
const tableName = tableNameOpt.value;
|
|
105
|
+
const rawRows = yield* Effect.tryPromise({
|
|
106
|
+
try: () => db.select().from(/** @type {_Table} */ (table)).where(eq(runIdCol, runId)),
|
|
107
|
+
catch: (cause) => toSmithersError(cause, `load outputs ${tableName}`, { code: "DB_QUERY_FAILED", details: { runId, tableName } }),
|
|
108
|
+
});
|
|
109
|
+
const boolKeys = getBooleanColumnKeys(/** @type {_Table} */ (table));
|
|
110
|
+
const rows = coerceBooleanColumns(rawRows, boolKeys);
|
|
111
|
+
out[tableName] = rows;
|
|
112
|
+
out[key] = rows;
|
|
113
|
+
}
|
|
114
|
+
return /** @type {OutputSnapshot} */ (/** @type {unknown} */ (out));
|
|
115
|
+
}).pipe(Effect.annotateLogs({ runId }), Effect.withLogSpan("db:load-outputs"));
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* @param {BunSQLiteDatabase<Record<string, unknown>>} db
|
|
119
|
+
* @param {Record<string, _Table | unknown>} schema
|
|
120
|
+
* @param {string} runId
|
|
121
|
+
* @returns {Promise<OutputSnapshot>}
|
|
122
|
+
*/
|
|
123
|
+
export function loadOutputs(db, schema, runId) {
|
|
124
|
+
return Effect.runPromise(loadOutputsEffect(db, schema, runId));
|
|
125
|
+
}
|