@cavelang/cli 0.27.14 → 0.29.1

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 (321) hide show
  1. package/Authors.md +5 -0
  2. package/License.md +6 -0
  3. package/README.md +122 -24
  4. package/dist/internal/act/action.d.ts +69 -0
  5. package/dist/internal/act/action.d.ts.map +1 -0
  6. package/dist/internal/act/action.js +201 -0
  7. package/dist/internal/act/action.js.map +1 -0
  8. package/dist/internal/act/declare.d.ts +102 -0
  9. package/dist/internal/act/declare.d.ts.map +1 -0
  10. package/dist/internal/act/declare.js +270 -0
  11. package/dist/internal/act/declare.js.map +1 -0
  12. package/dist/internal/act/engine.d.ts +103 -0
  13. package/dist/internal/act/engine.d.ts.map +1 -0
  14. package/dist/internal/act/engine.js +298 -0
  15. package/dist/internal/act/engine.js.map +1 -0
  16. package/dist/internal/act/index.d.ts +27 -0
  17. package/dist/internal/act/index.d.ts.map +1 -0
  18. package/dist/internal/act/index.js +25 -0
  19. package/dist/internal/act/index.js.map +1 -0
  20. package/dist/internal/automate/automation.d.ts +78 -0
  21. package/dist/internal/automate/automation.d.ts.map +1 -0
  22. package/dist/internal/automate/automation.js +135 -0
  23. package/dist/internal/automate/automation.js.map +1 -0
  24. package/dist/internal/automate/declare.d.ts +84 -0
  25. package/dist/internal/automate/declare.d.ts.map +1 -0
  26. package/dist/internal/automate/declare.js +233 -0
  27. package/dist/internal/automate/declare.js.map +1 -0
  28. package/dist/internal/automate/engine.d.ts +125 -0
  29. package/dist/internal/automate/engine.d.ts.map +1 -0
  30. package/dist/internal/automate/engine.js +388 -0
  31. package/dist/internal/automate/engine.js.map +1 -0
  32. package/dist/internal/automate/index.d.ts +28 -0
  33. package/dist/internal/automate/index.d.ts.map +1 -0
  34. package/dist/internal/automate/index.js +26 -0
  35. package/dist/internal/automate/index.js.map +1 -0
  36. package/dist/internal/automate/main.d.ts +26 -0
  37. package/dist/internal/automate/main.d.ts.map +1 -0
  38. package/dist/internal/automate/main.js +298 -0
  39. package/dist/internal/automate/main.js.map +1 -0
  40. package/dist/internal/connect/index.d.ts +26 -0
  41. package/dist/internal/connect/index.d.ts.map +1 -0
  42. package/dist/internal/connect/index.js +24 -0
  43. package/dist/internal/connect/index.js.map +1 -0
  44. package/dist/internal/connect/main.d.ts +23 -0
  45. package/dist/internal/connect/main.d.ts.map +1 -0
  46. package/dist/internal/connect/main.js +330 -0
  47. package/dist/internal/connect/main.js.map +1 -0
  48. package/dist/internal/connect/run.d.ts +85 -0
  49. package/dist/internal/connect/run.d.ts.map +1 -0
  50. package/dist/internal/connect/run.js +242 -0
  51. package/dist/internal/connect/run.js.map +1 -0
  52. package/dist/internal/connect/source.d.ts +44 -0
  53. package/dist/internal/connect/source.d.ts.map +1 -0
  54. package/dist/internal/connect/source.js +215 -0
  55. package/dist/internal/connect/source.js.map +1 -0
  56. package/dist/internal/connect/template.d.ts +69 -0
  57. package/dist/internal/connect/template.d.ts.map +1 -0
  58. package/dist/internal/connect/template.js +221 -0
  59. package/dist/internal/connect/template.js.map +1 -0
  60. package/dist/internal/eval/index.d.ts +28 -0
  61. package/dist/internal/eval/index.d.ts.map +1 -0
  62. package/dist/internal/eval/index.js +27 -0
  63. package/dist/internal/eval/index.js.map +1 -0
  64. package/dist/internal/eval/judge.d.ts +30 -0
  65. package/dist/internal/eval/judge.d.ts.map +1 -0
  66. package/dist/internal/eval/judge.js +101 -0
  67. package/dist/internal/eval/judge.js.map +1 -0
  68. package/dist/internal/eval/loop.d.ts +64 -0
  69. package/dist/internal/eval/loop.d.ts.map +1 -0
  70. package/dist/internal/eval/loop.js +123 -0
  71. package/dist/internal/eval/loop.js.map +1 -0
  72. package/dist/internal/eval/main.d.ts +17 -0
  73. package/dist/internal/eval/main.d.ts.map +1 -0
  74. package/dist/internal/eval/main.js +236 -0
  75. package/dist/internal/eval/main.js.map +1 -0
  76. package/dist/internal/eval/queries.d.ts +74 -0
  77. package/dist/internal/eval/queries.d.ts.map +1 -0
  78. package/dist/internal/eval/queries.js +161 -0
  79. package/dist/internal/eval/queries.js.map +1 -0
  80. package/dist/internal/eval/run.d.ts +143 -0
  81. package/dist/internal/eval/run.d.ts.map +1 -0
  82. package/dist/internal/eval/run.js +376 -0
  83. package/dist/internal/eval/run.js.map +1 -0
  84. package/dist/internal/eval/score.d.ts +81 -0
  85. package/dist/internal/eval/score.d.ts.map +1 -0
  86. package/dist/internal/eval/score.js +126 -0
  87. package/dist/internal/eval/score.js.map +1 -0
  88. package/dist/internal/eval/suite.d.ts +66 -0
  89. package/dist/internal/eval/suite.d.ts.map +1 -0
  90. package/dist/internal/eval/suite.js +130 -0
  91. package/dist/internal/eval/suite.js.map +1 -0
  92. package/dist/internal/ingest/context.d.ts +20 -0
  93. package/dist/internal/ingest/context.d.ts.map +1 -0
  94. package/dist/internal/ingest/context.js +59 -0
  95. package/dist/internal/ingest/context.js.map +1 -0
  96. package/dist/internal/ingest/files.d.ts +46 -0
  97. package/dist/internal/ingest/files.d.ts.map +1 -0
  98. package/dist/internal/ingest/files.js +115 -0
  99. package/dist/internal/ingest/files.js.map +1 -0
  100. package/dist/internal/ingest/index.d.ts +31 -0
  101. package/dist/internal/ingest/index.d.ts.map +1 -0
  102. package/dist/internal/ingest/index.js +29 -0
  103. package/dist/internal/ingest/index.js.map +1 -0
  104. package/dist/internal/ingest/main.d.ts +12 -0
  105. package/dist/internal/ingest/main.d.ts.map +1 -0
  106. package/dist/internal/ingest/main.js +180 -0
  107. package/dist/internal/ingest/main.js.map +1 -0
  108. package/dist/internal/ingest/prompt.d.ts +32 -0
  109. package/dist/internal/ingest/prompt.d.ts.map +1 -0
  110. package/dist/internal/ingest/prompt.js +75 -0
  111. package/dist/internal/ingest/prompt.js.map +1 -0
  112. package/dist/internal/ingest/run.d.ts +142 -0
  113. package/dist/internal/ingest/run.d.ts.map +1 -0
  114. package/dist/internal/ingest/run.js +350 -0
  115. package/dist/internal/ingest/run.js.map +1 -0
  116. package/dist/internal/ingest/web.d.ts +48 -0
  117. package/dist/internal/ingest/web.d.ts.map +1 -0
  118. package/dist/internal/ingest/web.js +140 -0
  119. package/dist/internal/ingest/web.js.map +1 -0
  120. package/dist/internal/loop/demo.d.ts +22 -0
  121. package/dist/internal/loop/demo.d.ts.map +1 -0
  122. package/dist/internal/loop/demo.js +67 -0
  123. package/dist/internal/loop/demo.js.map +1 -0
  124. package/dist/internal/loop/index.d.ts +20 -0
  125. package/dist/internal/loop/index.d.ts.map +1 -0
  126. package/dist/internal/loop/index.js +17 -0
  127. package/dist/internal/loop/index.js.map +1 -0
  128. package/dist/internal/loop/llm.d.ts +99 -0
  129. package/dist/internal/loop/llm.d.ts.map +1 -0
  130. package/dist/internal/loop/llm.js +231 -0
  131. package/dist/internal/loop/llm.js.map +1 -0
  132. package/dist/internal/loop/reconstruct.d.ts +87 -0
  133. package/dist/internal/loop/reconstruct.d.ts.map +1 -0
  134. package/dist/internal/loop/reconstruct.js +157 -0
  135. package/dist/internal/loop/reconstruct.js.map +1 -0
  136. package/dist/internal/loop/sqlite.d.ts +13 -0
  137. package/dist/internal/loop/sqlite.d.ts.map +1 -0
  138. package/dist/internal/loop/sqlite.js +33 -0
  139. package/dist/internal/loop/sqlite.js.map +1 -0
  140. package/dist/internal/loop/store.d.ts +50 -0
  141. package/dist/internal/loop/store.d.ts.map +1 -0
  142. package/dist/internal/loop/store.js +100 -0
  143. package/dist/internal/loop/store.js.map +1 -0
  144. package/dist/internal/mcp/bin.d.ts +7 -0
  145. package/dist/internal/mcp/bin.d.ts.map +1 -0
  146. package/dist/internal/mcp/bin.js +8 -0
  147. package/dist/internal/mcp/bin.js.map +1 -0
  148. package/dist/internal/mcp/index.d.ts +25 -0
  149. package/dist/internal/mcp/index.d.ts.map +1 -0
  150. package/dist/internal/mcp/index.js +23 -0
  151. package/dist/internal/mcp/index.js.map +1 -0
  152. package/dist/internal/mcp/main.d.ts +23 -0
  153. package/dist/internal/mcp/main.d.ts.map +1 -0
  154. package/dist/internal/mcp/main.js +156 -0
  155. package/dist/internal/mcp/main.js.map +1 -0
  156. package/dist/internal/mcp/server.d.ts +92 -0
  157. package/dist/internal/mcp/server.d.ts.map +1 -0
  158. package/dist/internal/mcp/server.js +251 -0
  159. package/dist/internal/mcp/server.js.map +1 -0
  160. package/dist/internal/mcp/tools.d.ts +91 -0
  161. package/dist/internal/mcp/tools.d.ts.map +1 -0
  162. package/dist/internal/mcp/tools.js +584 -0
  163. package/dist/internal/mcp/tools.js.map +1 -0
  164. package/dist/internal/rules/declare.d.ts +58 -0
  165. package/dist/internal/rules/declare.d.ts.map +1 -0
  166. package/dist/internal/rules/declare.js +152 -0
  167. package/dist/internal/rules/declare.js.map +1 -0
  168. package/dist/internal/rules/engine.d.ts +125 -0
  169. package/dist/internal/rules/engine.d.ts.map +1 -0
  170. package/dist/internal/rules/engine.js +575 -0
  171. package/dist/internal/rules/engine.js.map +1 -0
  172. package/dist/internal/rules/index.d.ts +23 -0
  173. package/dist/internal/rules/index.d.ts.map +1 -0
  174. package/dist/internal/rules/index.js +21 -0
  175. package/dist/internal/rules/index.js.map +1 -0
  176. package/dist/internal/rules/rule.d.ts +88 -0
  177. package/dist/internal/rules/rule.d.ts.map +1 -0
  178. package/dist/internal/rules/rule.js +221 -0
  179. package/dist/internal/rules/rule.js.map +1 -0
  180. package/dist/internal/shape/check.d.ts +118 -0
  181. package/dist/internal/shape/check.d.ts.map +1 -0
  182. package/dist/internal/shape/check.js +331 -0
  183. package/dist/internal/shape/check.js.map +1 -0
  184. package/dist/internal/shape/client.d.ts +31 -0
  185. package/dist/internal/shape/client.d.ts.map +1 -0
  186. package/dist/internal/shape/client.js +170 -0
  187. package/dist/internal/shape/client.js.map +1 -0
  188. package/dist/internal/shape/gate.d.ts +33 -0
  189. package/dist/internal/shape/gate.d.ts.map +1 -0
  190. package/dist/internal/shape/gate.js +0 -0
  191. package/dist/internal/shape/gate.js.map +1 -0
  192. package/dist/internal/shape/index.d.ts +27 -0
  193. package/dist/internal/shape/index.d.ts.map +1 -0
  194. package/dist/internal/shape/index.js +23 -0
  195. package/dist/internal/shape/index.js.map +1 -0
  196. package/dist/internal/shape/suggest.d.ts +82 -0
  197. package/dist/internal/shape/suggest.d.ts.map +1 -0
  198. package/dist/internal/shape/suggest.js +374 -0
  199. package/dist/internal/shape/suggest.js.map +1 -0
  200. package/dist/internal/sync/index.d.ts +22 -0
  201. package/dist/internal/sync/index.d.ts.map +1 -0
  202. package/dist/internal/sync/index.js +21 -0
  203. package/dist/internal/sync/index.js.map +1 -0
  204. package/dist/internal/sync/sync.d.ts +95 -0
  205. package/dist/internal/sync/sync.d.ts.map +1 -0
  206. package/dist/internal/sync/sync.js +342 -0
  207. package/dist/internal/sync/sync.js.map +1 -0
  208. package/dist/internal/view/api.d.ts +196 -0
  209. package/dist/internal/view/api.d.ts.map +1 -0
  210. package/dist/internal/view/api.js +189 -0
  211. package/dist/internal/view/api.js.map +1 -0
  212. package/dist/internal/view/index.d.ts +33 -0
  213. package/dist/internal/view/index.d.ts.map +1 -0
  214. package/dist/internal/view/index.js +30 -0
  215. package/dist/internal/view/index.js.map +1 -0
  216. package/dist/internal/view/main.d.ts +11 -0
  217. package/dist/internal/view/main.d.ts.map +1 -0
  218. package/dist/internal/view/main.js +98 -0
  219. package/dist/internal/view/main.js.map +1 -0
  220. package/dist/internal/view/page.d.ts +14 -0
  221. package/dist/internal/view/page.d.ts.map +1 -0
  222. package/dist/internal/view/page.js +370 -0
  223. package/dist/internal/view/page.js.map +1 -0
  224. package/dist/internal/view/report.d.ts +52 -0
  225. package/dist/internal/view/report.d.ts.map +1 -0
  226. package/dist/internal/view/report.js +367 -0
  227. package/dist/internal/view/report.js.map +1 -0
  228. package/dist/internal/view/scope.d.ts +11 -0
  229. package/dist/internal/view/scope.d.ts.map +1 -0
  230. package/dist/internal/view/scope.js +41 -0
  231. package/dist/internal/view/scope.js.map +1 -0
  232. package/dist/internal/view/server.d.ts +35 -0
  233. package/dist/internal/view/server.d.ts.map +1 -0
  234. package/dist/internal/view/server.js +141 -0
  235. package/dist/internal/view/server.js.map +1 -0
  236. package/dist/src/act.d.ts +3 -0
  237. package/dist/src/act.d.ts.map +1 -0
  238. package/dist/src/act.js +3 -0
  239. package/dist/src/act.js.map +1 -0
  240. package/dist/src/automate.d.ts +3 -0
  241. package/dist/src/automate.d.ts.map +1 -0
  242. package/dist/src/automate.js +3 -0
  243. package/dist/src/automate.js.map +1 -0
  244. package/dist/src/cli.d.ts +24 -17
  245. package/dist/src/cli.d.ts.map +1 -1
  246. package/dist/src/cli.js +408 -107
  247. package/dist/src/cli.js.map +1 -1
  248. package/dist/src/commands.d.ts +104 -0
  249. package/dist/src/commands.d.ts.map +1 -0
  250. package/dist/src/commands.js +33 -0
  251. package/dist/src/commands.js.map +1 -0
  252. package/dist/src/connect.d.ts +3 -0
  253. package/dist/src/connect.d.ts.map +1 -0
  254. package/dist/src/connect.js +3 -0
  255. package/dist/src/connect.js.map +1 -0
  256. package/dist/src/dispatch.d.ts +14 -0
  257. package/dist/src/dispatch.d.ts.map +1 -0
  258. package/dist/src/dispatch.js +116 -0
  259. package/dist/src/dispatch.js.map +1 -0
  260. package/dist/src/doctor.d.ts +45 -0
  261. package/dist/src/doctor.d.ts.map +1 -0
  262. package/dist/src/doctor.js +284 -0
  263. package/dist/src/doctor.js.map +1 -0
  264. package/dist/src/eval.d.ts +3 -0
  265. package/dist/src/eval.d.ts.map +1 -0
  266. package/dist/src/eval.js +3 -0
  267. package/dist/src/eval.js.map +1 -0
  268. package/dist/src/index.d.ts +9 -2
  269. package/dist/src/index.d.ts.map +1 -1
  270. package/dist/src/index.js +6 -2
  271. package/dist/src/index.js.map +1 -1
  272. package/dist/src/ingest.d.ts +3 -0
  273. package/dist/src/ingest.d.ts.map +1 -0
  274. package/dist/src/ingest.js +3 -0
  275. package/dist/src/ingest.js.map +1 -0
  276. package/dist/src/loop.d.ts +3 -0
  277. package/dist/src/loop.d.ts.map +1 -0
  278. package/dist/src/loop.js +3 -0
  279. package/dist/src/loop.js.map +1 -0
  280. package/dist/src/main.d.ts +1 -1
  281. package/dist/src/main.d.ts.map +1 -1
  282. package/dist/src/main.js +3 -75
  283. package/dist/src/main.js.map +1 -1
  284. package/dist/src/mcp.d.ts +3 -0
  285. package/dist/src/mcp.d.ts.map +1 -0
  286. package/dist/src/mcp.js +3 -0
  287. package/dist/src/mcp.js.map +1 -0
  288. package/dist/src/rules.d.ts +3 -0
  289. package/dist/src/rules.d.ts.map +1 -0
  290. package/dist/src/rules.js +3 -0
  291. package/dist/src/rules.js.map +1 -0
  292. package/dist/src/shape.d.ts +3 -0
  293. package/dist/src/shape.d.ts.map +1 -0
  294. package/dist/src/shape.js +3 -0
  295. package/dist/src/shape.js.map +1 -0
  296. package/dist/src/sync.d.ts +3 -0
  297. package/dist/src/sync.d.ts.map +1 -0
  298. package/dist/src/sync.js +3 -0
  299. package/dist/src/sync.js.map +1 -0
  300. package/dist/src/view.d.ts +3 -0
  301. package/dist/src/view.d.ts.map +1 -0
  302. package/dist/src/view.js +3 -0
  303. package/dist/src/view.js.map +1 -0
  304. package/package.json +81 -21
  305. package/src/act.ts +2 -0
  306. package/src/automate.ts +2 -0
  307. package/src/cli.ts +416 -102
  308. package/src/commands.ts +48 -0
  309. package/src/connect.ts +2 -0
  310. package/src/dispatch.ts +141 -0
  311. package/src/doctor.ts +370 -0
  312. package/src/eval.ts +2 -0
  313. package/src/index.ts +9 -2
  314. package/src/ingest.ts +2 -0
  315. package/src/loop.ts +2 -0
  316. package/src/main.ts +3 -66
  317. package/src/mcp.ts +2 -0
  318. package/src/rules.ts +2 -0
  319. package/src/shape.ts +2 -0
  320. package/src/sync.ts +2 -0
  321. package/src/view.ts +2 -0
