@sixb/core 0.1.2 → 0.1.4

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 (383) hide show
  1. package/dist/actions/index.js +19 -17
  2. package/dist/actions/index.js.map +1 -1
  3. package/dist/actions/worker.js +4 -4
  4. package/dist/actions/worker.js.map +1 -1
  5. package/dist/agents/adapters.d.ts +11 -1
  6. package/dist/agents/adapters.d.ts.map +1 -1
  7. package/dist/agents/context-compaction.d.ts +40 -0
  8. package/dist/agents/context-compaction.d.ts.map +1 -0
  9. package/dist/agents/context.js +1 -1
  10. package/dist/agents/errors.d.ts +1 -1
  11. package/dist/agents/errors.d.ts.map +1 -1
  12. package/dist/agents/execution.d.ts +3 -0
  13. package/dist/agents/execution.d.ts.map +1 -1
  14. package/dist/agents/ids.d.ts +2 -0
  15. package/dist/agents/ids.d.ts.map +1 -1
  16. package/dist/agents/index.d.ts +10 -6
  17. package/dist/agents/index.d.ts.map +1 -1
  18. package/dist/agents/index.js +51 -35
  19. package/dist/agents/index.js.map +1 -1
  20. package/dist/agents/request.d.ts.map +1 -1
  21. package/dist/agents/streams.d.ts +17 -1
  22. package/dist/agents/streams.d.ts.map +1 -1
  23. package/dist/agents/streams.js +5 -3
  24. package/dist/agents/streams.js.map +1 -1
  25. package/dist/agents/thread-context-projection.d.ts +19 -0
  26. package/dist/agents/thread-context-projection.d.ts.map +1 -0
  27. package/dist/agents/tool-definition.d.ts.map +1 -1
  28. package/dist/agents/tool-result.d.ts +6 -0
  29. package/dist/agents/tool-result.d.ts.map +1 -0
  30. package/dist/agents/types.d.ts +46 -1
  31. package/dist/agents/types.d.ts.map +1 -1
  32. package/dist/agents/validation.d.ts +2 -2
  33. package/dist/agents/validation.d.ts.map +1 -1
  34. package/dist/auth/index.js +11 -5
  35. package/dist/auth/index.js.map +1 -1
  36. package/dist/authorization/index.js +6 -2
  37. package/dist/authorization/index.js.map +1 -1
  38. package/dist/bootstrap/index.js +33 -31
  39. package/dist/bootstrap/index.js.map +1 -1
  40. package/dist/{chunk-ys1nse2v.js → chunk-1wk20wn3.js} +438 -246
  41. package/dist/{chunk-ys1nse2v.js.map → chunk-1wk20wn3.js.map} +11 -11
  42. package/dist/{chunk-sa4340y1.js → chunk-1yz3x65y.js} +7 -7
  43. package/dist/{chunk-gqdd7508.js → chunk-4rh2m6zg.js} +1 -1
  44. package/dist/{chunk-fmx1sz2h.js → chunk-72q2y8hn.js} +3 -3
  45. package/dist/{chunk-fmx1sz2h.js.map → chunk-72q2y8hn.js.map} +4 -4
  46. package/dist/{chunk-nnyp53zt.js → chunk-7gw7mepb.js} +259 -9
  47. package/dist/chunk-7gw7mepb.js.map +14 -0
  48. package/dist/{chunk-nten49ta.js → chunk-819wnjz8.js} +11 -5
  49. package/dist/chunk-819wnjz8.js.map +12 -0
  50. package/dist/chunk-96swp2wd.js +47 -0
  51. package/dist/chunk-96swp2wd.js.map +10 -0
  52. package/dist/{chunk-4x43bkbp.js → chunk-a09jx26t.js} +1 -1
  53. package/dist/{chunk-st4xgxey.js → chunk-afjpa2hs.js} +205 -48
  54. package/dist/chunk-afjpa2hs.js.map +45 -0
  55. package/dist/{chunk-0mbx247x.js → chunk-c43qr6s0.js} +427 -99
  56. package/dist/chunk-c43qr6s0.js.map +46 -0
  57. package/dist/{chunk-zg9yryhz.js → chunk-cbkm2vam.js} +3 -3
  58. package/dist/{chunk-57zpb99z.js → chunk-dm72y8wt.js} +26 -3
  59. package/dist/chunk-dm72y8wt.js.map +10 -0
  60. package/dist/chunk-drjqm1aa.js +913 -0
  61. package/dist/chunk-drjqm1aa.js.map +15 -0
  62. package/dist/chunk-dysw7nsm.js.map +1 -1
  63. package/dist/{chunk-8ryen3p3.js → chunk-f6erf2vv.js} +1 -1
  64. package/dist/{chunk-34bqh420.js → chunk-f83ka50g.js} +188 -44
  65. package/dist/chunk-f83ka50g.js.map +23 -0
  66. package/dist/{chunk-bct7hmfc.js → chunk-g13869yf.js} +3 -3
  67. package/dist/{chunk-0k4avqr2.js → chunk-hbeh8j9w.js} +2 -2
  68. package/dist/{chunk-qvybnnpe.js → chunk-nzw7sm3b.js} +2 -2
  69. package/dist/{chunk-k9pts48t.js → chunk-pn8n8sba.js} +16 -15
  70. package/dist/{chunk-k9pts48t.js.map → chunk-pn8n8sba.js.map} +3 -3
  71. package/dist/{chunk-63te770v.js → chunk-qewtks41.js} +8 -8
  72. package/dist/{chunk-63te770v.js.map → chunk-qewtks41.js.map} +2 -2
  73. package/dist/{chunk-85j5ybfj.js → chunk-rdeagz6b.js} +2 -2
  74. package/dist/{chunk-85j5ybfj.js.map → chunk-rdeagz6b.js.map} +3 -3
  75. package/dist/chunk-rhrbz7d4.js +36 -0
  76. package/dist/chunk-rhrbz7d4.js.map +10 -0
  77. package/dist/{chunk-bh6k3nc6.js → chunk-rs1wbvy6.js} +1 -1
  78. package/dist/{chunk-88ppkr54.js → chunk-rte5sm3z.js} +26 -2
  79. package/dist/chunk-rte5sm3z.js.map +12 -0
  80. package/dist/{chunk-n8herkry.js → chunk-s31d0qmq.js} +57 -20
  81. package/dist/{chunk-n8herkry.js.map → chunk-s31d0qmq.js.map} +8 -7
  82. package/dist/{chunk-7pc8b818.js → chunk-sxwk41qa.js} +1 -1
  83. package/dist/{chunk-663csy96.js → chunk-t0jjkep3.js} +2 -1
  84. package/dist/chunk-t0jjkep3.js.map +10 -0
  85. package/dist/{chunk-c6qd89g5.js → chunk-tek1qwgm.js} +6 -6
  86. package/dist/{chunk-c6qd89g5.js.map → chunk-tek1qwgm.js.map} +1 -1
  87. package/dist/{chunk-jaj13078.js → chunk-tkdscva6.js} +3 -33
  88. package/dist/{chunk-jaj13078.js.map → chunk-tkdscva6.js.map} +3 -4
  89. package/dist/{chunk-5egfka8j.js → chunk-tycbzedm.js} +2 -2
  90. package/dist/{chunk-g9t3kdtx.js → chunk-x2yw73hy.js} +1 -1
  91. package/dist/{chunk-57r1cpxx.js → chunk-xc7hq65b.js} +3 -2
  92. package/dist/{chunk-57r1cpxx.js.map → chunk-xc7hq65b.js.map} +3 -3
  93. package/dist/chunk-xdf9yswn.js +133 -0
  94. package/dist/chunk-xdf9yswn.js.map +11 -0
  95. package/dist/execution/agent.js +29 -27
  96. package/dist/execution/agent.js.map +1 -1
  97. package/dist/execution/primitive.js +29 -27
  98. package/dist/execution/primitive.js.map +2 -2
  99. package/dist/execution/request.js +30 -28
  100. package/dist/execution/request.js.map +2 -2
  101. package/dist/http/index.js +1 -1
  102. package/dist/index.d.ts +6 -5
  103. package/dist/index.d.ts.map +1 -1
  104. package/dist/index.js +60 -58
  105. package/dist/index.js.map +1 -1
  106. package/dist/lake-storage/types.d.ts +2 -1
  107. package/dist/lake-storage/types.d.ts.map +1 -1
  108. package/dist/materialization/model.d.ts +4 -0
  109. package/dist/materialization/model.d.ts.map +1 -1
  110. package/dist/materializer/edits/apply.d.ts +6 -1
  111. package/dist/materializer/edits/apply.d.ts.map +1 -1
  112. package/dist/materializer/edits/working-state.d.ts +2 -0
  113. package/dist/materializer/edits/working-state.d.ts.map +1 -1
  114. package/dist/materializer/effective/resolve.d.ts +3 -1
  115. package/dist/materializer/effective/resolve.d.ts.map +1 -1
  116. package/dist/materializer/execution/work-records.d.ts.map +1 -1
  117. package/dist/materializer/index.js +19 -17
  118. package/dist/materializer/index.js.map +1 -1
  119. package/dist/materializer/projections/replacement-plan.d.ts.map +1 -1
  120. package/dist/materializer/shared/normalize.d.ts.map +1 -1
  121. package/dist/models/index.d.ts +40 -0
  122. package/dist/models/index.d.ts.map +1 -0
  123. package/dist/objects/execution.d.ts +6 -1
  124. package/dist/objects/execution.d.ts.map +1 -1
  125. package/dist/objects/index.js +21 -19
  126. package/dist/objects/index.js.map +1 -1
  127. package/dist/objects/link/endpoints.d.ts.map +1 -1
  128. package/dist/objects/query/executor.d.ts +1 -0
  129. package/dist/objects/query/executor.d.ts.map +1 -1
  130. package/dist/objects/query/explain.d.ts +1 -0
  131. package/dist/objects/query/explain.d.ts.map +1 -1
  132. package/dist/objects/query/index.d.ts +3 -1
  133. package/dist/objects/query/index.d.ts.map +1 -1
  134. package/dist/objects/query/index.js +30 -5
  135. package/dist/objects/query/index.js.map +1 -1
  136. package/dist/objects/query/ir.d.ts +14 -1
  137. package/dist/objects/query/ir.d.ts.map +1 -1
  138. package/dist/objects/query/links.d.ts +25 -0
  139. package/dist/objects/query/links.d.ts.map +1 -0
  140. package/dist/objects/query/normalize.d.ts.map +1 -1
  141. package/dist/objects/query/planner.d.ts.map +1 -1
  142. package/dist/objects/query/validate.d.ts +1 -0
  143. package/dist/objects/query/validate.d.ts.map +1 -1
  144. package/dist/pipelines/index.js +16 -15
  145. package/dist/pipelines/index.js.map +1 -1
  146. package/dist/projections/builders.d.ts +52 -10
  147. package/dist/projections/builders.d.ts.map +1 -1
  148. package/dist/projections/index.d.ts +2 -1
  149. package/dist/projections/index.d.ts.map +1 -1
  150. package/dist/projections/internal.d.ts +4 -1
  151. package/dist/projections/internal.d.ts.map +1 -1
  152. package/dist/projections/internal.js +22 -17
  153. package/dist/projections/internal.js.map +1 -1
  154. package/dist/projections/run-dispatch.d.ts +1 -0
  155. package/dist/projections/run-dispatch.d.ts.map +1 -1
  156. package/dist/projections/timestamp.d.ts +3 -0
  157. package/dist/projections/timestamp.d.ts.map +1 -0
  158. package/dist/projections/types.d.ts +21 -9
  159. package/dist/projections/types.d.ts.map +1 -1
  160. package/dist/projections/validation.d.ts +6 -5
  161. package/dist/projections/validation.d.ts.map +1 -1
  162. package/dist/query.d.ts +2 -1
  163. package/dist/query.d.ts.map +1 -1
  164. package/dist/query.js +2 -2
  165. package/dist/queues/index.d.ts +1 -1
  166. package/dist/queues/index.d.ts.map +1 -1
  167. package/dist/queues/types.d.ts +7 -0
  168. package/dist/queues/types.d.ts.map +1 -1
  169. package/dist/runtime/ai-cost.d.ts +8 -0
  170. package/dist/runtime/ai-cost.d.ts.map +1 -0
  171. package/dist/runtime/create.d.ts +3 -0
  172. package/dist/runtime/create.d.ts.map +1 -1
  173. package/dist/runtime/definitions.d.ts +3 -0
  174. package/dist/runtime/definitions.d.ts.map +1 -1
  175. package/dist/runtime/host.d.ts +2 -0
  176. package/dist/runtime/host.d.ts.map +1 -1
  177. package/dist/runtime/resolve-definitions.d.ts +2 -0
  178. package/dist/runtime/resolve-definitions.d.ts.map +1 -1
  179. package/dist/storage/agents/in-memory.d.ts +22 -4
  180. package/dist/storage/agents/in-memory.d.ts.map +1 -1
  181. package/dist/storage/agents/index.d.ts +1 -1
  182. package/dist/storage/agents/index.d.ts.map +1 -1
  183. package/dist/storage/agents/provider.d.ts +31 -0
  184. package/dist/storage/agents/provider.d.ts.map +1 -1
  185. package/dist/storage/agents/provider.js +22 -7
  186. package/dist/storage/agents/provider.js.map +1 -1
  187. package/dist/storage/agents/types.d.ts +75 -4
  188. package/dist/storage/agents/types.d.ts.map +1 -1
  189. package/dist/storage/ai-cost/analytics.d.ts +61 -0
  190. package/dist/storage/ai-cost/analytics.d.ts.map +1 -0
  191. package/dist/storage/ai-cost/codec.d.ts +14 -0
  192. package/dist/storage/ai-cost/codec.d.ts.map +1 -0
  193. package/dist/storage/ai-cost/errors.d.ts +7 -0
  194. package/dist/storage/ai-cost/errors.d.ts.map +1 -0
  195. package/dist/storage/ai-cost/in-memory.d.ts +32 -0
  196. package/dist/storage/ai-cost/in-memory.d.ts.map +1 -0
  197. package/dist/storage/ai-cost/index.d.ts +6 -0
  198. package/dist/storage/ai-cost/index.d.ts.map +1 -0
  199. package/dist/storage/ai-cost/provider.d.ts +7 -0
  200. package/dist/storage/ai-cost/provider.d.ts.map +1 -0
  201. package/dist/storage/ai-cost/provider.js +132 -0
  202. package/dist/storage/ai-cost/provider.js.map +10 -0
  203. package/dist/storage/ai-cost/types.d.ts +154 -0
  204. package/dist/storage/ai-cost/types.d.ts.map +1 -0
  205. package/dist/storage/ai-cost/validation.d.ts +7 -0
  206. package/dist/storage/ai-cost/validation.d.ts.map +1 -0
  207. package/dist/storage/ai-usage/in-memory.d.ts +2 -1
  208. package/dist/storage/ai-usage/in-memory.d.ts.map +1 -1
  209. package/dist/storage/ai-usage/index.d.ts +1 -1
  210. package/dist/storage/ai-usage/index.d.ts.map +1 -1
  211. package/dist/storage/ai-usage/types.d.ts +6 -0
  212. package/dist/storage/ai-usage/types.d.ts.map +1 -1
  213. package/dist/storage/in-memory/index.d.ts +5 -0
  214. package/dist/storage/in-memory/index.d.ts.map +1 -1
  215. package/dist/storage/index.d.ts +6 -3
  216. package/dist/storage/index.d.ts.map +1 -1
  217. package/dist/storage/index.js +33 -21
  218. package/dist/storage/index.js.map +1 -1
  219. package/dist/storage/objects/in-memory.d.ts +6 -3
  220. package/dist/storage/objects/in-memory.d.ts.map +1 -1
  221. package/dist/storage/objects/index.d.ts +3 -1
  222. package/dist/storage/objects/index.d.ts.map +1 -1
  223. package/dist/storage/objects/keys.d.ts +16 -0
  224. package/dist/storage/objects/keys.d.ts.map +1 -0
  225. package/dist/storage/objects/types.d.ts +33 -6
  226. package/dist/storage/objects/types.d.ts.map +1 -1
  227. package/dist/storage/ontology/in-memory/materializations.d.ts.map +1 -1
  228. package/dist/storage/ontology/materializations.d.ts +3 -0
  229. package/dist/storage/ontology/materializations.d.ts.map +1 -1
  230. package/dist/storage/ontology/provider.js +1 -1
  231. package/dist/storage/operation-scope.d.ts.map +1 -1
  232. package/dist/storage/operation-scope.js +1 -1
  233. package/dist/storage/types.d.ts +2 -0
  234. package/dist/storage/types.d.ts.map +1 -1
  235. package/dist/storage/workflow-runs/provider.js +10 -5
  236. package/dist/storage/workflow-runs/provider.js.map +1 -1
  237. package/dist/syncs/index.js +16 -15
  238. package/dist/syncs/index.js.map +1 -1
  239. package/dist/testing/agent-storage-contract.d.ts +3 -2
  240. package/dist/testing/agent-storage-contract.d.ts.map +1 -1
  241. package/dist/testing/ai-cost-storage-contract.d.ts +12 -0
  242. package/dist/testing/ai-cost-storage-contract.d.ts.map +1 -0
  243. package/dist/testing/ai-usage-storage-contract.d.ts.map +1 -1
  244. package/dist/testing/effective-storage-contract.d.ts +1 -1
  245. package/dist/testing/effective-storage-contract.d.ts.map +1 -1
  246. package/dist/testing/index.d.ts +1 -0
  247. package/dist/testing/index.d.ts.map +1 -1
  248. package/dist/testing/index.js +2525 -1480
  249. package/dist/testing/index.js.map +10 -9
  250. package/dist/testing/lake-storage-contract.d.ts.map +1 -1
  251. package/dist/testing/materializer-storage-contract.d.ts.map +1 -1
  252. package/dist/testing/object-query-contract.d.ts +1 -1
  253. package/dist/testing/object-query-contract.d.ts.map +1 -1
  254. package/dist/webhooks/internal.js +14 -13
  255. package/dist/webhooks/internal.js.map +2 -2
  256. package/dist/workers/index.js +12 -2
  257. package/dist/workers/index.js.map +3 -3
  258. package/dist/workers/queue-worker.d.ts +2 -0
  259. package/dist/workers/queue-worker.d.ts.map +1 -1
  260. package/dist/workflows/execution.d.ts +3 -0
  261. package/dist/workflows/execution.d.ts.map +1 -1
  262. package/dist/workflows/index.js +30 -28
  263. package/dist/workflows/index.js.map +1 -1
  264. package/package.json +7 -1
  265. package/src/agents/adapters.ts +64 -23
  266. package/src/agents/builders.ts +3 -3
  267. package/src/agents/context-compaction.ts +261 -0
  268. package/src/agents/errors.ts +2 -2
  269. package/src/agents/execution.ts +14 -2
  270. package/src/agents/ids.ts +5 -0
  271. package/src/agents/index.ts +32 -6
  272. package/src/agents/request.ts +5 -0
  273. package/src/agents/streams.ts +56 -0
  274. package/src/agents/thread-context-projection.ts +93 -0
  275. package/src/agents/tool-definition.ts +17 -2
  276. package/src/agents/tool-result.ts +61 -0
  277. package/src/agents/types.ts +57 -1
  278. package/src/agents/validation.ts +36 -6
  279. package/src/http/api-routes.ts +7 -7
  280. package/src/index.ts +27 -0
  281. package/src/lake-storage/types.ts +2 -1
  282. package/src/materialization/model.ts +4 -0
  283. package/src/materializer/edits/apply.ts +55 -2
  284. package/src/materializer/edits/operations.ts +8 -1
  285. package/src/materializer/edits/working-state.ts +7 -0
  286. package/src/materializer/effective/resolve.ts +78 -9
  287. package/src/materializer/execution/work-records.ts +3 -1
  288. package/src/materializer/projections/entry-validator.ts +23 -1
  289. package/src/materializer/projections/replacement-plan.ts +2 -0
  290. package/src/materializer/shared/normalize.ts +16 -0
  291. package/src/materializer/telemetry/append.ts +33 -16
  292. package/src/models/index.ts +71 -0
  293. package/src/objects/execution.ts +20 -0
  294. package/src/objects/link/endpoints.ts +2 -1
  295. package/src/objects/query/executor.ts +42 -11
  296. package/src/objects/query/explain.ts +11 -0
  297. package/src/objects/query/index.ts +6 -0
  298. package/src/objects/query/ir.ts +16 -0
  299. package/src/objects/query/links.ts +308 -0
  300. package/src/objects/query/normalize.ts +40 -1
  301. package/src/objects/query/planner.ts +5 -0
  302. package/src/objects/query/validate.ts +58 -2
  303. package/src/projections/builders.ts +320 -50
  304. package/src/projections/index.ts +7 -0
  305. package/src/projections/internal.ts +4 -1
  306. package/src/projections/ownership.ts +5 -5
  307. package/src/projections/registry.ts +16 -3
  308. package/src/projections/revision.ts +35 -5
  309. package/src/projections/run-dispatch.ts +10 -1
  310. package/src/projections/timestamp.ts +66 -0
  311. package/src/projections/types.ts +20 -9
  312. package/src/projections/validation.ts +85 -19
  313. package/src/query.ts +2 -0
  314. package/src/queues/index.ts +1 -0
  315. package/src/queues/types.ts +8 -0
  316. package/src/runtime/ai-cost.ts +15 -0
  317. package/src/runtime/create.ts +4 -0
  318. package/src/runtime/definitions.ts +3 -0
  319. package/src/runtime/host.ts +2 -0
  320. package/src/runtime/resolve-definitions.ts +28 -0
  321. package/src/storage/agents/in-memory.ts +186 -4
  322. package/src/storage/agents/index.ts +5 -0
  323. package/src/storage/agents/provider.ts +225 -0
  324. package/src/storage/agents/types.ts +82 -3
  325. package/src/storage/ai-cost/analytics.ts +602 -0
  326. package/src/storage/ai-cost/codec.ts +136 -0
  327. package/src/storage/ai-cost/errors.ts +12 -0
  328. package/src/storage/ai-cost/in-memory.ts +164 -0
  329. package/src/storage/ai-cost/index.ts +35 -0
  330. package/src/storage/ai-cost/provider.ts +20 -0
  331. package/src/storage/ai-cost/types.ts +193 -0
  332. package/src/storage/ai-cost/validation.ts +337 -0
  333. package/src/storage/ai-usage/in-memory.ts +23 -0
  334. package/src/storage/ai-usage/index.ts +1 -0
  335. package/src/storage/ai-usage/types.ts +10 -0
  336. package/src/storage/in-memory/index.ts +50 -0
  337. package/src/storage/index.ts +48 -0
  338. package/src/storage/objects/in-memory.ts +103 -16
  339. package/src/storage/objects/index.ts +9 -0
  340. package/src/storage/objects/keys.ts +36 -0
  341. package/src/storage/objects/types.ts +34 -6
  342. package/src/storage/ontology/in-memory/materializations.ts +1 -0
  343. package/src/storage/ontology/materializations.ts +3 -0
  344. package/src/storage/ontology/provider-header-validation.ts +2 -2
  345. package/src/storage/operation-scope.ts +1 -0
  346. package/src/storage/types.ts +2 -0
  347. package/src/testing/agent-storage-contract.ts +353 -2
  348. package/src/testing/ai-cost-storage-contract.ts +320 -0
  349. package/src/testing/ai-usage-storage-contract.ts +35 -0
  350. package/src/testing/effective-storage-contract.ts +194 -4
  351. package/src/testing/index.ts +5 -0
  352. package/src/testing/lake-storage-contract.ts +56 -0
  353. package/src/testing/materializer-storage-contract.ts +120 -2
  354. package/src/testing/object-query-contract.ts +208 -1
  355. package/src/workers/queue-worker.ts +14 -1
  356. package/src/workflows/execution.ts +31 -10
  357. package/dist/agents/prompt.d.ts +0 -15
  358. package/dist/agents/prompt.d.ts.map +0 -1
  359. package/dist/chunk-0mbx247x.js.map +0 -43
  360. package/dist/chunk-34bqh420.js.map +0 -23
  361. package/dist/chunk-57zpb99z.js.map +0 -10
  362. package/dist/chunk-663csy96.js.map +0 -10
  363. package/dist/chunk-6wetht33.js +0 -89
  364. package/dist/chunk-6wetht33.js.map +0 -10
  365. package/dist/chunk-88ppkr54.js.map +0 -12
  366. package/dist/chunk-nnyp53zt.js.map +0 -13
  367. package/dist/chunk-nten49ta.js.map +0 -12
  368. package/dist/chunk-st4xgxey.js.map +0 -45
  369. package/dist/chunk-vp1vc6ee.js +0 -35
  370. package/dist/chunk-vp1vc6ee.js.map +0 -11
  371. package/src/agents/prompt.ts +0 -57
  372. /package/dist/{chunk-sa4340y1.js.map → chunk-1yz3x65y.js.map} +0 -0
  373. /package/dist/{chunk-gqdd7508.js.map → chunk-4rh2m6zg.js.map} +0 -0
  374. /package/dist/{chunk-4x43bkbp.js.map → chunk-a09jx26t.js.map} +0 -0
  375. /package/dist/{chunk-zg9yryhz.js.map → chunk-cbkm2vam.js.map} +0 -0
  376. /package/dist/{chunk-8ryen3p3.js.map → chunk-f6erf2vv.js.map} +0 -0
  377. /package/dist/{chunk-bct7hmfc.js.map → chunk-g13869yf.js.map} +0 -0
  378. /package/dist/{chunk-0k4avqr2.js.map → chunk-hbeh8j9w.js.map} +0 -0
  379. /package/dist/{chunk-qvybnnpe.js.map → chunk-nzw7sm3b.js.map} +0 -0
  380. /package/dist/{chunk-bh6k3nc6.js.map → chunk-rs1wbvy6.js.map} +0 -0
  381. /package/dist/{chunk-7pc8b818.js.map → chunk-sxwk41qa.js.map} +0 -0
  382. /package/dist/{chunk-5egfka8j.js.map → chunk-tycbzedm.js.map} +0 -0
  383. /package/dist/{chunk-g9t3kdtx.js.map → chunk-x2yw73hy.js.map} +0 -0
