@sixb/core 0.1.3 → 0.1.5

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 (271) hide show
  1. package/dist/actions/index.d.ts +2 -2
  2. package/dist/actions/index.d.ts.map +1 -1
  3. package/dist/actions/index.js +17 -18
  4. package/dist/actions/index.js.map +1 -1
  5. package/dist/actions/read-facade.d.ts +10 -2
  6. package/dist/actions/read-facade.d.ts.map +1 -1
  7. package/dist/actions/types/context.d.ts +45 -2
  8. package/dist/actions/types/context.d.ts.map +1 -1
  9. package/dist/actions/worker.js +4 -4
  10. package/dist/actions/worker.js.map +1 -1
  11. package/dist/agents/context-compaction.d.ts +40 -0
  12. package/dist/agents/context-compaction.d.ts.map +1 -0
  13. package/dist/agents/ids.d.ts +2 -0
  14. package/dist/agents/ids.d.ts.map +1 -1
  15. package/dist/agents/index.d.ts +6 -5
  16. package/dist/agents/index.d.ts.map +1 -1
  17. package/dist/agents/index.js +42 -37
  18. package/dist/agents/index.js.map +1 -1
  19. package/dist/agents/streams.d.ts +17 -1
  20. package/dist/agents/streams.d.ts.map +1 -1
  21. package/dist/agents/streams.js +4 -2
  22. package/dist/agents/streams.js.map +1 -1
  23. package/dist/agents/types.d.ts +11 -0
  24. package/dist/agents/types.d.ts.map +1 -1
  25. package/dist/agents/validation.d.ts +1 -1
  26. package/dist/agents/validation.d.ts.map +1 -1
  27. package/dist/auth/index.js +7 -3
  28. package/dist/auth/index.js.map +1 -1
  29. package/dist/authorization/index.js +6 -2
  30. package/dist/authorization/index.js.map +1 -1
  31. package/dist/bootstrap/index.js +30 -31
  32. package/dist/bootstrap/index.js.map +1 -1
  33. package/dist/{chunk-d6y2wsfg.js → chunk-1q02e95s.js} +12 -7
  34. package/dist/{chunk-d6y2wsfg.js.map → chunk-1q02e95s.js.map} +4 -3
  35. package/dist/{chunk-c6cfqydk.js → chunk-4h947jd8.js} +1 -1
  36. package/dist/{chunk-gqdd7508.js → chunk-4rh2m6zg.js} +1 -1
  37. package/dist/{chunk-f1cyvnrk.js → chunk-6d5xdj1q.js} +259 -9
  38. package/dist/chunk-6d5xdj1q.js.map +14 -0
  39. package/dist/{chunk-fmx1sz2h.js → chunk-72q2y8hn.js} +3 -3
  40. package/dist/{chunk-fmx1sz2h.js.map → chunk-72q2y8hn.js.map} +3 -3
  41. package/dist/{chunk-ttba8x6z.js → chunk-78c6xvyr.js} +68 -3
  42. package/dist/chunk-78c6xvyr.js.map +15 -0
  43. package/dist/{chunk-wb4051cx.js → chunk-819wnjz8.js} +11 -5
  44. package/dist/chunk-819wnjz8.js.map +12 -0
  45. package/dist/{chunk-177ed2mp.js → chunk-84h6qhmp.js} +233 -97
  46. package/dist/{chunk-177ed2mp.js.map → chunk-84h6qhmp.js.map} +9 -9
  47. package/dist/{chunk-pxtrxm3p.js → chunk-a09jx26t.js} +1 -1
  48. package/dist/{chunk-bv41fmjn.js → chunk-am6eczah.js} +59 -22
  49. package/dist/{chunk-bv41fmjn.js.map → chunk-am6eczah.js.map} +8 -7
  50. package/dist/{chunk-zpw39qhj.js → chunk-dm72y8wt.js} +25 -2
  51. package/dist/chunk-dm72y8wt.js.map +10 -0
  52. package/dist/{chunk-kqxgf6kv.js → chunk-drjqm1aa.js} +16 -1
  53. package/dist/{chunk-kqxgf6kv.js.map → chunk-drjqm1aa.js.map} +3 -3
  54. package/dist/chunk-dysw7nsm.js.map +1 -1
  55. package/dist/{chunk-4p9rh7jj.js → chunk-ea73pzk7.js} +1 -1
  56. package/dist/{chunk-4aw0jwk0.js → chunk-f6erf2vv.js} +1 -1
  57. package/dist/{chunk-4z3n1dzt.js → chunk-f83ka50g.js} +131 -25
  58. package/dist/chunk-f83ka50g.js.map +23 -0
  59. package/dist/{chunk-c8bw2b6c.js → chunk-gadsm794.js} +2 -2
  60. package/dist/{chunk-1ywq4hzk.js → chunk-h6h91mfy.js} +8 -10
  61. package/dist/{chunk-1ywq4hzk.js.map → chunk-h6h91mfy.js.map} +2 -2
  62. package/dist/{chunk-n5x5y80a.js → chunk-nzw7sm3b.js} +2 -2
  63. package/dist/{chunk-63te770v.js → chunk-qewtks41.js} +8 -8
  64. package/dist/{chunk-63te770v.js.map → chunk-qewtks41.js.map} +2 -2
  65. package/dist/{chunk-261ag4t4.js → chunk-r0rry8dn.js} +3 -3
  66. package/dist/{chunk-88ppkr54.js → chunk-rte5sm3z.js} +26 -2
  67. package/dist/chunk-rte5sm3z.js.map +12 -0
  68. package/dist/chunk-t0jjkep3.js.map +1 -1
  69. package/dist/{chunk-ettb0cy4.js → chunk-tbv03sx2.js} +59 -29
  70. package/dist/{chunk-ettb0cy4.js.map → chunk-tbv03sx2.js.map} +5 -5
  71. package/dist/{chunk-d2adj15j.js → chunk-tkdscva6.js} +1 -1
  72. package/dist/{chunk-xmggaxg4.js → chunk-v0egge8b.js} +201 -38
  73. package/dist/{chunk-xmggaxg4.js.map → chunk-v0egge8b.js.map} +8 -6
  74. package/dist/{chunk-z8j83gzd.js → chunk-x2yw73hy.js} +1 -1
  75. package/dist/{chunk-qer6am8w.js → chunk-xdf9yswn.js} +1 -1
  76. package/dist/{chunk-3rsf30p4.js → chunk-z3ga9q5m.js} +18 -21
  77. package/dist/{chunk-3rsf30p4.js.map → chunk-z3ga9q5m.js.map} +4 -5
  78. package/dist/{chunk-km4rkj4t.js → chunk-zp2v2rv6.js} +3 -3
  79. package/dist/execution/agent.js +26 -27
  80. package/dist/execution/agent.js.map +1 -1
  81. package/dist/execution/primitive.js +26 -27
  82. package/dist/execution/primitive.js.map +2 -2
  83. package/dist/execution/request.js +27 -28
  84. package/dist/execution/request.js.map +2 -2
  85. package/dist/http/index.js +1 -1
  86. package/dist/index.d.ts +6 -5
  87. package/dist/index.d.ts.map +1 -1
  88. package/dist/index.js +54 -55
  89. package/dist/index.js.map +1 -1
  90. package/dist/lake-storage/types.d.ts +2 -1
  91. package/dist/lake-storage/types.d.ts.map +1 -1
  92. package/dist/materializer/index.js +15 -16
  93. package/dist/materializer/index.js.map +1 -1
  94. package/dist/models/index.d.ts +40 -0
  95. package/dist/models/index.d.ts.map +1 -0
  96. package/dist/objects/execution.d.ts +6 -1
  97. package/dist/objects/execution.d.ts.map +1 -1
  98. package/dist/objects/index.js +19 -20
  99. package/dist/objects/index.js.map +1 -1
  100. package/dist/objects/link/endpoints.d.ts.map +1 -1
  101. package/dist/objects/query/executor.d.ts +1 -0
  102. package/dist/objects/query/executor.d.ts.map +1 -1
  103. package/dist/objects/query/explain.d.ts +1 -0
  104. package/dist/objects/query/explain.d.ts.map +1 -1
  105. package/dist/objects/query/index.d.ts +3 -1
  106. package/dist/objects/query/index.d.ts.map +1 -1
  107. package/dist/objects/query/index.js +30 -5
  108. package/dist/objects/query/index.js.map +1 -1
  109. package/dist/objects/query/ir.d.ts +14 -1
  110. package/dist/objects/query/ir.d.ts.map +1 -1
  111. package/dist/objects/query/links.d.ts +25 -0
  112. package/dist/objects/query/links.d.ts.map +1 -0
  113. package/dist/objects/query/normalize.d.ts.map +1 -1
  114. package/dist/objects/query/planner.d.ts.map +1 -1
  115. package/dist/objects/query/validate.d.ts +1 -0
  116. package/dist/objects/query/validate.d.ts.map +1 -1
  117. package/dist/ontology/internal.d.ts +1 -1
  118. package/dist/ontology/internal.d.ts.map +1 -1
  119. package/dist/ontology/internal.js +14 -6
  120. package/dist/ontology/internal.js.map +3 -3
  121. package/dist/ontology/json-schema.d.ts +10 -0
  122. package/dist/ontology/json-schema.d.ts.map +1 -1
  123. package/dist/pipelines/index.js +15 -16
  124. package/dist/pipelines/index.js.map +1 -1
  125. package/dist/projections/builders.d.ts +33 -4
  126. package/dist/projections/builders.d.ts.map +1 -1
  127. package/dist/projections/index.d.ts +1 -1
  128. package/dist/projections/index.d.ts.map +1 -1
  129. package/dist/projections/internal.js +15 -16
  130. package/dist/projections/internal.js.map +1 -1
  131. package/dist/projections/run-dispatch.d.ts +1 -0
  132. package/dist/projections/run-dispatch.d.ts.map +1 -1
  133. package/dist/projections/types.d.ts +12 -9
  134. package/dist/projections/types.d.ts.map +1 -1
  135. package/dist/projections/validation.d.ts +6 -5
  136. package/dist/projections/validation.d.ts.map +1 -1
  137. package/dist/query.d.ts +2 -1
  138. package/dist/query.d.ts.map +1 -1
  139. package/dist/query.js +2 -2
  140. package/dist/runtime/create.d.ts +3 -0
  141. package/dist/runtime/create.d.ts.map +1 -1
  142. package/dist/runtime/definitions.d.ts +3 -0
  143. package/dist/runtime/definitions.d.ts.map +1 -1
  144. package/dist/runtime/host.d.ts +2 -0
  145. package/dist/runtime/host.d.ts.map +1 -1
  146. package/dist/runtime/resolve-definitions.d.ts +2 -0
  147. package/dist/runtime/resolve-definitions.d.ts.map +1 -1
  148. package/dist/storage/agents/in-memory.d.ts +4 -0
  149. package/dist/storage/agents/in-memory.d.ts.map +1 -1
  150. package/dist/storage/agents/provider.js +9 -5
  151. package/dist/storage/agents/provider.js.map +1 -1
  152. package/dist/storage/agents/types.d.ts +5 -0
  153. package/dist/storage/agents/types.d.ts.map +1 -1
  154. package/dist/storage/ai-cost/provider.js +1 -1
  155. package/dist/storage/ai-usage/in-memory.d.ts +2 -1
  156. package/dist/storage/ai-usage/in-memory.d.ts.map +1 -1
  157. package/dist/storage/ai-usage/index.d.ts +1 -1
  158. package/dist/storage/ai-usage/index.d.ts.map +1 -1
  159. package/dist/storage/ai-usage/types.d.ts +6 -0
  160. package/dist/storage/ai-usage/types.d.ts.map +1 -1
  161. package/dist/storage/index.d.ts +3 -2
  162. package/dist/storage/index.d.ts.map +1 -1
  163. package/dist/storage/index.js +19 -14
  164. package/dist/storage/index.js.map +1 -1
  165. package/dist/storage/objects/in-memory.d.ts +6 -3
  166. package/dist/storage/objects/in-memory.d.ts.map +1 -1
  167. package/dist/storage/objects/index.d.ts +3 -1
  168. package/dist/storage/objects/index.d.ts.map +1 -1
  169. package/dist/storage/objects/keys.d.ts +16 -0
  170. package/dist/storage/objects/keys.d.ts.map +1 -0
  171. package/dist/storage/objects/types.d.ts +33 -6
  172. package/dist/storage/objects/types.d.ts.map +1 -1
  173. package/dist/storage/ontology/provider.js +1 -1
  174. package/dist/storage/workflow-runs/provider.js +9 -5
  175. package/dist/storage/workflow-runs/provider.js.map +1 -1
  176. package/dist/syncs/index.js +15 -16
  177. package/dist/syncs/index.js.map +1 -1
  178. package/dist/testing/agent-storage-contract.d.ts.map +1 -1
  179. package/dist/testing/ai-usage-storage-contract.d.ts.map +1 -1
  180. package/dist/testing/effective-storage-contract.d.ts +1 -1
  181. package/dist/testing/effective-storage-contract.d.ts.map +1 -1
  182. package/dist/testing/index.js +455 -40
  183. package/dist/testing/index.js.map +7 -7
  184. package/dist/testing/lake-storage-contract.d.ts.map +1 -1
  185. package/dist/testing/object-query-contract.d.ts +1 -1
  186. package/dist/testing/object-query-contract.d.ts.map +1 -1
  187. package/dist/webhooks/internal.js +13 -14
  188. package/dist/webhooks/internal.js.map +2 -2
  189. package/dist/workflows/index.js +27 -28
  190. package/dist/workflows/index.js.map +1 -1
  191. package/package.json +1 -1
  192. package/src/actions/index.ts +10 -1
  193. package/src/actions/read-facade.ts +125 -3
  194. package/src/actions/types/context.ts +69 -2
  195. package/src/agents/builders.ts +3 -3
  196. package/src/agents/context-compaction.ts +261 -0
  197. package/src/agents/ids.ts +5 -0
  198. package/src/agents/index.ts +18 -9
  199. package/src/agents/streams.ts +56 -0
  200. package/src/agents/types.ts +12 -0
  201. package/src/agents/validation.ts +39 -5
  202. package/src/http/api-routes.ts +7 -7
  203. package/src/index.ts +19 -0
  204. package/src/lake-storage/types.ts +2 -1
  205. package/src/materializer/telemetry/append.ts +33 -16
  206. package/src/models/index.ts +71 -0
  207. package/src/objects/execution.ts +20 -0
  208. package/src/objects/link/endpoints.ts +2 -1
  209. package/src/objects/query/executor.ts +42 -11
  210. package/src/objects/query/explain.ts +11 -0
  211. package/src/objects/query/index.ts +6 -0
  212. package/src/objects/query/ir.ts +16 -0
  213. package/src/objects/query/links.ts +308 -0
  214. package/src/objects/query/normalize.ts +40 -1
  215. package/src/objects/query/planner.ts +5 -0
  216. package/src/objects/query/validate.ts +58 -2
  217. package/src/ontology/internal.ts +1 -1
  218. package/src/ontology/json-schema.ts +27 -5
  219. package/src/projections/builders.ts +220 -15
  220. package/src/projections/index.ts +1 -0
  221. package/src/projections/ownership.ts +5 -5
  222. package/src/projections/registry.ts +9 -3
  223. package/src/projections/revision.ts +31 -5
  224. package/src/projections/run-dispatch.ts +10 -1
  225. package/src/projections/types.ts +13 -9
  226. package/src/projections/validation.ts +61 -19
  227. package/src/query.ts +2 -0
  228. package/src/runtime/create.ts +4 -0
  229. package/src/runtime/definitions.ts +3 -0
  230. package/src/runtime/host.ts +2 -0
  231. package/src/runtime/resolve-definitions.ts +28 -0
  232. package/src/storage/agents/in-memory.ts +15 -0
  233. package/src/storage/agents/types.ts +5 -0
  234. package/src/storage/ai-usage/in-memory.ts +23 -0
  235. package/src/storage/ai-usage/index.ts +1 -0
  236. package/src/storage/ai-usage/types.ts +10 -0
  237. package/src/storage/index.ts +11 -0
  238. package/src/storage/objects/in-memory.ts +103 -16
  239. package/src/storage/objects/index.ts +9 -0
  240. package/src/storage/objects/keys.ts +36 -0
  241. package/src/storage/objects/types.ts +34 -6
  242. package/src/storage/ontology/provider-header-validation.ts +2 -2
  243. package/src/storage/timeseries/store.ts +6 -6
  244. package/src/testing/agent-storage-contract.ts +12 -0
  245. package/src/testing/ai-usage-storage-contract.ts +35 -0
  246. package/src/testing/effective-storage-contract.ts +194 -4
  247. package/src/testing/lake-storage-contract.ts +56 -0
  248. package/src/testing/object-query-contract.ts +208 -1
  249. package/dist/agents/prompt.d.ts +0 -21
  250. package/dist/agents/prompt.d.ts.map +0 -1
  251. package/dist/chunk-4z3n1dzt.js.map +0 -23
  252. package/dist/chunk-6wetht33.js +0 -89
  253. package/dist/chunk-6wetht33.js.map +0 -10
  254. package/dist/chunk-88ppkr54.js.map +0 -12
  255. package/dist/chunk-f1cyvnrk.js.map +0 -13
  256. package/dist/chunk-ttba8x6z.js.map +0 -15
  257. package/dist/chunk-wb4051cx.js.map +0 -12
  258. package/dist/chunk-zpw39qhj.js.map +0 -10
  259. package/src/agents/prompt.ts +0 -85
  260. /package/dist/{chunk-c6cfqydk.js.map → chunk-4h947jd8.js.map} +0 -0
  261. /package/dist/{chunk-gqdd7508.js.map → chunk-4rh2m6zg.js.map} +0 -0
  262. /package/dist/{chunk-pxtrxm3p.js.map → chunk-a09jx26t.js.map} +0 -0
  263. /package/dist/{chunk-4p9rh7jj.js.map → chunk-ea73pzk7.js.map} +0 -0
  264. /package/dist/{chunk-4aw0jwk0.js.map → chunk-f6erf2vv.js.map} +0 -0
  265. /package/dist/{chunk-c8bw2b6c.js.map → chunk-gadsm794.js.map} +0 -0
  266. /package/dist/{chunk-n5x5y80a.js.map → chunk-nzw7sm3b.js.map} +0 -0
  267. /package/dist/{chunk-261ag4t4.js.map → chunk-r0rry8dn.js.map} +0 -0
  268. /package/dist/{chunk-d2adj15j.js.map → chunk-tkdscva6.js.map} +0 -0
  269. /package/dist/{chunk-z8j83gzd.js.map → chunk-x2yw73hy.js.map} +0 -0
  270. /package/dist/{chunk-qer6am8w.js.map → chunk-xdf9yswn.js.map} +0 -0
  271. /package/dist/{chunk-km4rkj4t.js.map → chunk-zp2v2rv6.js.map} +0 -0