@@ -0,0 +1,242 @@
1
+ /**
2
+ * The connect pass (spec §23.2) — instantiate the mapping per record, append
3
+ * through the standard pipeline with record provenance, and keep re-runs
4
+ * row-level incremental via per-record digest claims:
5
+ *
6
+ * ```cave
7
+ * connect/people/42 HAS connect-digest: 93a01c626b3f @src:cave-connect
8
+ * ```
9
+ *
10
+ * Every claim a record produces is auto-stamped `@src:connect/<name>/<key>`
11
+ * (spec §9.5), so a changed record diffs against itself: current claims
12
+ * still carrying the record's stamp but no longer produced by it are
13
+ * retracted (`@ 0%`). `--prune` extends the diff to records that vanished
14
+ * from the source. Explicit `run` provenance is the lifecycle identity;
15
+ * the compatibility stamp is also applied when a template names its own
16
+ * `@src:` context (both are kept).
17
+ */
18
+ import { createHash } from 'node:crypto';
19
+ import { Claim, Key, SourceSpan, Value } from '@cavelang/core';
20
+ import { query as caveQuery } from '@cavelang/query';
21
+ import * as Template from "./template.js";
22
+ export const digestAttribute = 'connect-digest';
23
+ export const provenanceContext = 'src:cave-connect';
24
+ /** First 12 hex chars of SHA-256, mirroring `@cavelang/cli/ingest` (spec §9.5). */
25
+ export const digestOf = (content) => createHash('sha256').update(content).digest('hex').slice(0, 12);
26
+ /**
27
+ * Claim key of a unit's digest claim. The value is excluded from keys
28
+ * (spec §9.2), so the key is stable while the digest evolves.
29
+ */
30
+ const digestKey = (subject) => Key.of(Claim.of({
31
+ subject: Claim.entity(subject),
32
+ verb: 'HAS',
33
+ payload: Claim.attribute(digestAttribute, Value.parse('x')),
34
+ contexts: [provenanceContext]
35
+ }));
36
+ /** @returns `true` when the unit's current digest claim matches `digest`. */
37
+ export const isConnected = (store, subject, digest) => {
38
+ const known = store.currentBelief(digestKey(subject));
39
+ return known !== undefined && known.value_text === digest && known.conf > 0;
40
+ };
41
+ const recordDigest = (store, subject, digest) => {
42
+ store.ingest(`${subject} HAS ${digestAttribute}: ${digest} @${provenanceContext}`);
43
+ };
44
+ const recordFailure = Symbol('cave-connect record failure');
45
+ const failRecord = (problems) => {
46
+ throw { [recordFailure]: true, problems };
47
+ };
48
+ const isRecordError = (error) => typeof error === 'object' && error !== null && recordFailure in error;
49
+ /**
50
+ * Context-safe record key from a field value: runs of characters outside
51
+ * `A-Za-z0-9._-` collapse to `-` (the key rides in an entity name and a
52
+ * `@src:` context — reserved characters would change the line's meaning).
53
+ * Casing is preserved; keys needing exact identity should be shaped in the
54
+ * source.
55
+ */
56
+ const keyOf = (value) => {
57
+ if (value === undefined || value === null) {
58
+ return undefined;
59
+ }
60
+ const text = String(value).trim().replace(/[^A-Za-z0-9._-]+/g, '-').replace(/^-+|-+$/g, '');
61
+ return text === '' ? undefined : text;
62
+ };
63
+ /** In-band vocabulary declarations are append-only and never lifecycle-retracted. */
64
+ const isDeclaration = (row) => row.verb === 'REVERSE' || row.verb === 'RENAMED-TO' ||
65
+ (row.verb === 'IS' && row.object === 'verb');
66
+ /**
67
+ * Retracts current claims carrying `context` that were not (re-)appended in
68
+ * this pass (spec §23.2). Contexts are part of claim identity, so every row
69
+ * of a stamped series carries the stamp — the latest row per key among the
70
+ * stamped rows *is* the series' current belief.
71
+ */
72
+ const retractStale = (store, run, keepIds) => {
73
+ const latest = new Map();
74
+ for (const row of store.byProvenance('run', run)) {
75
+ const seen = latest.get(row.claim_key);
76
+ if (seen === undefined || seen.tx < row.tx) {
77
+ latest.set(row.claim_key, row);
78
+ }
79
+ }
80
+ const stale = [...latest.values()]
81
+ .filter(row => row.conf > 0 && !keepIds.has(row.id) && !isDeclaration(row));
82
+ if (stale.length === 0) {
83
+ return 0;
84
+ }
85
+ store.insertResult({
86
+ claims: stale.map(row => ({
87
+ claim: { ...store.toClaim(row), conf: 0, raw: '', comment: 'retracted: no longer in source' },
88
+ line: 0
89
+ })),
90
+ edges: [],
91
+ registry: store.registry(),
92
+ problems: []
93
+ });
94
+ return stale.length;
95
+ };
96
+ /**
97
+ * One connect pass: prelude (digest-skipped as a unit under
98
+ * `connect/<name>`), then each record (digest-skipped under
99
+ * `connect/<name>/<key>`), then optional pruning. Each unit appends inside
100
+ * its own transaction — a failing record rolls back cleanly and never
101
+ * poisons the rest of the run.
102
+ */
103
+ export const connect = (store, mapping, records, options) => {
104
+ const force = options.force === true;
105
+ // The name rides in entity names and @src: contexts, like record keys.
106
+ const name = keyOf(options.name);
107
+ if (name === undefined) {
108
+ throw new Error(`cave connect: unusable source name ${JSON.stringify(options.name)} — pass --name`);
109
+ }
110
+ const failures = [];
111
+ const notes = [];
112
+ const seen = new Set();
113
+ let mapped = 0;
114
+ let skipped = 0;
115
+ let added = 0;
116
+ let retracted = 0;
117
+ let pruned = 0;
118
+ let dropped = 0;
119
+ const ingestUnit = (subject, text, digest, sourceContext) => {
120
+ store.transaction(() => {
121
+ const result = store.ingest(text, {
122
+ source: subject,
123
+ lifecycle: true,
124
+ ...sourceContext === undefined ? {} : { contexts: [sourceContext] }
125
+ });
126
+ if (result.problems.length > 0) {
127
+ failRecord(result.problems.map(problem => `line ${problem.line}: ${problem.message}`));
128
+ }
129
+ added += result.ids.length;
130
+ retracted += retractStale(store, subject, new Set(result.ids));
131
+ recordDigest(store, subject, digest);
132
+ });
133
+ };
134
+ if (mapping.prelude !== '') {
135
+ const subject = `connect/${name}`;
136
+ const digest = digestOf(mapping.prelude);
137
+ if (force || !isConnected(store, subject, digest)) {
138
+ store.transaction(() => {
139
+ const result = store.ingest(mapping.prelude, { source: subject });
140
+ if (result.problems.length > 0) {
141
+ // The prelude was linted with the mapping; a problem here aborts the run.
142
+ const detail = result.problems.map(problem => `prelude line ${problem.line}: ${problem.message}`).join('\n');
143
+ throw new Error(`cave connect: prelude failed to ingest\n${detail}`);
144
+ }
145
+ added += result.ids.length;
146
+ recordDigest(store, subject, digest);
147
+ });
148
+ }
149
+ else {
150
+ notes.push('prelude unchanged, skipped');
151
+ }
152
+ }
153
+ records.forEach((record, at) => {
154
+ const instantiation = Template.instantiate(mapping.templates, name => Template.fieldOf(record, name));
155
+ dropped += instantiation.dropped;
156
+ const key = options.key === undefined ?
157
+ digestOf(instantiation.text) :
158
+ keyOf(Template.fieldOf(record, options.key));
159
+ if (key === undefined) {
160
+ failures.push({ record: `record ${at + 1}`, problems: [`--key field ${JSON.stringify(options.key)} is missing or empty`] });
161
+ return;
162
+ }
163
+ if (seen.has(key)) {
164
+ notes.push(`duplicate record key ${JSON.stringify(key)} — last record wins`);
165
+ }
166
+ // Failed records still count as seen — pruning must never mistake a
167
+ // transient failure for a record that left the source.
168
+ seen.add(key);
169
+ if (instantiation.problems.length > 0) {
170
+ failures.push({ record: `record ${at + 1} (${key})`, problems: instantiation.problems });
171
+ return;
172
+ }
173
+ const subject = `connect/${name}/${key}`;
174
+ const sourceContext = options.source === undefined ? undefined :
175
+ SourceSpan.context(options.source, options.spans?.[at]);
176
+ const digest = digestOf(`${instantiation.text}\0${sourceContext ?? ''}`);
177
+ if (!force && isConnected(store, subject, digest)) {
178
+ skipped += 1;
179
+ return;
180
+ }
181
+ try {
182
+ ingestUnit(subject, instantiation.text, digest, sourceContext);
183
+ mapped += 1;
184
+ }
185
+ catch (error) {
186
+ if (!isRecordError(error)) {
187
+ throw error;
188
+ }
189
+ failures.push({ record: `record ${at + 1} (${key})`, problems: error.problems });
190
+ }
191
+ });
192
+ if (options.prune === true) {
193
+ const prefix = `connect/${name}/`;
194
+ const latest = new Map();
195
+ for (const row of store.byContext(provenanceContext)) {
196
+ const current = latest.get(row.claim_key);
197
+ if (current === undefined || current.tx < row.tx) {
198
+ latest.set(row.claim_key, row);
199
+ }
200
+ }
201
+ for (const row of latest.values()) {
202
+ if (row.conf <= 0 || !row.subject.startsWith(prefix) || seen.has(row.subject.slice(prefix.length))) {
203
+ continue;
204
+ }
205
+ store.transaction(() => {
206
+ retracted += retractStale(store, row.subject, new Set());
207
+ store.insertResult({
208
+ claims: [{ claim: { ...store.toClaim(row), conf: 0, raw: '', comment: 'retracted: record left the source' }, line: 0 }],
209
+ edges: [],
210
+ registry: store.registry(),
211
+ problems: []
212
+ });
213
+ pruned += 1;
214
+ });
215
+ }
216
+ }
217
+ return { records: records.length, mapped, skipped, added, retracted, pruned, dropped, failures, notes };
218
+ };
219
+ const rollback = Symbol('cave-connect query rollback');
220
+ /**
221
+ * Federation-lite (spec §23.3): appends the mapped claims inside a
222
+ * transaction, runs the CAVE-Q pattern over the union of store and source,
223
+ * and rolls back — external data is consulted at query time, nothing
224
+ * persists (digest bookkeeping included).
225
+ */
226
+ export const federatedQuery = (store, mapping, records, options, pattern, queryOptions = {}) => {
227
+ let outcome;
228
+ try {
229
+ store.transaction(() => {
230
+ const report = connect(store, mapping, records, { ...options, force: true, prune: false });
231
+ outcome = { matches: caveQuery(store, pattern, queryOptions), report };
232
+ throw rollback;
233
+ });
234
+ }
235
+ catch (error) {
236
+ if (error !== rollback) {
237
+ throw error;
238
+ }
239
+ }
240
+ return outcome;
241
+ };
242
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Record sources (spec §23) — CSV/TSV files, JSON documents, JSONL streams,
3
+ * SQLite databases (read-only), and http(s) URLs serving JSON or CSV. Every
4
+ * source loads to the same shape: an array of flat-ish records the template
5
+ * layer resolves fields from (`fieldOf` handles nested JSON by dot path).
6
+ */
7
+ import type { LineSpan } from '@cavelang/core';
8
+ export type Format = 'csv' | 'tsv' | 'json' | 'jsonl' | 'sqlite';
9
+ /** Injection point for tests; the built-in fetch otherwise. */
10
+ export type FetchLike = (url: string, init: RequestInit) => Promise<Response>;
11
+ export type Options = {
12
+ /** Explicit format; inferred from the extension when omitted. */
13
+ readonly format?: Format;
14
+ /** CSV delimiter (default `,`; `\t` for tsv). */
15
+ readonly delimiter?: string;
16
+ /** SQLite table to read (`SELECT *`). */
17
+ readonly table?: string;
18
+ /** SQLite query — the alternative to `table`. */
19
+ readonly sql?: string;
20
+ /** Dot path to the record array inside a JSON document. */
21
+ readonly records?: string;
22
+ /** URL fetch timeout in seconds (default 60). */
23
+ readonly timeoutSeconds?: number;
24
+ /** Injection point for tests; the built-in fetch otherwise. */
25
+ readonly fetchImpl?: FetchLike;
26
+ };
27
+ export type Loaded = {
28
+ readonly records: readonly Record<string, unknown>[];
29
+ readonly format: Format;
30
+ /** Record-aligned source line spans when the format has stable lines. */
31
+ readonly spans?: readonly LineSpan[];
32
+ };
33
+ export declare const isUrl: (source: string) => boolean;
34
+ /** Infers the source format from an explicit option or the file/URL extension. */
35
+ export declare const formatOf: (source: string, options?: Options) => Format;
36
+ /**
37
+ * Default source name for record identity (spec §23.2): the file/URL
38
+ * basename without extension, whitespace and path noise normalized to `-`.
39
+ */
40
+ export declare const nameOf: (source: string) => string;
41
+ export declare const parseCsv: (text: string, delimiter?: string) => Record<string, string>[];
42
+ /** Loads a source to records. Local files read synchronously; URLs fetch. */
43
+ export declare const load: (source: string, options?: Options) => Promise<Loaded>;
44
+ //# sourceMappingURL=source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../src/source.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAG9C,MAAM,MAAM,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAA;AAEhE,+DAA+D;AAC/D,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;AAE7E,MAAM,MAAM,OAAO,GAAG;IACpB,iEAAiE;IACjE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,iDAAiD;IACjD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,yCAAyC;IACzC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,iDAAiD;IACjD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB,2DAA2D;IAC3D,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,iDAAiD;IACjD,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;IAChC,+DAA+D;IAC/D,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAA;CAC/B,CAAA;AAED,MAAM,MAAM,MAAM,GAAG;IACnB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;IACpD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,yEAAyE;IACzE,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAA;CACrC,CAAA;AAED,eAAO,MAAM,KAAK,GAAI,QAAQ,MAAM,KAAG,OACT,CAAA;AAa9B,kFAAkF;AAClF,eAAO,MAAM,QAAQ,GAAI,QAAQ,MAAM,EAAE,UAAS,OAAY,KAAG,MAUhE,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,MAAM,GAAI,QAAQ,MAAM,KAAG,MAOvC,CAAA;AAqED,eAAO,MAAM,QAAQ,GAAI,MAAM,MAAM,EAAE,kBAAe,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACrC,CAAA;AA0E1C,6EAA6E;AAC7E,eAAO,MAAM,IAAI,GAAU,QAAQ,MAAM,EAAE,UAAS,OAAY,KAAG,OAAO,CAAC,MAAM,CAiBhF,CAAA"}
@@ -0,0 +1,215 @@
1
+ /**
2
+ * Record sources (spec §23) — CSV/TSV files, JSON documents, JSONL streams,
3
+ * SQLite databases (read-only), and http(s) URLs serving JSON or CSV. Every
4
+ * source loads to the same shape: an array of flat-ish records the template
5
+ * layer resolves fields from (`fieldOf` handles nested JSON by dot path).
6
+ */
7
+ import { readFileSync } from 'node:fs';
8
+ import { basename, extname } from 'node:path';
9
+ import { DatabaseSync } from 'node:sqlite';
10
+ import { fieldOf } from "./template.js";
11
+ export const isUrl = (source) => /^https?:\/\//i.test(source);
12
+ const extensionFormats = {
13
+ '.csv': 'csv',
14
+ '.tsv': 'tsv',
15
+ '.json': 'json',
16
+ '.jsonl': 'jsonl',
17
+ '.ndjson': 'jsonl',
18
+ '.db': 'sqlite',
19
+ '.sqlite': 'sqlite',
20
+ '.sqlite3': 'sqlite'
21
+ };
22
+ /** Infers the source format from an explicit option or the file/URL extension. */
23
+ export const formatOf = (source, options = {}) => {
24
+ if (options.format !== undefined) {
25
+ return options.format;
26
+ }
27
+ const path = isUrl(source) ? new URL(source).pathname : source;
28
+ const format = extensionFormats[extname(path).toLowerCase()];
29
+ if (format === undefined) {
30
+ throw new Error(`cannot infer format of ${JSON.stringify(source)} — pass --format csv|tsv|json|jsonl|sqlite`);
31
+ }
32
+ return format;
33
+ };
34
+ /**
35
+ * Default source name for record identity (spec §23.2): the file/URL
36
+ * basename without extension, whitespace and path noise normalized to `-`.
37
+ */
38
+ export const nameOf = (source) => {
39
+ const path = isUrl(source) ?
40
+ new URL(source).hostname + decodeURIComponent(new URL(source).pathname) :
41
+ source;
42
+ const base = basename(path, extname(path));
43
+ const name = base.replace(/[^A-Za-z0-9._-]+/g, '-').replace(/^-+|-+$/g, '');
44
+ return name === '' ? 'source' : name;
45
+ };
46
+ /**
47
+ * RFC 4180 CSV: quoted fields (with `""` escapes) may contain delimiters and
48
+ * newlines; records split on LF or CRLF. The first row names the fields.
49
+ */
50
+ const parseCsvLocated = (text, delimiter = ',') => {
51
+ const rows = [];
52
+ let row = [];
53
+ let field = '';
54
+ let quoted = false;
55
+ let line = 1;
56
+ let rowStart = 1;
57
+ const body = text.startsWith('\uFEFF') ? text.slice(1) : text;
58
+ const endField = () => {
59
+ row.push(field);
60
+ field = '';
61
+ };
62
+ const endRow = () => {
63
+ endField();
64
+ rows.push({ cells: row, span: { startLine: rowStart, endLine: line } });
65
+ row = [];
66
+ rowStart = line + 1;
67
+ };
68
+ for (let i = 0; i < body.length; i++) {
69
+ const char = body[i];
70
+ if (quoted) {
71
+ if (char === '"') {
72
+ if (body[i + 1] === '"') {
73
+ field += '"';
74
+ i += 1;
75
+ }
76
+ else {
77
+ quoted = false;
78
+ }
79
+ }
80
+ else if (char === '\r' && body[i + 1] === '\n') {
81
+ // CRLF normalizes to LF inside quoted fields too.
82
+ }
83
+ else {
84
+ field += char;
85
+ }
86
+ }
87
+ else if (char === '"' && field === '') {
88
+ quoted = true;
89
+ }
90
+ else if (char === delimiter) {
91
+ endField();
92
+ }
93
+ else if (char === '\n') {
94
+ endRow();
95
+ }
96
+ else if (char !== '\r' || body[i + 1] !== '\n') {
97
+ field += char;
98
+ }
99
+ if (char === '\n') {
100
+ line += 1;
101
+ }
102
+ }
103
+ if (field !== '' || row.length > 0) {
104
+ endRow();
105
+ }
106
+ const [headerRow, ...dataRows] = rows;
107
+ const header = headerRow?.cells;
108
+ if (header === undefined) {
109
+ return { records: [], spans: [] };
110
+ }
111
+ const present = dataRows.filter(row_ => row_.cells.length > 1 || row_.cells[0] !== '');
112
+ return {
113
+ records: present.map(row_ => Object.fromEntries(header.map((name, at) => [name.trim(), row_.cells[at] ?? '']))),
114
+ spans: present.map(row_ => row_.span)
115
+ };
116
+ };
117
+ export const parseCsv = (text, delimiter = ',') => parseCsvLocated(text, delimiter).records;
118
+ const asRecords = (value, source) => {
119
+ if (!Array.isArray(value)) {
120
+ throw new Error(`${source}: expected an array of records${value !== null && typeof value === 'object' ? ' — pass --records <dot.path> to the array' : ''}`);
121
+ }
122
+ return value.map((item, at) => {
123
+ if (item === null || typeof item !== 'object' || Array.isArray(item)) {
124
+ throw new Error(`${source}: record ${at + 1} is not an object`);
125
+ }
126
+ return item;
127
+ });
128
+ };
129
+ const parseJson = (text, source, options) => {
130
+ const parsed = JSON.parse(text);
131
+ const picked = options.records === undefined ? parsed : fieldOf(parsed, options.records);
132
+ if (options.records !== undefined && picked === undefined) {
133
+ throw new Error(`${source}: --records ${JSON.stringify(options.records)} not found`);
134
+ }
135
+ return asRecords(picked, source);
136
+ };
137
+ const parseJsonlLocated = (text, source) => {
138
+ const located = text.split(/\r?\n/)
139
+ .map((line, at) => ({ line, lineNo: at + 1 }))
140
+ .filter(entry => entry.line.trim() !== '');
141
+ return {
142
+ records: located.map(entry => {
143
+ const parsed = JSON.parse(entry.line);
144
+ if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
145
+ throw new Error(`${source}: line ${entry.lineNo} is not a JSON object`);
146
+ }
147
+ return parsed;
148
+ }),
149
+ spans: located.map(entry => ({ startLine: entry.lineNo, endLine: entry.lineNo }))
150
+ };
151
+ };
152
+ /** node:sqlite values → template-substitutable values. */
153
+ const sqliteValue = (value) => typeof value === 'bigint' ?
154
+ (Number.isSafeInteger(Number(value)) ? Number(value) : value.toString()) :
155
+ value;
156
+ const readSqlite = (path, options) => {
157
+ if ((options.table === undefined) === (options.sql === undefined)) {
158
+ throw new Error(`${path}: a SQLite source needs exactly one of --table or --sql`);
159
+ }
160
+ const sql = options.sql ?? `SELECT * FROM "${options.table.replaceAll('"', '""')}"`;
161
+ const db = new DatabaseSync(path, { readOnly: true });
162
+ try {
163
+ const rows = db.prepare(sql).all();
164
+ return rows.map(row => Object.fromEntries(Object.entries(row).map(([key, value]) => [key, sqliteValue(value)])));
165
+ }
166
+ finally {
167
+ db.close();
168
+ }
169
+ };
170
+ const fetchText = async (url, options) => {
171
+ const response = await (options.fetchImpl ?? fetch)(url, {
172
+ headers: {
173
+ 'user-agent': 'cave-connect',
174
+ accept: 'application/json, text/csv;q=0.9, */*;q=0.8'
175
+ },
176
+ redirect: 'follow',
177
+ signal: AbortSignal.timeout((options.timeoutSeconds ?? 60) * 1000)
178
+ });
179
+ if (!response.ok) {
180
+ throw new Error(`${url}: HTTP ${response.status}`);
181
+ }
182
+ return { text: await response.text(), contentType: response.headers.get('content-type') ?? '' };
183
+ };
184
+ /** Loads a source to records. Local files read synchronously; URLs fetch. */
185
+ export const load = async (source, options = {}) => {
186
+ if (isUrl(source)) {
187
+ const { text, contentType } = await fetchText(source, options);
188
+ const format = options.format ??
189
+ (contentType.includes('json') ? 'json' :
190
+ contentType.includes('csv') ? 'csv' :
191
+ formatOf(source, options));
192
+ if (format === 'sqlite') {
193
+ throw new Error(`${source}: SQLite sources must be local files`);
194
+ }
195
+ return { ...parseLocated(format, text, source, options), format };
196
+ }
197
+ const format = formatOf(source, options);
198
+ if (format === 'sqlite') {
199
+ return { records: readSqlite(source, options), format };
200
+ }
201
+ return { ...parseLocated(format, readFileSync(source, 'utf8'), source, options), format };
202
+ };
203
+ const parseLocated = (format, text, source, options) => {
204
+ switch (format) {
205
+ case 'csv':
206
+ return parseCsvLocated(text, options.delimiter ?? ',');
207
+ case 'tsv':
208
+ return parseCsvLocated(text, options.delimiter ?? '\t');
209
+ case 'json':
210
+ return { records: parseJson(text, source, options) };
211
+ case 'jsonl':
212
+ return parseJsonlLocated(text, source);
213
+ }
214
+ };
215
+ //# sourceMappingURL=source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.js","sourceRoot":"","sources":["../../src/source.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Mapping templates (spec §23.1) — an ordinary CAVE document whose `?field`
3
+ * variables stand for record fields.
4
+ *
5
+ * Top-level blocks (a line plus its indented children) split by whether they
6
+ * contain a variable: variable-free blocks form the **prelude** (verb
7
+ * declarations, static claims — appended once per run), blocks with
8
+ * variables are **record templates**, instantiated once per record.
9
+ *
10
+ * A variable is a whole whitespace-delimited token beginning with `?`;
11
+ * tokens inside `"…"` and `` `…` `` literals are never substituted. A claim
12
+ * line whose record lacks a referenced field is dropped together with its
13
+ * indented children — optional fields simply yield fewer claims.
14
+ */
15
+ export type Mapping = {
16
+ /** Variable-free blocks plus leading comments, joined — appended once per run. */
17
+ readonly prelude: string;
18
+ /** Record templates: raw lines of each variable-bearing top-level block. */
19
+ readonly templates: readonly (readonly string[])[];
20
+ /** Distinct variable names referenced by the templates, sorted. */
21
+ readonly variables: readonly string[];
22
+ };
23
+ export type t = Mapping;
24
+ /** A field value substituted into one template slot. */
25
+ export type Formatted = {
26
+ readonly kind: 'ok';
27
+ readonly text: string;
28
+ } | {
29
+ readonly kind: 'missing';
30
+ } | {
31
+ readonly kind: 'problem';
32
+ readonly message: string;
33
+ };
34
+ /** One record's instantiation of every template block. */
35
+ export type Instantiation = {
36
+ /** Ready-to-ingest CAVE text; empty when every line dropped. */
37
+ readonly text: string;
38
+ /** Claim lines dropped because a referenced field was missing/empty. */
39
+ readonly dropped: number;
40
+ /** Formatting errors — a non-empty list fails the whole record (spec §23.2). */
41
+ readonly problems: readonly string[];
42
+ };
43
+ /**
44
+ * Parses a mapping document: lints it (variables parse as ordinary terms, so
45
+ * diagnostics are real syntax problems), rejects variables in attribute
46
+ * position (`?attr: …` would silently name an attribute `?attr`), and splits
47
+ * top-level blocks into prelude and record templates.
48
+ */
49
+ export declare const parse: (text: string) => {
50
+ mapping?: Mapping;
51
+ problems: readonly string[];
52
+ };
53
+ /**
54
+ * Formats one field value for one template slot (spec §23.1). Deterministic
55
+ * and exact — values insert verbatim when already token-safe, or as quoted
56
+ * literals; formatting never invents names (no slugification).
57
+ */
58
+ export declare const formatValue: (value: unknown, position: "subject" | "payload") => Formatted;
59
+ /**
60
+ * Resolves a field by name: exact key first, then a dot path into nested
61
+ * JSON (`address.city`, `items.0.sku`).
62
+ */
63
+ export declare const fieldOf: (record: unknown, name: string) => unknown;
64
+ /**
65
+ * Instantiates every template block for one record. Lines without variables
66
+ * pass through verbatim; a dropped line takes its indented children with it.
67
+ */
68
+ export declare const instantiate: (templates: readonly (readonly string[])[], lookup: (name: string) => unknown) => Instantiation;
69
+ //# sourceMappingURL=template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/template.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,MAAM,MAAM,OAAO,GAAG;IACpB,kFAAkF;IAClF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,4EAA4E;IAC5E,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAA;IAClD,mEAAmE;IACnE,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;CACtC,CAAA;AAED,MAAM,MAAM,CAAC,GAAG,OAAO,CAAA;AAEvB,wDAAwD;AACxD,MAAM,MAAM,SAAS,GACjB;IAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9C;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GAC5B;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAE1D,0DAA0D;AAC1D,MAAM,MAAM,aAAa,GAAG;IAC1B,gEAAgE;IAChE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,wEAAwE;IACxE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,gFAAgF;IAChF,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;CACrC,CAAA;AAkBD;;;;;GAKG;AACH,eAAO,MAAM,KAAK,GAAI,MAAM,MAAM,KAAG;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;CAgDpF,CAAA;AAID;;;;GAIG;AACH,eAAO,MAAM,WAAW,GAAI,OAAO,OAAO,EAAE,UAAU,SAAS,GAAG,SAAS,KAAG,SAqC7E,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,OAAO,GAAI,QAAQ,OAAO,EAAE,MAAM,MAAM,KAAG,OAYvD,CAAA;AA0CD;;;GAGG;AACH,eAAO,MAAM,WAAW,GACtB,WAAW,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,EACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,KAChC,aAsCF,CAAA"}