@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
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { parseXmlJson } from "@smithers-orchestrator/graph/utils/xml";
|
|
2
|
+
/** @typedef {import("./FrameDeltaOp.ts").FrameDeltaOp} FrameDeltaOp */
|
|
3
|
+
/** @typedef {import("./JsonPath.ts").JsonPath} JsonPath */
|
|
4
|
+
|
|
5
|
+
/** @typedef {import("./FrameDelta.ts").FrameDelta} FrameDelta */
|
|
6
|
+
|
|
7
|
+
const FRAME_DELTA_VERSION = 1;
|
|
8
|
+
/**
|
|
9
|
+
* @param {string} previousXmlJson
|
|
10
|
+
* @param {string} nextXmlJson
|
|
11
|
+
* @returns {FrameDelta}
|
|
12
|
+
*/
|
|
13
|
+
export function encodeFrameDelta(previousXmlJson, nextXmlJson) {
|
|
14
|
+
const prev = parseXmlJson(previousXmlJson);
|
|
15
|
+
const next = parseXmlJson(nextXmlJson);
|
|
16
|
+
const ops = [];
|
|
17
|
+
diffValues(prev, next, [], ops, null);
|
|
18
|
+
return {
|
|
19
|
+
version: FRAME_DELTA_VERSION,
|
|
20
|
+
ops,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* @param {unknown} prev
|
|
25
|
+
* @param {unknown} next
|
|
26
|
+
* @param {JsonPath} path
|
|
27
|
+
* @param {FrameDeltaOp[]} ops
|
|
28
|
+
* @param {string | null} currentNodeId
|
|
29
|
+
*/
|
|
30
|
+
function diffValues(prev, next, path, ops, currentNodeId) {
|
|
31
|
+
if (deepEqual(prev, next))
|
|
32
|
+
return;
|
|
33
|
+
if (prev === undefined && next !== undefined) {
|
|
34
|
+
pushSet(ops, path, next, currentNodeId);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (next === undefined) {
|
|
38
|
+
pushRemove(ops, path, currentNodeId);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const prevIsObj = isRecord(prev);
|
|
42
|
+
const nextIsObj = isRecord(next);
|
|
43
|
+
if (Array.isArray(prev) && Array.isArray(next)) {
|
|
44
|
+
diffArrays(prev, next, path, ops, currentNodeId);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (prevIsObj && nextIsObj) {
|
|
48
|
+
const nodeId = inferNodeId(next, inferNodeId(prev, currentNodeId));
|
|
49
|
+
diffObjects(prev, next, path, ops, nodeId);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
pushSet(ops, path, next, currentNodeId);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* @param {Record<string, unknown>} prev
|
|
56
|
+
* @param {Record<string, unknown>} next
|
|
57
|
+
* @param {JsonPath} path
|
|
58
|
+
* @param {FrameDeltaOp[]} ops
|
|
59
|
+
* @param {string | null} currentNodeId
|
|
60
|
+
*/
|
|
61
|
+
function diffObjects(prev, next, path, ops, currentNodeId) {
|
|
62
|
+
const keys = Array.from(new Set([...Object.keys(prev), ...Object.keys(next)])).sort();
|
|
63
|
+
for (const key of keys) {
|
|
64
|
+
const hasPrev = Object.prototype.hasOwnProperty.call(prev, key);
|
|
65
|
+
const hasNext = Object.prototype.hasOwnProperty.call(next, key);
|
|
66
|
+
const nextPath = [...path, key];
|
|
67
|
+
if (!hasNext && hasPrev) {
|
|
68
|
+
pushRemove(ops, nextPath, currentNodeId);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (hasNext && !hasPrev) {
|
|
72
|
+
pushSet(ops, nextPath, next[key], currentNodeId);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
diffValues(prev[key], next[key], nextPath, ops, currentNodeId);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* @param {unknown[]} prev
|
|
80
|
+
* @param {unknown[]} next
|
|
81
|
+
* @param {JsonPath} path
|
|
82
|
+
* @param {FrameDeltaOp[]} ops
|
|
83
|
+
* @param {string | null} currentNodeId
|
|
84
|
+
*/
|
|
85
|
+
function diffArrays(prev, next, path, ops, currentNodeId) {
|
|
86
|
+
let start = 0;
|
|
87
|
+
while (start < prev.length && start < next.length && deepEqual(prev[start], next[start])) {
|
|
88
|
+
start += 1;
|
|
89
|
+
}
|
|
90
|
+
let prevEnd = prev.length - 1;
|
|
91
|
+
let nextEnd = next.length - 1;
|
|
92
|
+
while (prevEnd >= start && nextEnd >= start && deepEqual(prev[prevEnd], next[nextEnd])) {
|
|
93
|
+
prevEnd -= 1;
|
|
94
|
+
nextEnd -= 1;
|
|
95
|
+
}
|
|
96
|
+
const prevCount = prevEnd - start + 1;
|
|
97
|
+
const nextCount = nextEnd - start + 1;
|
|
98
|
+
if (prevCount <= 0 && nextCount <= 0) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (prevCount <= 0) {
|
|
102
|
+
for (let i = 0; i < nextCount; i += 1) {
|
|
103
|
+
pushInsert(ops, [...path, start + i], next[start + i], currentNodeId);
|
|
104
|
+
}
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (nextCount <= 0) {
|
|
108
|
+
for (let i = prevEnd; i >= start; i -= 1) {
|
|
109
|
+
pushRemove(ops, [...path, i], currentNodeId);
|
|
110
|
+
}
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (prevCount === nextCount) {
|
|
114
|
+
for (let i = 0; i < prevCount; i += 1) {
|
|
115
|
+
const prevValue = prev[start + i];
|
|
116
|
+
const nextValue = next[start + i];
|
|
117
|
+
const childNodeId = inferNodeId(nextValue, inferNodeId(prevValue, currentNodeId));
|
|
118
|
+
diffValues(prevValue, nextValue, [...path, start + i], ops, childNodeId);
|
|
119
|
+
}
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
for (let i = prevEnd; i >= start; i -= 1) {
|
|
123
|
+
pushRemove(ops, [...path, i], currentNodeId);
|
|
124
|
+
}
|
|
125
|
+
for (let i = 0; i < nextCount; i += 1) {
|
|
126
|
+
pushInsert(ops, [...path, start + i], next[start + i], currentNodeId);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* @param {FrameDeltaOp[]} ops
|
|
131
|
+
* @param {JsonPath} path
|
|
132
|
+
* @param {unknown} value
|
|
133
|
+
* @param {string | null} nodeId
|
|
134
|
+
*/
|
|
135
|
+
function pushSet(ops, path, value, nodeId) {
|
|
136
|
+
const op = {
|
|
137
|
+
op: "set",
|
|
138
|
+
path,
|
|
139
|
+
value: cloneValue(value),
|
|
140
|
+
...(nodeId ? { nodeId } : {}),
|
|
141
|
+
};
|
|
142
|
+
ops.push(op);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* @param {FrameDeltaOp[]} ops
|
|
146
|
+
* @param {JsonPath} path
|
|
147
|
+
* @param {unknown} value
|
|
148
|
+
* @param {string | null} nodeId
|
|
149
|
+
*/
|
|
150
|
+
function pushInsert(ops, path, value, nodeId) {
|
|
151
|
+
const op = {
|
|
152
|
+
op: "insert",
|
|
153
|
+
path,
|
|
154
|
+
value: cloneValue(value),
|
|
155
|
+
...(nodeId ? { nodeId } : {}),
|
|
156
|
+
};
|
|
157
|
+
ops.push(op);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* @param {FrameDeltaOp[]} ops
|
|
161
|
+
* @param {JsonPath} path
|
|
162
|
+
* @param {string | null} nodeId
|
|
163
|
+
*/
|
|
164
|
+
function pushRemove(ops, path, nodeId) {
|
|
165
|
+
const op = {
|
|
166
|
+
op: "remove",
|
|
167
|
+
path,
|
|
168
|
+
...(nodeId ? { nodeId } : {}),
|
|
169
|
+
};
|
|
170
|
+
ops.push(op);
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* @param {unknown} value
|
|
174
|
+
* @param {string | null} fallback
|
|
175
|
+
* @returns {string | null}
|
|
176
|
+
*/
|
|
177
|
+
function inferNodeId(value, fallback) {
|
|
178
|
+
if (!isRecord(value))
|
|
179
|
+
return fallback;
|
|
180
|
+
if (value.kind !== "element")
|
|
181
|
+
return fallback;
|
|
182
|
+
const props = value.props;
|
|
183
|
+
if (!isRecord(props))
|
|
184
|
+
return fallback;
|
|
185
|
+
const id = props.id;
|
|
186
|
+
return typeof id === "string" && id.length > 0 ? id : fallback;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* @param {unknown} a
|
|
190
|
+
* @param {unknown} b
|
|
191
|
+
* @returns {boolean}
|
|
192
|
+
*/
|
|
193
|
+
function deepEqual(a, b) {
|
|
194
|
+
if (Object.is(a, b))
|
|
195
|
+
return true;
|
|
196
|
+
if (typeof a !== typeof b)
|
|
197
|
+
return false;
|
|
198
|
+
if (a === null || b === null)
|
|
199
|
+
return a === b;
|
|
200
|
+
if (Array.isArray(a) || Array.isArray(b)) {
|
|
201
|
+
if (!Array.isArray(a) || !Array.isArray(b))
|
|
202
|
+
return false;
|
|
203
|
+
if (a.length !== b.length)
|
|
204
|
+
return false;
|
|
205
|
+
for (let i = 0; i < a.length; i += 1) {
|
|
206
|
+
if (!deepEqual(a[i], b[i]))
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
if (isRecord(a) || isRecord(b)) {
|
|
212
|
+
if (!isRecord(a) || !isRecord(b))
|
|
213
|
+
return false;
|
|
214
|
+
const keysA = Object.keys(a).sort();
|
|
215
|
+
const keysB = Object.keys(b).sort();
|
|
216
|
+
if (keysA.length !== keysB.length)
|
|
217
|
+
return false;
|
|
218
|
+
for (let i = 0; i < keysA.length; i += 1) {
|
|
219
|
+
if (keysA[i] !== keysB[i])
|
|
220
|
+
return false;
|
|
221
|
+
const key = keysA[i];
|
|
222
|
+
if (!deepEqual(a[key], b[key]))
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
return true;
|
|
226
|
+
}
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* @param {unknown} value
|
|
231
|
+
* @returns {value is Record<string, unknown>}
|
|
232
|
+
*/
|
|
233
|
+
function isRecord(value) {
|
|
234
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* @template T
|
|
238
|
+
* @param {T} value
|
|
239
|
+
* @returns {T}
|
|
240
|
+
*/
|
|
241
|
+
function cloneValue(value) {
|
|
242
|
+
if (value === null)
|
|
243
|
+
return value;
|
|
244
|
+
if (typeof value !== "object")
|
|
245
|
+
return value;
|
|
246
|
+
return JSON.parse(JSON.stringify(value));
|
|
247
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// @smithers-type-exports-begin
|
|
2
|
+
/** @typedef {import("./FrameDelta.ts").FrameDelta} FrameDelta */
|
|
3
|
+
/** @typedef {import("./FrameDeltaOp.ts").FrameDeltaOp} FrameDeltaOp */
|
|
4
|
+
/** @typedef {import("./FrameEncoding.ts").FrameEncoding} FrameEncoding */
|
|
5
|
+
/** @typedef {import("./JsonPath.ts").JsonPath} JsonPath */
|
|
6
|
+
/** @typedef {import("./JsonPathSegment.ts").JsonPathSegment} JsonPathSegment */
|
|
7
|
+
// @smithers-type-exports-end
|
|
8
|
+
|
|
9
|
+
export { FRAME_KEYFRAME_INTERVAL } from "./FRAME_KEYFRAME_INTERVAL.js";
|
|
10
|
+
export { normalizeFrameEncoding } from "./normalizeFrameEncoding.js";
|
|
11
|
+
export { parseFrameDelta } from "./parseFrameDelta.js";
|
|
12
|
+
export { serializeFrameDelta } from "./serializeFrameDelta.js";
|
|
13
|
+
export { encodeFrameDelta } from "./encodeFrameDelta.js";
|
|
14
|
+
export { applyFrameDelta } from "./applyFrameDelta.js";
|
|
15
|
+
export { applyFrameDeltaJson } from "./applyFrameDeltaJson.js";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
|
|
2
|
+
/** @typedef {import("./FrameEncoding.ts").FrameEncoding} FrameEncoding */
|
|
3
|
+
/**
|
|
4
|
+
* @param {unknown} value
|
|
5
|
+
* @returns {FrameEncoding}
|
|
6
|
+
*/
|
|
7
|
+
export function normalizeFrameEncoding(value) {
|
|
8
|
+
if (value === "delta")
|
|
9
|
+
return "delta";
|
|
10
|
+
if (value === "keyframe")
|
|
11
|
+
return "keyframe";
|
|
12
|
+
return "full";
|
|
13
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
|
|
2
|
+
/** @typedef {import("./FrameDelta.ts").FrameDelta} FrameDelta */
|
|
3
|
+
const FRAME_DELTA_VERSION = 1;
|
|
4
|
+
/**
|
|
5
|
+
* @param {string} deltaJson
|
|
6
|
+
* @returns {FrameDelta}
|
|
7
|
+
*/
|
|
8
|
+
export function parseFrameDelta(deltaJson) {
|
|
9
|
+
const parsed = JSON.parse(deltaJson);
|
|
10
|
+
if (!isRecord(parsed)) {
|
|
11
|
+
throw new Error("Invalid frame delta payload (not an object)");
|
|
12
|
+
}
|
|
13
|
+
if (parsed.version !== FRAME_DELTA_VERSION) {
|
|
14
|
+
throw new Error(`Unsupported frame delta version: ${String(parsed.version)}`);
|
|
15
|
+
}
|
|
16
|
+
if (!Array.isArray(parsed.ops)) {
|
|
17
|
+
throw new Error("Invalid frame delta payload (missing ops array)");
|
|
18
|
+
}
|
|
19
|
+
return parsed;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* @param {unknown} value
|
|
23
|
+
* @returns {value is Record<string, unknown>}
|
|
24
|
+
*/
|
|
25
|
+
function isRecord(value) {
|
|
26
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
27
|
+
}
|