@@ -145,6 +145,41 @@ export function runAiUsageStorageContractSuite<TStorage extends AiUsageStorage>(
145
145
  })
146
146
  })
147
147
 
148
+ test("returns the latest completed call for one execution", async () => {
149
+ await withStorage(async (storage) => {
150
+ await expect(
151
+ storage.getLatestForExecution({ projectId, executionId: agentExecutionId })
152
+ ).resolves.toBeNull()
153
+
154
+ await storage.recordModelCall(
155
+ modelCallInput({
156
+ id: "usage_later",
157
+ callId: "call_later",
158
+ responseId: "response_later",
159
+ occurredAt: at("2026-06-23T10:02:00.000Z"),
160
+ })
161
+ )
162
+ await storage.recordModelCall(
163
+ modelCallInput({
164
+ id: "usage_earlier",
165
+ callId: "call_earlier",
166
+ responseId: "response_earlier",
167
+ occurredAt: at("2026-06-23T10:01:00.000Z"),
168
+ })
169
+ )
170
+
171
+ await expect(
172
+ storage.getLatestForExecution({ projectId, executionId: agentExecutionId })
173
+ ).resolves.toMatchObject({ id: "usage_later", responseId: "response_later" })
174
+ await expect(
175
+ storage.getLatestForExecution({
176
+ projectId: "other-project",
177
+ executionId: agentExecutionId,
178
+ })
179
+ ).resolves.toBeNull()
180
+ })
181
+ })
182
+
148
183
  test("bills the same call and response IDs again on a later delivery attempt", async () => {
149
184
  // Regression guard: remove `attempt` from a provider's idempotency key/query/index and the
150
185
  // second append collapses into the first, making the aggregate assertions fail.
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, test } from "bun:test"
2
2
  import { defineObjectType, link, OntologyRegistry, prop } from "../ontology"
3
- import type { Storage } from "../storage"
3
+ import { linkBatchKey, objectBatchKey, objectLinkCursor, type Storage } from "../storage"
4
4
  import { createMaterializerTestFixture } from "./materializer-fixture"
5
5
 
6
6
  export interface EffectiveStorageContractSuiteOptions<TStorage extends Storage> {
@@ -19,7 +19,25 @@ const Device = defineObjectType({
19
19
  ],
20
20
  links: [link.self("peers", { cardinality: "many" })],
21
21
  })
22
- const ontology = new OntologyRegistry({ sources: [Device] })
22
+ const OpaqueA = defineObjectType({
23
+ id: "A",
24
+ name: "Opaque A",
25
+ properties: [
26
+ prop("id", "string", { primary: true, required: true }),
27
+ prop("name", "string", { required: true }),
28
+ ],
29
+ links: [link.self("D", { cardinality: "many" })],
30
+ })
31
+ const OpaqueAB = defineObjectType({
32
+ id: "A:B",
33
+ name: "Opaque AB",
34
+ properties: [
35
+ prop("id", "string", { primary: true, required: true }),
36
+ prop("name", "string", { required: true }),
37
+ ],
38
+ links: [link.self("D", { cardinality: "many" })],
39
+ })
40
+ const ontology = new OntologyRegistry({ sources: [Device, OpaqueA, OpaqueAB] })
23
41
 
24
42
  export function runEffectiveStorageContractSuite<TStorage extends Storage>(
25
43
  name: string,
@@ -56,7 +74,7 @@ export function runEffectiveStorageContractSuite<TStorage extends Storage>(
56
74
  { objectTypeId: Device.id, primaryId: "missing" },
57
75
  ],
58
76
  })
