@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.
Files changed (130) hide show
  1. package/LICENSE +21 -0
  2. package/package.json +43 -0
  3. package/src/JsonBounds.ts +6 -0
  4. package/src/SchemaRegistryEntry.ts +6 -0
  5. package/src/SqlMessageStorage.js +818 -0
  6. package/src/SqlMessageStorageEventHistoryQuery.ts +7 -0
  7. package/src/SqliteWriteRetryOptions.ts +7 -0
  8. package/src/adapter/AlertRow.ts +29 -0
  9. package/src/adapter/AlertSeverity.ts +2 -0
  10. package/src/adapter/AlertStatus.ts +2 -0
  11. package/src/adapter/ApprovalRow.ts +13 -0
  12. package/src/adapter/AttemptRow.ts +17 -0
  13. package/src/adapter/CacheRow.ts +12 -0
  14. package/src/adapter/DB_ALERT_ALLOWED_SEVERITIES.js +5 -0
  15. package/src/adapter/DB_ALERT_ALLOWED_STATUSES.js +6 -0
  16. package/src/adapter/DB_ALERT_ID_MAX_LENGTH.js +1 -0
  17. package/src/adapter/DB_ALERT_MESSAGE_MAX_LENGTH.js +1 -0
  18. package/src/adapter/DB_ALERT_POLICY_NAME_MAX_LENGTH.js +1 -0
  19. package/src/adapter/DB_RUN_ALLOWED_STATUSES.js +10 -0
  20. package/src/adapter/DB_RUN_ID_MAX_LENGTH.js +1 -0
  21. package/src/adapter/DB_RUN_WORKFLOW_NAME_MAX_LENGTH.js +1 -0
  22. package/src/adapter/EventHistoryQuery.ts +7 -0
  23. package/src/adapter/HumanRequestRow.ts +19 -0
  24. package/src/adapter/NodeDiffCacheRow.ts +9 -0
  25. package/src/adapter/NodeRow.ts +10 -0
  26. package/src/adapter/PendingHumanRequestRow.ts +7 -0
  27. package/src/adapter/RunAncestryRow.ts +5 -0
  28. package/src/adapter/RunRow.ts +21 -0
  29. package/src/adapter/SignalQuery.ts +6 -0
  30. package/src/adapter/SignalRow.ts +9 -0
  31. package/src/adapter/SmithersDb.js +2236 -0
  32. package/src/adapter/StaleRunRecord.ts +7 -0
  33. package/src/adapter/index.js +27 -0
  34. package/src/adapter.js +2359 -0
  35. package/src/assertJsonPayloadWithinBounds.js +94 -0
  36. package/src/assertMaxBytes.js +23 -0
  37. package/src/assertMaxJsonDepth.js +40 -0
  38. package/src/assertMaxStringLength.js +16 -0
  39. package/src/assertOptionalArrayMaxLength.js +16 -0
  40. package/src/assertOptionalStringMaxLength.js +11 -0
  41. package/src/assertPositiveFiniteInteger.js +14 -0
  42. package/src/assertPositiveFiniteNumber.js +12 -0
  43. package/src/buildHumanRequestId.js +9 -0
  44. package/src/cache/nodeDiffCache.js +124 -0
  45. package/src/ensure.js +18 -0
  46. package/src/ensureSqlMessageStorage.js +11 -0
  47. package/src/ensureSqlMessageStorageEffect.js +12 -0
  48. package/src/frame-codec/FRAME_KEYFRAME_INTERVAL.js +1 -0
  49. package/src/frame-codec/FrameDelta.ts +6 -0
  50. package/src/frame-codec/FrameDeltaOp.ts +20 -0
  51. package/src/frame-codec/FrameEncoding.ts +1 -0
  52. package/src/frame-codec/JsonPath.ts +3 -0
  53. package/src/frame-codec/JsonPathSegment.ts +1 -0
  54. package/src/frame-codec/applyFrameDelta.js +143 -0
  55. package/src/frame-codec/applyFrameDeltaJson.js +10 -0
  56. package/src/frame-codec/encodeFrameDelta.js +247 -0
  57. package/src/frame-codec/index.js +15 -0
  58. package/src/frame-codec/normalizeFrameEncoding.js +13 -0
  59. package/src/frame-codec/parseFrameDelta.js +27 -0
  60. package/src/frame-codec/serializeFrameDelta.js +9 -0
  61. package/src/frame-codec.js +409 -0
  62. package/src/getSqlMessageStorage.js +11 -0
  63. package/src/index.d.ts +5203 -0
  64. package/src/index.js +20 -0
  65. package/src/input-bounds.js +12 -0
  66. package/src/input.js +17 -0
  67. package/src/internal-schema/index.js +19 -0
  68. package/src/internal-schema/smithersAlerts.js +27 -0
  69. package/src/internal-schema/smithersApprovals.js +18 -0
  70. package/src/internal-schema/smithersAttempts.js +20 -0
  71. package/src/internal-schema/smithersCache.js +13 -0
  72. package/src/internal-schema/smithersCron.js +11 -0
  73. package/src/internal-schema/smithersEvents.js +10 -0
  74. package/src/internal-schema/smithersFrames.js +14 -0
  75. package/src/internal-schema/smithersHumanRequests.js +17 -0
  76. package/src/internal-schema/smithersNodeDiffs.js +12 -0
  77. package/src/internal-schema/smithersNodes.js +13 -0
  78. package/src/internal-schema/smithersRalph.js +10 -0
  79. package/src/internal-schema/smithersRuns.js +22 -0
  80. package/src/internal-schema/smithersSandboxes.js +16 -0
  81. package/src/internal-schema/smithersSignals.js +12 -0
  82. package/src/internal-schema/smithersTimeTravelAudit.js +12 -0
  83. package/src/internal-schema/smithersToolCalls.js +19 -0
  84. package/src/internal-schema/smithersVectors.js +12 -0
  85. package/src/internal-schema.js +245 -0
  86. package/src/isRetryableSqliteWriteError.js +53 -0
  87. package/src/loadInputEffect.js +28 -0
  88. package/src/loadOutputsEffect.js +87 -0
  89. package/src/output/OutputKey.ts +1 -0
  90. package/src/output/buildKeyWhere.js +17 -0
  91. package/src/output/buildOutputRow.js +34 -0
  92. package/src/output/describeSchemaShape.js +70 -0
  93. package/src/output/getAgentOutputSchema.js +13 -0
  94. package/src/output/getKeyColumns.js +19 -0
  95. package/src/output/index.js +14 -0
  96. package/src/output/selectOutputRowEffect.js +30 -0
  97. package/src/output/stripAutoColumns.js +10 -0
  98. package/src/output/upsertOutputRowEffect.js +38 -0
  99. package/src/output/validateExistingOutput.js +17 -0
  100. package/src/output/validateOutput.js +17 -0
  101. package/src/output-schema-descriptor.js +163 -0
  102. package/src/output.js +240 -0
  103. package/src/react-output.js +10 -0
  104. package/src/runState/ComputeRunStateOptions.ts +4 -0
  105. package/src/runState/DeriveRunStateInput.ts +10 -0
  106. package/src/runState/RUN_STATE_HEARTBEAT_STALE_MS.js +1 -0
  107. package/src/runState/ReasonBlocked.ts +10 -0
  108. package/src/runState/ReasonUnhealthy.ts +6 -0
  109. package/src/runState/RunState.ts +12 -0
  110. package/src/runState/RunStateView.ts +11 -0
  111. package/src/runState/computeRunState.js +22 -0
  112. package/src/runState/computeRunStateFromRow.js +102 -0
  113. package/src/runState/deriveRunState.js +109 -0
  114. package/src/runState/parseEventMeta.js +18 -0
  115. package/src/runState/parseTimerMeta.js +16 -0
  116. package/src/runState-types.ts +23 -0
  117. package/src/runState.js +7 -0
  118. package/src/schema-signature.js +22 -0
  119. package/src/snapshot.js +125 -0
  120. package/src/sql-message-storage.js +839 -0
  121. package/src/storage/InMemoryStorage.js +484 -0
  122. package/src/storage/StorageService.js +7 -0
  123. package/src/storage/StorageServiceShape.ts +122 -0
  124. package/src/storage/StorageServiceTypes.ts +150 -0
  125. package/src/unwrapZodType.js +17 -0
  126. package/src/utils/camelToSnake.js +6 -0
  127. package/src/withSqliteWriteRetryEffect.js +110 -0
  128. package/src/write-retry.js +49 -0
  129. package/src/zodToCreateTableSQL.js +41 -0
  130. 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
+ }
@@ -0,0 +1,9 @@
1
+
2
+ /** @typedef {import("./FrameDelta.ts").FrameDelta} FrameDelta */
3
+ /**
4
+ * @param {FrameDelta} delta
5
+ * @returns {string}
6
+ */
7
+ export function serializeFrameDelta(delta) {
8
+ return JSON.stringify(delta);
9
+ }