@@ -1,4 +1,11 @@
1
- import type { ObjectType, OntologyRegistry, Property, Schema, ValueType } from "../../ontology"
1
+ import type {
2
+ ObjectRef,
3
+ ObjectType,
4
+ OntologyRegistry,
5
+ Property,
6
+ Schema,
7
+ ValueType,
8
+ } from "../../ontology"
2
9
  import { normalizeDecimalValue } from "../../ontology"
3
10
  import { formatUnknownObjectTypeMessage } from "../../ontology/errors"
4
11
  import { validatePropertyValue, validateSchemaValue } from "../../ontology/validation"
@@ -30,11 +37,12 @@ export interface ObjectQueryValidationOptions {
30
37
  ontology: OntologyRegistry
31
38
  maxLimit?: number
32
39
  maxPageSize?: number
40
+ maxRefs?: number
33
41
  normalize?: boolean
34
42
  }
35
43
 
36
44
  type QueryValidationContext = Required<
37
- Pick<ObjectQueryValidationOptions, "maxLimit" | "maxPageSize">
45
+ Pick<ObjectQueryValidationOptions, "maxLimit" | "maxPageSize" | "maxRefs">
38
46
  > & {
39
47
  ontology: OntologyRegistry
40
48
  valueTypesById: ReadonlyMap<string, ValueType>
@@ -53,6 +61,7 @@ interface TextFieldResolution {
53
61
 
54
62
  const DEFAULT_MAX_LIMIT = 1_000
55
63
  const DEFAULT_MAX_PAGE_SIZE = 1_000
64
+ const DEFAULT_MAX_REFS = 1_000
56
65
 
57
66
  export function validateObjectQuery(
58
67
  query: ObjectQuery,
@@ -96,6 +105,7 @@ function createValidationContext(options: ObjectQueryValidationOptions): QueryVa
96
105
  valueTypesById: options.ontology.getValueTypesById(),
97
106
  maxLimit: options.maxLimit ?? DEFAULT_MAX_LIMIT,
98
107
  maxPageSize: options.maxPageSize ?? DEFAULT_MAX_PAGE_SIZE,
108
+ maxRefs: options.maxRefs ?? DEFAULT_MAX_REFS,
99
109
  issues: [],
100
110
  touchedObjectTypeIds: new Set<string>(),
101
111
  }
@@ -125,6 +135,8 @@ function dispatchQueryNode(
125
135
  switch (query.kind) {
126
136
  case "start":
127
137
  return validateStart(query.objectTypeId, query.includeSubtypes, path, ctx)
138
+ case "refs":
139
+ return validateRefs(query.refs, path, ctx)
128
140
  case "filter": {
129
141
  const input = validateQueryNode(query.input, `${path}.input`, ctx)
130
142
  const predicate = validatePredicate(query.predicate, input.result, `${path}.predicate`, ctx)
@@ -199,6 +211,50 @@ function dispatchQueryNode(
199
211
  }
200
212
  }
201
213
 
214
+ function validateRefs(
215
+ refs: readonly ObjectRef[],
216
+ path: string,
217
+ ctx: QueryValidationContext
218
+ ): QueryValidationResult {
219
+ if (refs.length === 0) {
220
+ addIssue(ctx, `${path}.refs`, "empty_refs", "refs must include at least one object reference")
221
+ }
222
+ if (refs.length > ctx.maxRefs) {
223
+ addIssue(
224
+ ctx,
225
+ `${path}.refs`,
226
+ "too_many_refs",
227
+ `refs must include at most ${ctx.maxRefs} object references`
228
+ )
229
+ }
230
+
231
+ const objectTypeIds = new Set<string>()
232
+ refs.forEach((ref, index) => {
233
+ const refPath = `${path}.refs[${index}]`
234
+ if (!ref.objectTypeId) {
235
+ addIssue(ctx, `${refPath}.objectTypeId`, "missing_object_type", "objectTypeId is required")
236
+ } else if (!ctx.ontology.getObjectTypeById(ref.objectTypeId)) {
237
+ addIssue(
238
+ ctx,
239
+ `${refPath}.objectTypeId`,
240
+ "unknown_object_type",
241
+ formatUnknownObjectTypeMessage(ref.objectTypeId)
242
+ )
243
+ } else {
244
+ objectTypeIds.add(ref.objectTypeId)
245
+ }
246
+
247
+ if (!ref.primaryId) {
248
+ addIssue(ctx, `${refPath}.primaryId`, "missing_primary_id", "primaryId is required")
249
+ }
250
+ })
251
+
252
+ return {
253
+ result: { objectTypeIds: [...objectTypeIds] },
254
+ query: { kind: "refs", refs: refs.map((ref) => ({ ...ref })) },
255
+ }
256
+ }
257
+
202
258
  function validateStart(
203
259
  objectTypeId: string,
204
260
  includeSubtypes: boolean | undefined,
@@ -5,6 +5,7 @@
5
5
  */
6
6
 
7
7
  import type {
8
+ DatasetColumnDefinitionOf,
8
9
  DatasetColumnNameOf,
9
10
  DatasetColumnType,
10
11
  DatasetColumnTypeOf,
@@ -21,7 +22,9 @@ import type {
21
22
  ObjectProjectionTarget,
22
23
  ProjectionDefinition,
23
24
  ProjectionTarget,
25
+ SourceEditConflictResolution,
24
26
  TelemetryProjectionDefinition,
27
+ TelemetryProjectionPropertyMapping,
25
28
  } from "./types"
26
29
  import {
27
30
  validateAndLowerLinkMapping,
@@ -153,6 +156,20 @@ type DateLikeDatasetColumnNameOf<TDataset extends DatasetDefinition> =
153
156
  : never
154
157
  }[DatasetColumnNameOf<TDataset>]
155
158
 
159
+ type TimestampDatasetColumnNameOf<TDataset extends DatasetDefinition> =
160
+ string extends DatasetColumnNameOf<TDataset>
161
+ ? string
162
+ : {
163
+ [TColumnName in DatasetColumnNameOf<TDataset>]: DatasetColumnTypeOf<
164
+ TDataset,
165
+ TColumnName
166
+ > extends "timestamp"
167
+ ? DatasetColumnDefinitionOf<TDataset, TColumnName> extends { readonly nullable: true }
168
+ ? never
169
+ : TColumnName
170
+ : never
171
+ }[DatasetColumnNameOf<TDataset>]
172
+
156
173
  type ProjectionMappingFor<TObjectType extends ObjectType, TDataset extends DatasetDefinition> = {
157
174
  readonly [TPropertyId in PropertyIdOf<TObjectType>]?: DatasetColumnNameCompatibleWithSchema<
158
175
  TDataset,
@@ -170,6 +187,18 @@ type TelemetryPropertyToken<TObjectTypeId extends string = string> = PropertyTok
170
187
  Property & { readonly mode: "telemetry" }
171
188
  >
172
189
 
190
+ type TelemetryPropertyOf<TObjectType extends ObjectType> = Extract<
191
+ TObjectType["properties"][number],
192
+ { readonly mode: "telemetry" }
193
+ >
194
+
195
+ type TelemetryPropertyIdOf<TObjectType extends ObjectType> = TelemetryPropertyOf<TObjectType>["id"]
196
+
197
+ type TelemetryPropertyById<
198
+ TObjectType extends ObjectType,
199
+ TPropertyId extends TelemetryPropertyIdOf<TObjectType>,
200
+ > = Extract<TelemetryPropertyOf<TObjectType>, { readonly id: TPropertyId }>
201
+
173
202
  type TelemetryProjectionPointMapping<
174
203
  TPropertyToken extends TelemetryPropertyToken,
175
204
  TDataset extends DatasetDefinition,
@@ -187,6 +216,58 @@ type ExactTelemetryProjectionPointMapping<TMapping> = TMapping & {
187
216
  readonly [TKey in Exclude<keyof TMapping, "objectId" | "at" | "value" | "unit">]: never
188
217
  }
189
218
 
219
+ type TelemetryProjectionPropertyInput<
220
+ TProperty extends Property,
221
+ TDataset extends DatasetDefinition,
222
+ > =
223
+ | DatasetColumnNameCompatibleWithSchema<TDataset, TProperty["schema"]>
224
+ | {
225
+ readonly value: DatasetColumnNameCompatibleWithSchema<TDataset, TProperty["schema"]>
226
+ readonly unit: StringDatasetColumnNameOf<TDataset>
227
+ }
228
+
229
+ type TelemetryProjectionPropertiesMapping<
230
+ TObjectType extends ObjectType,
231
+ TDataset extends DatasetDefinition,
232
+ > = {
233
+ readonly [TPropertyId in TelemetryPropertyIdOf<TObjectType>]?: TelemetryProjectionPropertyInput<
234
+ TelemetryPropertyById<TObjectType, TPropertyId>,
235
+ TDataset
236
+ >
237
+ }
238
+
239
+ type ExactTelemetryProjectionPropertiesMapping<
240
+ TObjectType extends ObjectType,
241
+ TMapping,
242
+ > = TMapping & {
243
+ readonly [TKey in Exclude<keyof TMapping, TelemetryPropertyIdOf<TObjectType>>]: never
244
+ }
245
+
246
+ type ExactTelemetryProjectionPropertyInputs<TMapping> = {
247
+ readonly [TPropertyId in keyof TMapping]: TMapping[TPropertyId] extends object
248
+ ? TMapping[TPropertyId] & {
249
+ readonly [TKey in Exclude<keyof TMapping[TPropertyId], "value" | "unit">]: never
250
+ }
251
+ : TMapping[TPropertyId]
252
+ }
253
+
254
+ type NonEmptyTelemetryProjectionProperties<TMapping> = keyof TMapping extends never
255
+ ? never
256
+ : TMapping
257
+
258
+ type TelemetryProjectionPropertiesPointMapping<
259
+ TObjectType extends ObjectType,
260
+ TDataset extends DatasetDefinition,
261
+ TProperties,
262
+ > = {
263
+ readonly objectId: StringDatasetColumnNameOf<TDataset>
264
+ readonly at: DateLikeDatasetColumnNameOf<TDataset>
265
+ readonly properties: NonEmptyTelemetryProjectionProperties<
266
+ ExactTelemetryProjectionPropertiesMapping<TObjectType, TProperties> &
267
+ ExactTelemetryProjectionPropertyInputs<TProperties>
268
+ >
269
+ }
270
+
190
271
  type ForeignKeyFromSourceProperty = Omit<
191
272
  ForeignKeyDescriptor,
192
273
  "sourcePropertyId" | "sourceField"
@@ -239,7 +320,7 @@ type ProjectionForeignKeyTokenInput<
239
320
  )
240
321
  }
241
322
 
242
- type ProjectionForeignKeyInput<
323
+ export type ProjectionForeignKeyInput<
243
324
  TObjectType extends ObjectType,
244
325
  TDataset extends DatasetDefinition,
245
326
  TLinkId extends LinkIdOf<TObjectType>,
@@ -268,28 +349,42 @@ function isForeignKeyDescriptor(value: unknown): value is ForeignKeyDescriptor {
268
349
 
269
350
  // ── defineProjection ─────────────────────────────────────────
270
351
 
271
- interface ObjectProjectionSourceBuilder<TObjectType extends ObjectType> {
352
+ interface ObjectTypeProjectionSourceBuilder<TObjectType extends ObjectType> {
272
353
  fromDataset<const TDataset extends DatasetDefinition>(
273
354
  dataset: TDataset
274
- ): ObjectProjectionMappingBuilder<TObjectType, TDataset>
355
+ ): ObjectTypeProjectionDatasetBuilder<TObjectType, TDataset>
275
356
  }
276
357
 
277
- interface ObjectProjectionMappingBuilder<
358
+ interface ObjectTypeProjectionDatasetBuilder<
278
359
  TObjectType extends ObjectType,
279
360
  TDataset extends DatasetDefinition,
280
361
  > {
281
362
  properties<const TMapping extends ProjectionMappingFor<TObjectType, TDataset>>(
282
363
  mapping: ExactProjectionMapping<TObjectType, TMapping>
283
- ): ObjectProjectionDefinition & ObjectProjectionLinkBuilder<TObjectType, TDataset>
364
+ ): ObjectProjectionBuilder<TObjectType, TDataset>
365
+ points<const TProperties extends TelemetryProjectionPropertiesMapping<TObjectType, TDataset>>(
366
+ mapping: TelemetryProjectionPropertiesPointMapping<TObjectType, TDataset, TProperties>
367
+ ): TelemetryProjectionDefinition
284
368
  }
285
369
 
286
- interface ObjectProjectionLinkBuilder<
370
+ export type ObjectProjectionConflictResolution<TDataset extends DatasetDefinition> =
371
+ | { readonly strategy: "editsWin" }
372
+ | {
373
+ readonly strategy: "mostRecent"
374
+ readonly sourceTimestamp: TimestampDatasetColumnNameOf<TDataset>
375
+ }
376
+
377
+ export interface ObjectProjectionBuilder<
287
378
  TObjectType extends ObjectType,
288
379
  TDataset extends DatasetDefinition,
289
- > {
380
+ > extends ObjectProjectionDefinition {
381
+ readonly conflictResolution: SourceEditConflictResolution
290
382
  withLinks(
291
383
  mapping: { [K in LinkIdOf<TObjectType>]?: ProjectionForeignKeyInput<TObjectType, TDataset, K> }
292
- ): ObjectProjectionDefinition
384
+ ): ObjectProjectionBuilder<TObjectType, TDataset>
385
+ resolveConflicts(
386
+ resolution: ObjectProjectionConflictResolution<TDataset>
387
+ ): ObjectProjectionBuilder<TObjectType, TDataset>
293
388
  }
294
389
 
295
390
  /**
@@ -311,7 +406,7 @@ interface ObjectProjectionLinkBuilder<
311
406
  export function defineProjection<const TObjectType extends ObjectType>(
312
407
  id: string,
313
408
  objectType: TObjectType
314
- ): ObjectProjectionSourceBuilder<TObjectType>
409
+ ): ObjectTypeProjectionSourceBuilder<TObjectType>
315
410
  export function defineProjection<
316
411
  TObjectTypeId extends string,
317
412
  TLinkId extends string,
@@ -328,72 +423,125 @@ export function defineProjection(
328
423
  id: string,
329
424
  target: ObjectType | LinkToken<string, string, string> | TelemetryPropertyToken
330
425
  ):
331
- | ObjectProjectionSourceBuilder<ObjectType>
426
+ | ObjectTypeProjectionSourceBuilder<ObjectType>
332
427
  | LinkProjectionSourceBuilder
333
428
  | TelemetryProjectionSourceBuilder<TelemetryPropertyToken> {
334
429
  if ("link" in target) return buildLinkProjection(id, target)
335
430
  if ("property" in target) return buildTelemetryProjection(id, target)
336
- return buildObjectProjection(id, target)
431
+ return buildObjectTypeProjection(id, target)
337
432
  }
338
433
 
339
- function buildObjectProjection<const TObjectType extends ObjectType>(
434
+ function buildObjectTypeProjection<const TObjectType extends ObjectType>(
340
435
  id: string,
341
436
  objectType: TObjectType
342
- ): ObjectProjectionSourceBuilder<TObjectType> {
437
+ ): ObjectTypeProjectionSourceBuilder<TObjectType> {
343
438
  assertNonEmpty(id, "id")
344
439
 
345
440
  return {
346
441
  fromDataset<const TDataset extends DatasetDefinition>(
347
442
  dataset: TDataset
348
- ): ObjectProjectionMappingBuilder<TObjectType, TDataset> {
443
+ ): ObjectTypeProjectionDatasetBuilder<TObjectType, TDataset> {
349
444
  assertProjectionDataset(dataset)
350
445
  const datasetId = dataset.id
351
446
 
352
447
  return {
353
448
  properties<const TMapping extends ProjectionMappingFor<TObjectType, TDataset>>(
354
449
  mapping: ExactProjectionMapping<TObjectType, TMapping>
355
- ): ObjectProjectionDefinition & ObjectProjectionLinkBuilder<TObjectType, TDataset> {
450
+ ): ObjectProjectionBuilder<TObjectType, TDataset> {
356
451
  const propertyMapping = mapping as Record<string, string>
357
452
  validatePropertyMapping(objectType, propertyMapping)
358
453
 
359
- const definition: ObjectProjectionDefinition = {
360
- _tag: "ObjectProjectionDefinition",
454
+ return objectProjectionBuilder({
361
455
  id,
362
- objectTypeId: objectType.id,
456
+ objectType,
363
457
  datasetId,
364
- properties: { ...propertyMapping },
458
+ propertyMapping,
365
459
  links: {},
366
- }
367
-
368
- return Object.assign(definition, {
369
- withLinks(
370
- linkMapping: {
371
- [K in LinkIdOf<TObjectType>]?: ProjectionForeignKeyInput<TObjectType, TDataset, K>
372
- }
373
- ): ObjectProjectionDefinition {
374
- const loweredLinkMapping = lowerForeignKeyMapping(linkMapping)
375
- const validatedLinks = validateAndLowerLinkMapping(
376
- objectType,
377
- loweredLinkMapping,
378
- propertyMapping
379
- )
380
-
381
- return {
382
- _tag: "ObjectProjectionDefinition",
383
- id,
384
- objectTypeId: objectType.id,
385
- datasetId,
386
- properties: { ...propertyMapping },
387
- links: validatedLinks,
388
- }
389
- },
460
+ conflictResolution: { strategy: "editsWin" },
390
461
  })
391
462
  },
463
+ points<
464
+ const TProperties extends TelemetryProjectionPropertiesMapping<TObjectType, TDataset>,
465
+ >(
466
+ mapping: TelemetryProjectionPropertiesPointMapping<TObjectType, TDataset, TProperties>
467
+ ): TelemetryProjectionDefinition {
468
+ const pointMapping = lowerTelemetryPropertiesPointMapping(
469
+ objectType,
470
+ mapping as {
471
+ readonly objectId?: string
472
+ readonly at?: string
473
+ readonly properties?: Readonly<Record<string, unknown>>
474
+ }
475
+ )
476
+ return {
477
+ _tag: "TelemetryProjectionDefinition",
478
+ id,
479
+ objectTypeId: objectType.id,
480
+ datasetId,
481
+ objectIdField: pointMapping.objectId,
482
+ atField: pointMapping.at,
483
+ properties: pointMapping.properties,
484
+ }
485
+ },
392
486
  }
393
487
  },
394
488
  }
395
489
  }
396
490
 
491
+ function objectProjectionBuilder<
492
+ TObjectType extends ObjectType,
493
+ TDataset extends DatasetDefinition,
494
+ >(input: {
495
+ readonly id: string
496
+ readonly objectType: TObjectType
497
+ readonly datasetId: string
498
+ readonly propertyMapping: Readonly<Record<string, string>>
499
+ readonly links: Readonly<Record<string, ForeignKeyDescriptor>>
500
+ readonly conflictResolution: SourceEditConflictResolution
501
+ }): ObjectProjectionBuilder<TObjectType, TDataset> {
502
+ const definition: ObjectProjectionDefinition & {
503
+ readonly conflictResolution: SourceEditConflictResolution
504
+ } = {
505
+ _tag: "ObjectProjectionDefinition",
506
+ id: input.id,
507
+ objectTypeId: input.objectType.id,
508
+ datasetId: input.datasetId,
509
+ properties: { ...input.propertyMapping },
510
+ links: { ...input.links },
511
+ conflictResolution: { ...input.conflictResolution },
512
+ }
513
+
514
+ return Object.assign(definition, {
515
+ withLinks(
516
+ linkMapping: {
517
+ [K in LinkIdOf<TObjectType>]?: ProjectionForeignKeyInput<TObjectType, TDataset, K>
518
+ }
519
+ ): ObjectProjectionBuilder<TObjectType, TDataset> {
520
+ const loweredLinkMapping = lowerForeignKeyMapping(linkMapping)
521
+ const validatedLinks = validateAndLowerLinkMapping(
522
+ input.objectType,
523
+ loweredLinkMapping,
524
+ input.propertyMapping as Record<string, string>
525
+ )
526
+ return objectProjectionBuilder({ ...input, links: validatedLinks })
527
+ },
528
+ resolveConflicts(
529
+ resolution: ObjectProjectionConflictResolution<TDataset>
530
+ ): ObjectProjectionBuilder<TObjectType, TDataset> {
531
+ validateConflictResolution(resolution)
532
+ return objectProjectionBuilder({
533
+ ...input,
534
+ conflictResolution: resolution as SourceEditConflictResolution,
535
+ })
536
+ },
537
+ })
538
+ }
539
+
540
+ function validateConflictResolution(resolution: SourceEditConflictResolution): void {
541
+ if (resolution.strategy === "editsWin") return
542
+ assertNonEmpty(resolution.sourceTimestamp, "source timestamp field")
543
+ }
544
+
397
545
  // ── Telemetry projection ────────────────────────────────────
398
546
 
399
547
  interface TelemetryProjectionSourceBuilder<TPropertyToken extends TelemetryPropertyToken> {
@@ -448,12 +596,15 @@ function buildTelemetryProjection<const TPropertyToken extends TelemetryProperty
448
596
  _tag: "TelemetryProjectionDefinition",
449
597
  id,
450
598
  objectTypeId: propertyToken.objectTypeId,
451
- propertyId: propertyToken.id,
452
599
  datasetId,
453
600
  objectIdField: pointMapping.objectId,
454
601
  atField: pointMapping.at,
455
- valueField: pointMapping.value,
456
- ...(pointMapping.unit !== undefined ? { unitField: pointMapping.unit } : {}),
602
+ properties: {
603
+ [propertyToken.id]: {
604
+ valueField: pointMapping.value,
605
+ ...(pointMapping.unit !== undefined ? { unitField: pointMapping.unit } : {}),
606
+ },
607
+ },
457
608
  }
458
609
  },
459
610
  }
@@ -514,6 +665,109 @@ function lowerTelemetryPointMapping(mapping: {
514
665
  }
515
666
  }
516
667
 
668
+ function lowerTelemetryPropertiesPointMapping(
669
+ objectType: ObjectType,
670
+ mapping: {
671
+ readonly objectId?: string
672
+ readonly at?: string
673
+ readonly properties?: Readonly<Record<string, unknown>>
674
+ }
675
+ ): {
676
+ readonly objectId: string
677
+ readonly at: string
678
+ readonly properties: Readonly<Record<string, TelemetryProjectionPropertyMapping>>
679
+ } {
680
+ const allowedKeys = new Set(["objectId", "at", "properties"])
681
+ for (const key of Object.keys(mapping)) {
682
+ if (!allowedKeys.has(key)) {
683
+ throw new ProjectionValidationError(
684
+ `Telemetry projection point mapping contains unknown key '${key}'.`
685
+ )
686
+ }
687
+ }
688
+
689
+ if (mapping.objectId === undefined) {
690
+ throw new ProjectionValidationError("Telemetry projection point mapping requires objectId.")
691
+ }
692
+ if (mapping.at === undefined) {
693
+ throw new ProjectionValidationError("Telemetry projection point mapping requires at.")
694
+ }
695
+ if (mapping.properties === undefined) {
696
+ throw new ProjectionValidationError("Telemetry projection point mapping requires properties.")
697
+ }
698
+ if (!isRecord(mapping.properties)) {
699
+ throw new ProjectionValidationError(
700
+ "Telemetry projection point mapping properties must be an object."
701
+ )
702
+ }
703
+
704
+ assertNonEmpty(mapping.objectId, "objectId field")
705
+ assertNonEmpty(mapping.at, "at field")
706
+
707
+ const propertyEntries = Object.entries(mapping.properties)
708
+ if (propertyEntries.length === 0) {
709
+ throw new ProjectionValidationError(
710
+ "Telemetry projection point mapping requires at least one property."
711
+ )
712
+ }
713
+
714
+ const propertiesById = new Map(objectType.properties.map((property) => [property.id, property]))
715
+ const properties: Record<string, TelemetryProjectionPropertyMapping> = {}
716
+ for (const [propertyId, input] of propertyEntries) {
717
+ const property = propertiesById.get(propertyId)
718
+ if (!property) {
719
+ throw new ProjectionValidationError(
720
+ `Property '${propertyId}' does not exist on object type '${objectType.id}'.`
721
+ )
722
+ }
723
+ if (property.mode !== "telemetry") {
724
+ throw new ProjectionValidationError(
725
+ `Projection property '${objectType.id}.${propertyId}' must be telemetry-enabled.`
726
+ )
727
+ }
728
+ properties[propertyId] = lowerTelemetryPropertyMapping(propertyId, input)
729
+ }
730
+
731
+ return { objectId: mapping.objectId, at: mapping.at, properties }
732
+ }
733
+
734
+ function lowerTelemetryPropertyMapping(
735
+ propertyId: string,
736
+ input: unknown
737
+ ): TelemetryProjectionPropertyMapping {
738
+ if (typeof input === "string") {
739
+ assertNonEmpty(input, `property '${propertyId}' value field`)
740
+ return { valueField: input }
741
+ }
742
+ if (!isRecord(input)) {
743
+ throw new ProjectionValidationError(
744
+ `Telemetry projection property '${propertyId}' must map a value column or value/unit columns.`
745
+ )
746
+ }
747
+
748
+ const allowedKeys = new Set(["value", "unit"])
749
+ for (const key of Object.keys(input)) {
750
+ if (!allowedKeys.has(key)) {
751
+ throw new ProjectionValidationError(
752
+ `Telemetry projection property '${propertyId}' contains unknown key '${key}'.`
753
+ )
754
+ }
755
+ }
756
+ if (typeof input.value !== "string") {
757
+ throw new ProjectionValidationError(
758
+ `Telemetry projection property '${propertyId}' requires a value field.`
759
+ )
760
+ }
761
+ if (typeof input.unit !== "string") {
762
+ throw new ProjectionValidationError(
763
+ `Telemetry projection property '${propertyId}' requires a unit field.`
764
+ )
765
+ }
766
+ assertNonEmpty(input.value, `property '${propertyId}' value field`)
767
+ assertNonEmpty(input.unit, `property '${propertyId}' unit field`)
768
+ return { valueField: input.value, unitField: input.unit }
769
+ }
770
+
517
771
  // ── fromForeignKey ───────────────────────────────────────────
518
772
 
519
773
  /**
@@ -672,10 +926,18 @@ export function isObjectProjectionDefinition(value: unknown): value is ObjectPro
672
926
  typeof value.objectTypeId === "string" &&
673
927
  typeof value.datasetId === "string" &&
674
928
  isRecord(value.properties) &&
675
- isRecord(value.links)
929
+ isRecord(value.links) &&
930
+ isSourceEditConflictResolution(value.conflictResolution)
676
931
  )
677
932
  }
678
933
 
934
+ function isSourceEditConflictResolution(value: unknown): boolean {
935
+ if (value === undefined) return true
936
+ if (!isRecord(value) || typeof value.strategy !== "string") return false
937
+ if (value.strategy === "editsWin") return value.sourceTimestamp === undefined
938
+ return value.strategy === "mostRecent" && typeof value.sourceTimestamp === "string"
939
+ }
940
+
679
941
  /** Runtime type guard for {@link LinkProjectionDefinition}. */
680
942
  export function isLinkProjectionDefinition(value: unknown): value is LinkProjectionDefinition {
681
943
  if (!isRecord(value)) return false
@@ -700,12 +962,20 @@ export function isTelemetryProjectionDefinition(
700
962
  value._tag === "TelemetryProjectionDefinition" &&
701
963
  typeof value.id === "string" &&
702
964
  typeof value.objectTypeId === "string" &&
703
- typeof value.propertyId === "string" &&
704
965
  typeof value.datasetId === "string" &&
705
966
  typeof value.objectIdField === "string" &&
706
967
  typeof value.atField === "string" &&
707
- typeof value.valueField === "string" &&
708
- (value.unitField === undefined || typeof value.unitField === "string")
968
+ isTelemetryProjectionProperties(value.properties)
969
+ )
970
+ }
971
+
972
+ function isTelemetryProjectionProperties(value: unknown): boolean {
973
+ if (!isRecord(value) || Object.keys(value).length === 0) return false
974
+ return Object.values(value).every(
975
+ (mapping) =>
976
+ isRecord(mapping) &&
977
+ typeof mapping.valueField === "string" &&
978
+ (mapping.unitField === undefined || typeof mapping.unitField === "string")
709
979
  )
710
980
  }
711
981
 
@@ -1,5 +1,10 @@
1
1
  // ── Builders ─────────────────────────────────────────────────
2
2
 
3
+ export type {
4
+ ObjectProjectionBuilder,
5
+ ObjectProjectionConflictResolution,
6
+ ProjectionForeignKeyInput,
7
+ } from "./builders"
3
8
  export {
4
9
  categorizeProjections,
5
10
  defineProjection,
@@ -24,7 +29,9 @@ export type {
24
29
  ProjectionKind,
25
30
  ProjectionTarget,
26
31
  ProjectionTargetByKind,
32
+ SourceEditConflictResolution,
27
33
  TelemetryProjectionDefinition,
34
+ TelemetryProjectionPropertyMapping,
28
35
  } from "./types"
29
36
  // ── Validation ───────────────────────────────────────────────
30
37
  export {
@@ -7,7 +7,9 @@ import type { ProjectionDispatchDescriptor } from "./types"
7
7
  *
8
8
  * `projectionTargetOf` derives the object types a projection writes, to record them on the run.
9
9
  * `validateTelemetryProjectionFieldMapping` re-checks a telemetry mapping against the dataset schema
10
- * before writing. Both are plumbing, so they live here instead of on the `@sixb/core` root.
10
+ * before writing. `parseDatasetTimestamp` keeps worker timestamps aligned with the materializer's
11
+ * authoritative validation. These are plumbing, so they live here instead of on the
12
+ * `@sixb/core` root.
11
13
  */
12
14
  export { projectionTargetOf } from "./builders"
13
15
  export {
@@ -27,6 +29,7 @@ export {
27
29
  ProjectionRunDispatcher,
28
30
  } from "./run-dispatch"
29
31
  export { createProjectionRunId } from "./run-id"
32
+ export { parseDatasetTimestamp } from "./timestamp"
30
33
  export { validateTelemetryProjectionFieldMapping } from "./validation"
31
34
 
32
35
  export type { ProjectionDispatchDescriptor, ProjectionMaterializationIdentity, ProjectionRegistry }
@@ -42,12 +42,12 @@ export function computeProjectionOwnership(
42
42
  return freezeOwnership({
43
43
  objects: [],
44
44
  links: [],
45
- telemetry: [
46
- {
45
+ telemetry: Object.keys(projection.properties)
46
+ .sort(compareStrings)
47
+ .map((propertyId) => ({
47
48
  objectTypeId: projection.objectTypeId,
48
- propertyId: projection.propertyId,
49
- },
50
- ],
49
+ propertyId,
50
+ })),
51
51
  })
52
52
  }
53
53