59
- expect([...batch.keys()]).toEqual([`${Device.id}:a`])
77
+ expect([...batch.keys()]).toEqual([objectBatchKey(Device.id, "a")])
60
78
  })
61
79
  })
62
80
 
@@ -81,7 +99,179 @@ export function runEffectiveStorageContractSuite<TStorage extends Storage>(
81
99
  projectId,
82
100
  items: [{ objectTypeId: Device.id, objectId: "a", linkId: "peers" }],
83
101
  })
84
- expect(linksByScope.get(`${Device.id}:a:peers`)).toHaveLength(2)
102
+ expect(linksByScope.get(linkBatchKey(Device.id, "a", "peers"))).toHaveLength(2)
103
+ })
104
+ })
105
+
106
+ test("pages and filters incident links in the provider", async () => {
107
+ await withStorage(async (storage) => {
108
+ const first = await storage.objects.queryLinks({
109
+ projectId,
110
+ objectRefs: [{ objectTypeId: Device.id, primaryId: "a" }],
111
+ direction: "outgoing",
112
+ linkId: "peers",
113
+ endpointObjectTypeIds: [Device.id],
114
+ limit: 1,
115
+ })
116
+ expect(first.links.map((row) => row.targetId)).toEqual(["b"])
117
+ expect(first.hasMore).toBe(true)
118
+
119
+ const second = await storage.objects.queryLinks({
120
+ projectId,
121
+ objectRefs: [{ objectTypeId: Device.id, primaryId: "a" }],
122
+ direction: "outgoing",
123
+ linkId: "peers",
124
+ endpointObjectTypeIds: [Device.id],
125
+ after: objectLinkCursor(first.links[0]),
126
+ limit: 1,
127
+ })
128
+ expect(second.links.map((row) => row.targetId)).toEqual(["c"])
129
+ expect(second.hasMore).toBe(false)
130
+
131
+ const duplicateRefs = await storage.objects.queryLinks({
132
+ projectId,
133
+ objectRefs: [
134
+ { objectTypeId: Device.id, primaryId: "a" },
135
+ { objectTypeId: Device.id, primaryId: "a" },
136
+ ],
137
+ direction: "outgoing",
138
+ limit: 10,
139
+ })
140
+ expect(duplicateRefs.links.map((row) => row.targetId)).toEqual(["b", "c"])
141
+
142
+ const incoming = await storage.objects.queryLinks({
143
+ projectId,
144
+ objectRefs: [{ objectTypeId: Device.id, primaryId: "b" }],
145
+ direction: "incoming",
146
+ limit: 10,
147
+ })
148
+ expect(incoming.links.map((row) => [row.sourceId, row.targetId])).toEqual([["a", "b"]])
149
+
150
+ const bothDirections = await storage.objects.queryLinks({
151
+ projectId,
152
+ objectRefs: [
153
+ { objectTypeId: Device.id, primaryId: "a" },
154
+ { objectTypeId: Device.id, primaryId: "b" },
155
+ ],
156
+ direction: "both",
157
+ endpointObjectTypeIds: [Device.id],
158
+ limit: 10,
159
+ })
160
+ expect(bothDirections.links.map((row) => [row.sourceId, row.targetId])).toEqual([
161
+ ["a", "b"],
162
+ ["a", "c"],
163
+ ])
164
+
165
+ const unauthorized = await storage.objects.queryLinks({
166
+ projectId,
167
+ objectRefs: [{ objectTypeId: Device.id, primaryId: "a" }],
168
+ direction: "both",
169
+ endpointObjectTypeIds: [],
170
+ limit: 10,
171
+ })
172
+ expect(unauthorized).toEqual({ links: [], hasMore: false })
173
+ })
174
+ })
175
+
176
+ test("keeps delimiter-bearing object and batch-link identities distinct", async () => {
177
+ await withStorage(async (storage) => {
178
+ const opaqueProjectId = `${projectId}-opaque-batch-keys`
179
+ const fixture = createMaterializerTestFixture({
180
+ projectId: opaqueProjectId,
181
+ ontology,
182
+ storage,
183
+ })
184
+ await fixture.seed({
185
+ objects: [
186
+ {
187
+ ref: { objectTypeId: OpaqueA.id, primaryId: "B:C" },
188
+ properties: { id: "B:C", name: "First" },
189
+ },
190
+ {
191
+ ref: { objectTypeId: OpaqueAB.id, primaryId: "C" },
192
+ properties: { id: "C", name: "Second" },
193
+ },
194
+ ],
195
+ links: [
196
+ {
197
+ ref: {
198
+ source: { objectTypeId: OpaqueA.id, primaryId: "B:C" },
199
+ linkId: "D",
200
+ target: { objectTypeId: OpaqueA.id, primaryId: "B:C" },
201
+ },
202
+ },
203
+ {
204
+ ref: {
205
+ source: { objectTypeId: OpaqueAB.id, primaryId: "C" },
206
+ linkId: "D",
207
+ target: { objectTypeId: OpaqueAB.id, primaryId: "C" },
208
+ },
209
+ },
210
+ ],
211
+ })
212
+
213
+ const objects = await storage.objects.getByPrimaryIdBatch({
214
+ projectId: opaqueProjectId,
215
+ items: [
216
+ { objectTypeId: OpaqueA.id, primaryId: "B:C" },
217
+ { objectTypeId: OpaqueAB.id, primaryId: "C" },
218
+ ],
219
+ })
220
+ expect(objects.get(objectBatchKey(OpaqueA.id, "B:C"))?.properties.name).toBe("First")
221
+ expect(objects.get(objectBatchKey(OpaqueAB.id, "C"))?.properties.name).toBe("Second")
222
+
223
+ const links = await storage.objects.listLinksBatch({
224
+ projectId: opaqueProjectId,
225
+ items: [
226
+ { objectTypeId: OpaqueA.id, objectId: "B:C", linkId: "D" },
227
+ { objectTypeId: OpaqueAB.id, objectId: "C", linkId: "D" },
228
+ ],
229
+ })
230
+ expect(links.get(linkBatchKey(OpaqueA.id, "B:C", "D"))).toHaveLength(1)
231
+ expect(links.get(linkBatchKey(OpaqueAB.id, "C", "D"))).toHaveLength(1)
232
+ })
233
+ })
234
+
235
+ test("preserves distinct incident links when opaque ids contain delimiters", async () => {
236
+ await withStorage(async (storage) => {
237
+ const opaqueIdsProjectId = `${projectId}-opaque-link-ids`
238
+ const firstSourceId = "opaque:source"
239
+ const firstTargetId = `target:peers:${Device.id}:opaque:end`
240
+ const secondSourceId = `${firstSourceId}:peers:${Device.id}:target`
241
+ const secondTargetId = "opaque:end"
242
+ const fixture = createMaterializerTestFixture({
243
+ projectId: opaqueIdsProjectId,
244
+ ontology,
245
+ storage,
246
+ })
247
+ await fixture.seed({
248
+ objects: [
249
+ device(firstSourceId, "First source"),
250
+ device(firstTargetId, "First target"),
251
+ device(secondSourceId, "Second source"),
252
+ device(secondTargetId, "Second target"),
253
+ ],
254
+ links: [peer(firstSourceId, firstTargetId), peer(secondSourceId, secondTargetId)],
255
+ })
256
+
257
+ const incident = await storage.objects.listIncidentLinksBatch({
258
+ projectId: opaqueIdsProjectId,
259
+ items: [
260
+ { objectTypeId: Device.id, objectId: firstSourceId },
261
+ { objectTypeId: Device.id, objectId: secondSourceId },
262
+ ],
263
+ })
264
+ const matching = incident.filter(
265
+ (row) => row.sourceId === firstSourceId || row.sourceId === secondSourceId
266
+ )
267
+
268
+ expect(matching.map((row) => [row.sourceId, row.linkId, row.targetId])).toEqual(
269
+ expect.arrayContaining([
270
+ [firstSourceId, "peers", firstTargetId],
271
+ [secondSourceId, "peers", secondTargetId],
272
+ ])
273
+ )
274
+ expect(matching).toHaveLength(2)
85
275
  })
86
276
  })
87
277
 
@@ -438,6 +438,62 @@ export function runLakeStorageContractSuite<TStorage extends LakeStorage>(
438
438
  })
439
439
  })
440
440
 
441
+ test("creates an initial empty snapshot version", async () => {
442
+ await withStorage(async (storage) => {
443
+ await storage.createDataset(writeDataset)
444
+
445
+ const write = await storage.beginWrite({ dataset: writeDataset, mode: "snapshot" })
446
+ const version = await write.commit()
447
+
448
+ expect(version).toMatchObject({
449
+ datasetId: writeDataset.id,
450
+ mode: "snapshot",
451
+ outcome: "created",
452
+ rowCount: 0,
453
+ })
454
+ expect(await storage.getLatestVersion(writeDataset.id)).toMatchObject({
455
+ versionId: version.versionId,
456
+ })
457
+ expect(await storage.listVersions(writeDataset.id)).toHaveLength(1)
458
+
459
+ const repeatedWrite = await storage.beginWrite({
460
+ dataset: writeDataset,
461
+ mode: "snapshot",
462
+ })
463
+ const repeatedVersion = await repeatedWrite.commit()
464
+ expect(repeatedVersion.outcome).toBe("unchanged")
465
+ expect(repeatedVersion.versionId).toBe(version.versionId)
466
+ expect(await storage.listVersions(writeDataset.id)).toHaveLength(1)
467
+
468
+ await expect(
469
+ collectRows(storage.readRows({ datasetId: writeDataset.id }))
470
+ ).resolves.toEqual([])
471
+ })
472
+ })
473
+
474
+ test("creates an initial empty append version", async () => {
475
+ await withStorage(async (storage) => {
476
+ await storage.createDataset(writeDataset)
477
+
478
+ const write = await storage.beginWrite({ dataset: writeDataset, mode: "append" })
479
+ const version = await write.commit()
480
+
481
+ expect(version).toMatchObject({
482
+ datasetId: writeDataset.id,
483
+ mode: "append",
484
+ outcome: "created",
485
+ })
486
+ expect(version.parentVersionId).toBeUndefined()
487
+ expect(await storage.getLatestVersion(writeDataset.id)).toMatchObject({
488
+ versionId: version.versionId,
489
+ })
490
+ expect(await storage.listVersions(writeDataset.id)).toHaveLength(1)
491
+ await expect(
492
+ collectRows(storage.readRows({ datasetId: writeDataset.id }))
493
+ ).resolves.toEqual([])
494
+ })
495
+ })
496
+
441
497
  test("snapshot writes replace the visible latest rows", async () => {
442
498
  await withStorage(async (storage) => {
443
499
  await storage.createDataset(writeDataset)
@@ -4,6 +4,7 @@ import {
4
4
  collectObjectQueryValidationIssues,
5
5
  countObjects,
6
6
  executeObjectQuery,
7
+ executeObjectQueryLinks,
7
8
  existsObjects,
8
9
  facetObjects,
9
10
  normalizeObjectQuery,
@@ -145,7 +146,7 @@ export const objectQueryContractOntology = new OntologyRegistry({
145
146
  *
146
147
  * The contract defines the portable V1 query surface: capability declarations,
147
148
  * validation/normalization handoff, provider pushdown, bounded fallback,
148
- * traversal, set operations, pagination, search profile defaults, and stable
149
+ * canonical reference sets, traversal, set operations, pagination, search profile defaults, and stable
149
150
  * structured rejections for features outside a provider's capability map.
150
151
  */
151
152
  export function runObjectQueryProviderContractSuite<TStorage extends Storage>(
@@ -345,6 +346,212 @@ export function runObjectQueryProviderContractSuite<TStorage extends Storage>(
345
346
  })
346
347
  })
347
348
 
349
+ test("queries opaque ids through canonical exact refs", async () => {
350
+ await withStorage(async ({ objects: storage, fixture }) => {
351
+ const issue297 = "github:issue:sixb-ai/sixb#297"
352
+ const issue298 = "github:issue:sixb-ai/sixb#298"
353
+ await fixture.seed({
354
+ objects: [
355
+ objectSeed(Asset.id, issue297, { id: issue297 }),
356
+ objectSeed(Asset.id, issue298, { id: issue298 }),
357
+ ],
358
+ })
359
+
360
+ const refs = await executeObjectQuery(
361
+ {
362
+ projectId,
363
+ query: {
364
+ kind: "refs",
365
+ refs: [
366
+ { objectTypeId: Asset.id, primaryId: issue298 },
367
+ { objectTypeId: Asset.id, primaryId: issue297 },
368
+ ],
369
+ },
370
+ },
371
+ { ontology: objectQueryContractOntology, storage }
372
+ )
373
+
374
+ // The JSON query body preserves URL-reserved characters without encoding.
375
+ expect(refs.plan.mode).toBe(
376
+ storage.queryCapabilities().nodes?.refs === true ? "pushdown" : "fallback"
377
+ )
378
+ expect(ids(refs)).toEqual([issue297, issue298])
379
+ })
380
+ })
381
+
382
+ test("executes canonical heterogeneous refs with pagination and projection", async () => {
383
+ await withStorage(async ({ objects: storage, fixture }) => {
384
+ await seedObjectQueryContractData(fixture)
385
+
386
+ const refs: Extract<ObjectQuery, { kind: "refs" }>["refs"] = [
387
+ { objectTypeId: Device.id, primaryId: "device-sensor" },
388
+ { objectTypeId: Room.id, primaryId: "room-gamma" },
389
+ { objectTypeId: Room.id, primaryId: "missing" },
390
+ { objectTypeId: Room.id, primaryId: "room-alpha" },
391
+ ]
392
+ const first = await executeObjectQuery(
393
+ {
394
+ projectId,
395
+ query: {
396
+ kind: "project",
397
+ properties: ["id"],
398
+ input: { kind: "page", pageSize: 2, input: { kind: "refs", refs } },
399
+ },
400
+ },
401
+ { ontology: objectQueryContractOntology, storage }
402
+ )
403
+ const second = await executeObjectQuery(
404
+ {
405
+ projectId,
406
+ query: {
407
+ kind: "project",
408
+ properties: ["id"],
409
+ input: {
410
+ kind: "page",
411
+ pageSize: 2,
412
+ pageToken: first.nextPageToken,
413
+ input: { kind: "refs", refs },
414
+ },
415
+ },
416
+ },
417
+ { ontology: objectQueryContractOntology, storage }
418
+ )
419
+ const count = await countObjects(
420
+ { projectId, query: { kind: "refs", refs } },
421
+ { ontology: objectQueryContractOntology, storage }
422
+ )
423
+
424
+ const expectedMode =
425
+ storage.queryCapabilities().nodes?.refs === true ? "pushdown" : "fallback"
426
+ expect(first.plan.mode).toBe(expectedMode)
427
+ expect(ids(first)).toEqual(["device-sensor", "room-alpha"])
428
+ expect(first.objects.map((row) => row.properties)).toEqual([
429
+ { id: "device-sensor" },
430
+ { id: "room-alpha" },
431
+ ])
432
+ expect(first.total).toBe(3)
433
+ expect(first.hasMore).toBe(true)
434
+ expect(first.nextPageToken).toBeTruthy()
435
+ expect(second.plan.mode).toBe(expectedMode)
436
+ expect(ids(second)).toEqual(["room-gamma"])
437
+ expect(second.hasMore).toBe(false)
438
+ expect(count.plan.mode).toBe(expectedMode)
439
+ expect(count.count).toBe(3)
440
+ })
441
+ })
442
+
443
+ test("composes refs with traversal in provider pushdown", async () => {
444
+ await withStorage(async ({ objects: storage, fixture }) => {
445
+ if (storage.queryCapabilities().nodes?.refs !== true) return
446
+ await seedObjectQueryContractData(fixture)
447
+
448
+ const result = await executeObjectQuery(
449
+ {
450
+ projectId,
451
+ query: {
452
+ kind: "traverse",
453
+ direction: "outgoing",
454
+ linkId: "hasDevice",
455
+ input: {
456
+ kind: "refs",
457
+ refs: [{ objectTypeId: Room.id, primaryId: "room-alpha" }],
458
+ },
459
+ },
460
+ },
461
+ { ontology: objectQueryContractOntology, storage }
462
+ )
463
+
464
+ expect(result.plan.mode).toBe("pushdown")
465
+ expect(ids(result)).toEqual(["device-projector"])
466
+ })
467
+ })
468
+
469
+ test("queries and paginates incident links over a provider-backed object set", async () => {
470
+ await withStorage(async ({ objects: storage, fixture }) => {
471
+ await seedObjectQueryContractData(fixture)
472
+ const query: ObjectQuery = {
473
+ kind: "refs",
474
+ refs: [{ objectTypeId: Device.id, primaryId: "device-projector" }],
475
+ }
476
+
477
+ const first = await executeObjectQueryLinks(
478
+ {
479
+ projectId,
480
+ query,
481
+ direction: "incoming",
482
+ includeObjects: true,
483
+ pageSize: 1,
484
+ },
485
+ { ontology: objectQueryContractOntology, storage }
486
+ )
487
+ const second = await executeObjectQueryLinks(
488
+ {
489
+ projectId,
490
+ query,
491
+ direction: "incoming",
492
+ includeObjects: true,
493
+ pageSize: 1,
494
+ pageToken: first.nextPageToken,
495
+ },
496
+ { ontology: objectQueryContractOntology, storage }
497
+ )
498
+
499
+ expect(first.links).toEqual([
500
+ expect.objectContaining({
501
+ sourceTypeId: Room.id,
502
+ sourceId: "room-alpha",
503
+ linkId: "hasDevice",
504
+ targetTypeId: Device.id,
505
+ targetId: "device-projector",
506
+ }),
507
+ ])
508
+ expect(first.objects.map((row) => row.primaryId)).toEqual([
509
+ "device-projector",
510
+ "room-alpha",
511
+ ])
512
+ expect(first.hasMore).toBe(true)
513
+ expect(first.nextPageToken).toBeTruthy()
514
+ expect(second.links).toEqual([
515
+ expect.objectContaining({
516
+ sourceTypeId: Zone.id,
517
+ sourceId: "zone-one",
518
+ linkId: "hasDevice",
519
+ targetTypeId: Device.id,
520
+ targetId: "device-projector",
521
+ }),
522
+ ])
523
+ expect(second.objects.map((row) => row.primaryId)).toEqual(["device-projector", "zone-one"])
524
+ expect(second.hasMore).toBe(false)
525
+ })
526
+ })
527
+
528
+ test("does not admit a provider page probe into the link selector", async () => {
529
+ await withStorage(async ({ objects: storage, fixture }) => {
530
+ await seedObjectQueryContractData(fixture)
531
+
532
+ const result = await executeObjectQueryLinks(
533
+ {
534
+ projectId,
535
+ query: {
536
+ kind: "page",
537
+ pageSize: 1,
538
+ input: {
539
+ kind: "sort",
540
+ fields: [{ kind: "property", propertyId: "id", direction: "asc" }],
541
+ input: { kind: "start", objectTypeId: Room.id },
542
+ },
543
+ },
544
+ direction: "outgoing",
545
+ },
546
+ { ontology: objectQueryContractOntology, storage }
547
+ )
548
+
549
+ expect(result.links).toEqual([
550
+ expect.objectContaining({ sourceId: "room-alpha", targetId: "device-projector" }),
551
+ ])
552
+ })
553
+ })
554
+
348
555
  test("matches null, missing, neq, in, and not predicate semantics", async () => {
349
556
  await withStorage(async ({ objects: storage, fixture }) => {
350
557
  await seedObjectQueryContractData(fixture)
@@ -1,21 +0,0 @@
1
- export declare const DEFAULT_AGENT_SYSTEM_CONTEXT: string;
2
- export declare const DEFAULT_AGENT_WORKFLOW_SYSTEM_CONTEXT: string;
3
- export declare const DEFAULT_WORKFLOW_OUTPUT_FINALIZER_SYSTEM_CONTEXT: string;
4
- export interface BuildAgentSystemPromptInput {
5
- readonly instructions: string;
6
- readonly addendum?: string;
7
- readonly mode?: "conversation" | "workflow";
8
- }
9
- export interface BuildWorkflowOutputFinalizerPromptInput {
10
- readonly instructions: string;
11
- }
12
- /**
13
- * Compose the framework-owned system prompt for every agent turn.
14
- *
15
- * Core Sixb rules are first and explicitly separated from runtime context and project-authored
16
- * agent instructions so models can distinguish platform behavior from agent-specific goals.
17
- */
18
- export declare function buildAgentSystemPrompt(input: BuildAgentSystemPromptInput): string;
19
- /** Compose the system prompt for the tool-free workflow output projection call. */
20
- export declare function buildWorkflowOutputFinalizerPrompt(input: BuildWorkflowOutputFinalizerPromptInput): string;
21
- //# sourceMappingURL=prompt.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/agents/prompt.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,4BAA4B,QAS7B,CAAA;AAEZ,eAAO,MAAM,qCAAqC,QAKtC,CAAA;AAEZ,eAAO,MAAM,gDAAgD,QASjD,CAAA;AAWZ,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,cAAc,GAAG,UAAU,CAAA;CAC5C;AAED,MAAM,WAAW,uCAAuC;IACtD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;CAC9B;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,2BAA2B,GAAG,MAAM,CAgBjF;AAED,mFAAmF;AACnF,wBAAgB,kCAAkC,CAChD,KAAK,EAAE,uCAAuC,GAC7C,MAAM,CAKR"}