functionalscript 0.36.0 → 0.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. package/fs/asn.1/module.f.js +1 -1
  2. package/fs/asserts/proof.f.js +1 -1
  3. package/fs/base_n/module.f.js +3 -3
  4. package/fs/base_n/proof.f.js +3 -3
  5. package/fs/{base128 → basen/base128}/module.f.d.ts +1 -1
  6. package/fs/{base128 → basen/base128}/module.f.js +1 -1
  7. package/fs/{base128 → basen/base128}/proof.f.js +3 -3
  8. package/fs/{base64 → basen/base64}/module.f.d.ts +2 -2
  9. package/fs/{base64 → basen/base64}/module.f.js +25 -15
  10. package/fs/{base64 → basen/base64}/proof.f.d.ts +1 -0
  11. package/fs/{base64 → basen/base64}/proof.f.js +11 -5
  12. package/fs/{cbase32 → basen/cbase32}/module.f.d.ts +2 -2
  13. package/fs/{cbase32 → basen/cbase32}/module.f.js +2 -2
  14. package/fs/{cbase32 → basen/cbase32}/proof.f.js +1 -1
  15. package/fs/bnf/data/module.f.js +4 -4
  16. package/fs/bnf/data/proof.f.js +6 -6
  17. package/fs/bnf/descent/module.f.js +6 -6
  18. package/fs/bnf/descent/proof.f.js +6 -6
  19. package/fs/bnf/ll1/module.f.js +9 -9
  20. package/fs/bnf/ll1/proof.f.js +6 -6
  21. package/fs/bnf/module.f.js +4 -4
  22. package/fs/bnf/proof.f.js +2 -2
  23. package/fs/bnf/testlib.f.js +1 -1
  24. package/fs/cas/cli/module.f.js +7 -7
  25. package/fs/cas/cli/proof.f.js +8 -8
  26. package/fs/cas/mcp/module.f.js +95 -55
  27. package/fs/cas/mcp/proof.f.d.ts +3 -1
  28. package/fs/cas/mcp/proof.f.js +79 -51
  29. package/fs/cas/module.f.js +10 -10
  30. package/fs/cas/proof.f.d.ts +4 -2
  31. package/fs/cas/proof.f.js +10 -10
  32. package/fs/ci/bun/module.f.js +2 -2
  33. package/fs/ci/common/module.f.d.ts +2 -2
  34. package/fs/ci/common/module.f.js +4 -4
  35. package/fs/ci/config/module.f.d.ts +19 -20
  36. package/fs/ci/config/module.f.js +3 -5
  37. package/fs/ci/deno/module.f.js +8 -4
  38. package/fs/ci/module.f.js +9 -9
  39. package/fs/ci/node/module.f.d.ts +1 -1
  40. package/fs/ci/node/module.f.js +3 -5
  41. package/fs/ci/playwright/module.f.js +3 -3
  42. package/fs/ci/proof.f.js +14 -14
  43. package/fs/ci/rust/module.f.js +2 -2
  44. package/fs/cli/module.f.js +3 -3
  45. package/fs/cli/proof.f.js +3 -3
  46. package/fs/{types → common}/monoid/module.f.d.ts +1 -1
  47. package/fs/crypto/hmac/module.f.js +2 -2
  48. package/fs/crypto/hmac/proof.f.js +5 -5
  49. package/fs/crypto/pow/module.f.js +3 -3
  50. package/fs/crypto/pow/proof.f.js +4 -4
  51. package/fs/crypto/secp/module.f.js +2 -2
  52. package/fs/crypto/secp/proof.f.js +3 -3
  53. package/fs/crypto/sha2/module.f.js +2 -2
  54. package/fs/crypto/sha2/proof.f.js +6 -6
  55. package/fs/crypto/sign/module.f.js +4 -4
  56. package/fs/crypto/vdf/module.f.js +1 -1
  57. package/fs/crypto/vdf/proof.f.js +1 -1
  58. package/fs/dev/module.f.js +6 -6
  59. package/fs/dev/package_json/module.f.js +6 -6
  60. package/fs/dev/package_json/proof.f.js +3 -3
  61. package/fs/dev/proof.f.js +2 -2
  62. package/fs/djs/ast/module.f.js +2 -2
  63. package/fs/djs/ast/proof.f.js +4 -4
  64. package/fs/djs/examples/m.f.d.ts +1 -1
  65. package/fs/djs/module.f.d.ts +1 -1
  66. package/fs/djs/module.f.js +5 -5
  67. package/fs/djs/parser/module.f.js +4 -4
  68. package/fs/djs/parser/proof.f.js +7 -7
  69. package/fs/djs/proof.f.js +3 -3
  70. package/fs/djs/serializer/module.f.js +6 -6
  71. package/fs/djs/serializer/proof.f.js +4 -4
  72. package/fs/djs/tokenizer/module.f.js +3 -3
  73. package/fs/djs/tokenizer/proof.f.js +5 -5
  74. package/fs/djs/tokenizer-new/proof.f.js +6 -6
  75. package/fs/djs/transpiler/module.f.d.ts +5 -0
  76. package/fs/djs/transpiler/module.f.js +21 -11
  77. package/fs/djs/transpiler/proof.f.js +5 -5
  78. package/fs/effects/memory/module.f.js +4 -4
  79. package/fs/effects/memory/proof.f.js +3 -3
  80. package/fs/effects/module.f.js +1 -1
  81. package/fs/effects/node/memory/module.js +2 -2
  82. package/fs/effects/node/memory/proof.js +3 -3
  83. package/fs/effects/node/module.f.js +7 -7
  84. package/fs/effects/node/module.js +10 -10
  85. package/fs/effects/node/virtual/module.f.js +7 -7
  86. package/fs/effects/node/virtual/proof.f.d.ts +1 -0
  87. package/fs/effects/node/virtual/proof.f.js +11 -4
  88. package/fs/effects/proof.f.js +2 -2
  89. package/fs/emergent_testing/all.test.js +2 -2
  90. package/fs/emergent_testing/example.f.d.ts +1 -1
  91. package/fs/emergent_testing/module.f.js +6 -6
  92. package/fs/emergent_testing/proof.f.d.ts +19 -17
  93. package/fs/emergent_testing/proof.f.js +7 -7
  94. package/fs/emergent_testing/scenarios/all.js +1 -1
  95. package/fs/fsc/bnf.f.js +2 -2
  96. package/fs/fsc/json.f.js +1 -1
  97. package/fs/fsc/module.f.js +7 -7
  98. package/fs/fsc/proof.f.js +4 -4
  99. package/fs/fsm/module.f.js +9 -9
  100. package/fs/fsm/proof.f.js +7 -7
  101. package/fs/js/tokenizer/module.f.js +7 -7
  102. package/fs/js/tokenizer/proof.f.js +5 -5
  103. package/fs/mcp/module.f.d.ts +13 -13
  104. package/fs/mcp/module.f.js +8 -8
  105. package/fs/mcp/proof.f.js +5 -5
  106. package/fs/mcp/stdio/module.f.d.ts +2 -2
  107. package/fs/mcp/stdio/module.f.js +10 -10
  108. package/fs/mcp/stdio/proof.f.js +10 -10
  109. package/fs/{html → media/html}/module.f.d.ts +3 -3
  110. package/fs/{html → media/html}/module.f.js +9 -9
  111. package/fs/media/json/module.f.d.ts +50 -0
  112. package/fs/{json → media/json}/module.f.js +7 -7
  113. package/fs/{json → media/json}/parser/module.f.d.ts +2 -2
  114. package/fs/{json → media/json}/parser/module.f.js +7 -7
  115. package/fs/{json → media/json}/parser/proof.f.js +6 -6
  116. package/fs/{json → media/json}/proof.f.js +4 -4
  117. package/fs/media/json/rpc/module.f.d.ts +114 -0
  118. package/fs/{json → media/json}/rpc/module.f.js +3 -3
  119. package/fs/{json → media/json}/rpc/proof.f.js +4 -4
  120. package/fs/media/json/schema/module.f.d.ts +78 -0
  121. package/fs/{json → media/json}/schema/module.f.js +2 -2
  122. package/fs/{json → media/json}/schema/proof.f.js +3 -3
  123. package/fs/{json → media/json}/serializer/module.f.d.ts +1 -1
  124. package/fs/{json → media/json}/serializer/module.f.js +2 -2
  125. package/fs/{json → media/json}/serializer/proof.f.js +2 -2
  126. package/fs/{json → media/json}/tokenizer/module.f.d.ts +2 -2
  127. package/fs/{json → media/json}/tokenizer/module.f.js +4 -4
  128. package/fs/{json → media/json}/tokenizer/proof.f.js +5 -5
  129. package/fs/media/module.f.d.ts +37 -0
  130. package/fs/media/module.f.js +24 -0
  131. package/fs/media/proof.f.d.ts +9 -0
  132. package/fs/media/proof.f.js +57 -0
  133. package/fs/media/revision/module.f.d.ts +51 -0
  134. package/fs/media/revision/module.f.js +110 -0
  135. package/fs/media/revision/proof.f.d.ts +29 -0
  136. package/fs/media/revision/proof.f.js +119 -0
  137. package/fs/{mime → media/type}/module.f.d.ts +6 -6
  138. package/fs/{mime → media/type}/module.f.js +6 -6
  139. package/fs/{mime → media/type}/proof.f.js +6 -6
  140. package/fs/module.f.d.ts +2 -0
  141. package/fs/{fjs/module.f.js → module.f.js} +8 -8
  142. package/fs/module.js +4 -0
  143. package/fs/path/module.f.js +2 -2
  144. package/fs/{fjs/proof.f.js → proof.f.js} +4 -4
  145. package/fs/sul/id/module.f.js +9 -9
  146. package/fs/sul/id/proof.f.js +5 -5
  147. package/fs/sul/level/hash/module.f.js +3 -3
  148. package/fs/sul/level/hash/proof.f.js +3 -3
  149. package/fs/sul/level/literal/module.f.js +5 -5
  150. package/fs/sul/level/literal/proof.f.js +3 -3
  151. package/fs/sul/module.f.js +3 -3
  152. package/fs/sul/proof.f.js +3 -3
  153. package/fs/text/ascii/proof.f.js +3 -3
  154. package/fs/text/code_point/module.f.js +2 -2
  155. package/fs/text/code_point/proof.f.js +1 -1
  156. package/fs/text/module.f.js +5 -5
  157. package/fs/text/proof.f.js +4 -4
  158. package/fs/text/sgr/module.f.js +2 -2
  159. package/fs/text/sgr/proof.f.js +2 -2
  160. package/fs/text/utf16/module.f.js +5 -5
  161. package/fs/text/utf16/proof.f.js +4 -4
  162. package/fs/text/utf8/module.f.js +22 -17
  163. package/fs/text/utf8/proof.f.js +5 -5
  164. package/fs/types/array/module.f.js +1 -1
  165. package/fs/types/array/proof.f.js +3 -3
  166. package/fs/types/bigfloat/module.f.js +1 -1
  167. package/fs/types/bigfloat/proof.f.js +1 -1
  168. package/fs/types/bigint/module.f.js +2 -2
  169. package/fs/types/bigint/proof.f.js +3 -3
  170. package/fs/types/bit_vec/module.f.js +8 -8
  171. package/fs/types/bit_vec/proof.f.js +5 -5
  172. package/fs/types/btree/find/module.f.js +1 -1
  173. package/fs/types/btree/find/proof.f.d.ts +3 -1
  174. package/fs/types/btree/find/proof.f.js +7 -7
  175. package/fs/types/btree/module.f.js +2 -2
  176. package/fs/types/btree/proof.f.d.ts +11 -5
  177. package/fs/types/btree/proof.f.js +7 -7
  178. package/fs/types/btree/remove/module.f.js +4 -4
  179. package/fs/types/btree/remove/proof.f.d.ts +5 -2
  180. package/fs/types/btree/remove/proof.f.js +5 -5
  181. package/fs/types/btree/set/module.f.js +3 -3
  182. package/fs/types/btree/set/proof.f.js +4 -4
  183. package/fs/types/byte_set/module.f.js +2 -2
  184. package/fs/types/byte_set/proof.f.js +4 -4
  185. package/fs/types/function/compare/proof.f.js +1 -1
  186. package/fs/types/function/operator/proof.f.d.ts +21 -10
  187. package/fs/types/function/operator/proof.f.js +1 -1
  188. package/fs/types/function/proof.f.js +1 -1
  189. package/fs/types/list/module.f.js +2 -2
  190. package/fs/types/list/proof.f.d.ts +15 -7
  191. package/fs/types/list/proof.f.js +4 -4
  192. package/fs/types/map/proof.f.js +2 -2
  193. package/fs/types/nibble_set/proof.f.js +2 -2
  194. package/fs/types/nullable/module.f.js +2 -2
  195. package/fs/types/nullable/proof.f.js +1 -1
  196. package/fs/types/number/module.f.js +5 -5
  197. package/fs/types/number/proof.f.js +1 -1
  198. package/fs/types/object/module.f.js +4 -4
  199. package/fs/types/object/proof.f.js +1 -1
  200. package/fs/types/ordered_map/module.f.js +6 -6
  201. package/fs/types/ordered_map/proof.f.js +3 -3
  202. package/fs/types/patricia_trie/proof.f.d.ts +11 -5
  203. package/fs/types/patricia_trie/proof.f.js +2 -2
  204. package/fs/types/prime_field/module.f.js +2 -2
  205. package/fs/types/prime_field/proof.f.js +2 -2
  206. package/fs/types/range/proof.f.js +1 -1
  207. package/fs/types/range_map/module.f.js +4 -4
  208. package/fs/types/range_map/proof.f.js +7 -7
  209. package/fs/types/result/module.js +1 -1
  210. package/fs/types/result/proof.f.d.ts +9 -4
  211. package/fs/types/rtti/common/module.f.js +4 -4
  212. package/fs/types/rtti/module.f.d.ts +2 -2
  213. package/fs/types/rtti/module.f.js +1 -1
  214. package/fs/types/rtti/parse/module.f.js +5 -5
  215. package/fs/types/rtti/parse/proof.f.js +2 -2
  216. package/fs/types/rtti/ts/module.f.js +1 -1
  217. package/fs/types/rtti/ts/proof.f.js +2 -2
  218. package/fs/types/rtti/validate/module.f.js +4 -4
  219. package/fs/types/rtti/validate/proof.f.js +2 -2
  220. package/fs/types/sorted_list/module.f.js +3 -3
  221. package/fs/types/sorted_list/proof.f.js +6 -6
  222. package/fs/types/sorted_set/module.f.js +1 -1
  223. package/fs/types/sorted_set/proof.f.js +6 -6
  224. package/fs/types/string/module.f.js +4 -4
  225. package/fs/types/string/proof.f.js +2 -2
  226. package/fs/types/string_set/module.f.js +6 -6
  227. package/fs/types/string_set/proof.f.js +1 -1
  228. package/fs/types/ts/proof.f.d.ts +18 -18
  229. package/fs/types/ts/proof.f.js +1 -1
  230. package/fs/types/uint8array/module.f.js +4 -4
  231. package/fs/types/uint8array/proof.f.js +4 -4
  232. package/fs/website/module.f.js +3 -3
  233. package/fs/website/proof.f.js +3 -3
  234. package/package.json +8 -8
  235. package/fs/fjs/module.f.d.ts +0 -2
  236. package/fs/fjs/module.js +0 -4
  237. package/fs/json/module.f.d.ts +0 -50
  238. package/fs/json/rpc/module.f.d.ts +0 -114
  239. package/fs/json/schema/module.f.d.ts +0 -77
  240. /package/fs/{base128 → basen/base128}/proof.f.d.ts +0 -0
  241. /package/fs/{cbase32 → basen/cbase32}/proof.f.d.ts +0 -0
  242. /package/fs/{types → common}/monoid/module.f.js +0 -0
  243. /package/fs/{types → common}/monoid/proof.f.d.ts +0 -0
  244. /package/fs/{types → common}/monoid/proof.f.js +0 -0
  245. /package/fs/{html → media/html}/proof.f.d.ts +0 -0
  246. /package/fs/{html → media/html}/proof.f.js +0 -0
  247. /package/fs/{json → media/json}/parser/proof.f.d.ts +0 -0
  248. /package/fs/{json → media/json}/proof.f.d.ts +0 -0
  249. /package/fs/{json → media/json}/rpc/proof.f.d.ts +0 -0
  250. /package/fs/{json → media/json}/schema/proof.f.d.ts +0 -0
  251. /package/fs/{json → media/json}/serializer/proof.f.d.ts +0 -0
  252. /package/fs/{json → media/json}/tokenizer/proof.f.d.ts +0 -0
  253. /package/fs/{mime → media/type}/proof.f.d.ts +0 -0
  254. /package/fs/{fjs/module.d.ts → module.d.ts} +0 -0
  255. /package/fs/{fjs/proof.f.d.ts → proof.f.d.ts} +0 -0
@@ -12,7 +12,7 @@
12
12
  * | Tool | args | action | result |
13
13
  * |------------|-------------------------------|------------------|-------------------------------------|
14
14
  * | `cas_add` | `{ content, type? }` | `c.write(...)` | hash (cBase32) |
15
- * | `cas_get` | `{ hash, content?: boolean }` | `c.read(key)` | JSON `{length,mime_type,type[,content]}` |
15
+ * | `cas_get` | `{ hash, content?: boolean }` | `c.read(key)` | JSON `{length,mimeType,type[,uri][,text\|blob]}` |
16
16
  * | `cas_list` | `{}` | `c.list()` | hashes, one per line |
17
17
  *
18
18
  * ## `cas_add` input encoding
@@ -31,37 +31,56 @@
31
31
  *
32
32
  * ## `cas_get` output
33
33
  *
34
- * Always returns a JSON object `{ length, mime_type, type[, url][, content] }`.
35
- * `type` is always present (`'text'` or `'base64'`). A single classifier — the
36
- * `fs/mime` detector state machine (length × magic-byte eliminator × UTF-8 DFA)
37
- * produces the same three-way verdict on both paths, so there is no second,
38
- * divergent copy of the rules:
34
+ * Always returns a JSON object `{ length, mimeType, type[, uri][, text | blob] }`.
35
+ * These field names mirror the MCP resource-contents shape (`resources/read`
36
+ * results), so the tool view and the future resource view of a blob use the same
37
+ * vocabulary: `mimeType` (not `mime_type`), `uri` (not `url`) the resource URI
38
+ * under which the same blob will be readable via `resources/read` — and `text` /
39
+ * `blob` (not a `type`-tagged `content`) for inline payloads. `type` is always
40
+ * present (`'text'` or `'base64'`) as the discriminator for which of `text` /
41
+ * `blob` a later `content: true` fetch would populate — MCP allows extra fields,
42
+ * so `type` and `length` simply stay alongside the required resource-contents
43
+ * fields. A single classifier — the `fs/media/type` detector state machine (length ×
44
+ * magic-byte eliminator × UTF-8 DFA) — produces the same three-way verdict on
45
+ * both paths, so there is no second, divergent copy of the rules:
39
46
  *
40
47
  * 1. **Magic-byte hit** (PNG/JPEG/GIF/WebP/PDF/ZIP) → `type: 'base64'` with the
41
- * detected `mime_type`.
42
- * 2. **Whole-blob-valid UTF-8** → `type: 'text'`, `mime_type: 'text/plain'`.
43
- * 3. **Fallback** → `type: 'base64'`, `mime_type: 'application/octet-stream'`.
44
- *
45
- * **Metadata-only (`content: false`, the default) is size-independent.** It folds
46
- * the read stream through `fs/mime` `detectStream` and never buffers the blob.
47
- * Because a single `Vec` caps at `maxLength` bits (128 KiB), the old
48
- * drain-into-one-`Vec` approach failed on any blob larger than one chunk even when
49
- * only metadata was asked for; streaming detection returns correct
50
- * `{ length, mime_type, type[, url] }` regardless of size.
51
- *
52
- * **`content: true`** first derives `{ length, mime_type, type }` with the same
53
- * size-independent `fs/mime` `detectStream` machine, then materializes the bytes
54
- * (via `collectRead`, bounded by `maxLength`) and encodes the inline payload by
55
- * `type` a `fs/text/utf8` `fromVec` string for `text`, base64 for `base64`. A
56
- * blob larger than `maxLength` (128 KiB) cannot be buffered into one `Vec`, so it
57
- * is rejected here with a descriptive *"too large"* error (carrying the byte size
58
- * and `url`) rather than being misreported as absent; it should be fetched via
59
- * `url` or inspected with metadata-only `cas_get`.
48
+ * detected `mimeType`.
49
+ * 2. **Whole-blob-valid UTF-8** → `type: 'text'`, `mimeType: 'text/plain'`.
50
+ * 3. **Fallback** → `type: 'base64'`, `mimeType: 'application/octet-stream'`.
51
+ *
52
+ * **Metadata-only (`content: false`, the default) is size-independent for
53
+ * non-text and oversized blobs.** It folds the read stream through
54
+ * `fs/media/type` `detectStream` and never buffers the blob. Because a single
55
+ * `Vec` caps at `maxLength` bits (128 KiB), the old drain-into-one-`Vec`
56
+ * approach failed on any blob larger than one chunk even when only metadata
57
+ * was asked for; streaming detection returns correct
58
+ * `{ length, mimeType, type[, uri] }` regardless of size. A dialect (e.g.
59
+ * `vnd.fjs.revision`, see `fs/media/module.f.ts`) can only be recognized by
60
+ * parsing the whole blob as JSON, so when the streaming verdict is
61
+ * whole-blob-valid text within the same bounded inline cap as `content: true`
62
+ * (`maxLengthBytes`), one extra bounded read materializes the blob purely to
63
+ * refine `mimeType` through the dialect-aware detector; a larger or non-text
64
+ * blob is never a dialect match and is returned from the streaming verdict
65
+ * alone, unbuffered.
66
+ *
67
+ * **`content: true`** first derives `{ length, mimeType, type }` with the same
68
+ * size-independent `fs/media/type` `detectStream` machine (to decide whether the
69
+ * blob even fits inline), then materializes the bytes (via `collectRead`, bounded
70
+ * by `maxLength`) and re-derives the verdict from the dialect-aware detector
71
+ * (`fs/media/module.f.ts` `detect`) — now that the whole blob is in hand, a
72
+ * dialect match is reflected in the result — before encoding the inline payload
73
+ * by `type` — a `fs/text/utf8` `fromVec` string on `text` (for `type: 'text'`),
74
+ * base64 on `blob` (for `type: 'base64'`). A blob larger than `maxLength` (128
75
+ * KiB) cannot be buffered into one `Vec`, so it is rejected here with a
76
+ * descriptive *"too large"* error (carrying the byte size and `uri`) rather than
77
+ * being misreported as absent; it should be fetched via `uri` or inspected with
78
+ * metadata-only `cas_get`.
60
79
  *
61
80
  * ## Encoding split: hashes vs. content
62
81
  *
63
82
  * `Cas<O>` deals in `Vec` (bit vectors); MCP models only `textContent` today.
64
- * **Hashes** travel as cBase32 (`fs/cbase32`) — the canonical CAS hash format,
83
+ * **Hashes** travel as cBase32 (`fs/basen/cbase32`) — the canonical CAS hash format,
65
84
  * shared with the CLI and the on-disk store layout. **Content** encoding is
66
85
  * determined at read time as described above.
67
86
  *
@@ -80,24 +99,25 @@
80
99
  *
81
100
  * @module
82
101
  */
83
- import { string, option, or, boolean } from "../../types/rtti/module.f.js";
84
- import { stringify } from "../../json/module.f.js";
85
- import { pure, decode } from "../../effects/module.f.js";
86
- import { create } from "../../effects/memory/module.f.js";
87
- import { cBase32ToVec, vecToCBase32 } from "../../cbase32/module.f.js";
88
- import { decode as base64Decode, encode as base64Encode } from "../../base64/module.f.js";
89
- import { tryUtf8 } from "../../text/module.f.js";
90
- import { detectStream } from "../../mime/module.f.js";
91
- import { empty, length as bitVecLength, maxLength, maxLengthBytes, msb, vec } from "../../types/bit_vec/module.f.js";
92
- import { ok, error } from "../../types/result/module.f.js";
93
- import {} from "../../effects/node/module.f.js";
94
- import { stdioTransport } from "../../mcp/stdio/module.f.js";
95
- import { mcpStep, uninitializedState, toolEntry, fromRegistry, errorResult, } from "../../mcp/module.f.js";
96
- import { fileCas } from "../module.f.js";
97
- import { fromVec } from "../../text/utf8/module.f.js";
98
- import { identity } from "../../types/function/module.f.js";
99
- import { sha256 } from "../../crypto/sha2/module.f.js";
100
- import { nonEmpty, empty as elEmpty } from "../../effects/list/module.f.js";
102
+ import { string, option, or, boolean } from '../../types/rtti/module.f.js';
103
+ import { stringify } from '../../media/json/module.f.js';
104
+ import { pure, decode } from '../../effects/module.f.js';
105
+ import { create } from '../../effects/memory/module.f.js';
106
+ import { cBase32ToVec, vecToCBase32 } from '../../basen/cbase32/module.f.js';
107
+ import { decode as base64Decode, encode as base64Encode } from '../../basen/base64/module.f.js';
108
+ import { tryUtf8 } from '../../text/module.f.js';
109
+ import { detectStream } from '../../media/type/module.f.js';
110
+ import { detect as detectDialect } from '../../media/module.f.js';
111
+ import { empty, length as bitVecLength, maxLength, maxLengthBytes, msb, vec } from '../../types/bit_vec/module.f.js';
112
+ import { ok, error } from '../../types/result/module.f.js';
113
+ import {} from '../../effects/node/module.f.js';
114
+ import { stdioTransport } from '../../mcp/stdio/module.f.js';
115
+ import { mcpStep, uninitializedState, toolEntry, fromRegistry, errorResult, } from '../../mcp/module.f.js';
116
+ import { fileCas } from '../module.f.js';
117
+ import { fromVec } from '../../text/utf8/module.f.js';
118
+ import { identity } from '../../types/function/module.f.js';
119
+ import { sha256 } from '../../crypto/sha2/module.f.js';
120
+ import { nonEmpty, empty as elEmpty } from '../../effects/list/module.f.js';
101
121
  // ── Argument schemas (declared once, used for both inputSchema and validate) ─────
102
122
  /** Arguments for `cas_add`: content to store, with optional encoding type. */
103
123
  export const casAddArgs = {
@@ -116,7 +136,7 @@ export const casListArgs = {};
116
136
  * Drains a CAS read stream into a single `Vec`. Used only on the `content: true`
117
137
  * path, where the whole blob is needed for inline base64 / UTF-8 transfer; the
118
138
  * chunk stream is concatenated and an error item is surfaced as the result.
119
- * Metadata-only `cas_get` avoids this entirely via `fs/mime` `detectStream`,
139
+ * Metadata-only `cas_get` avoids this entirely via `fs/media/type` `detectStream`,
120
140
  * which is why it is not bound by the `maxLength` ceiling below.
121
141
  */
122
142
  const collectRead = (stream) => {
@@ -157,45 +177,65 @@ const casToolRegistry = (home) => {
157
177
  ? errorResult('write')
158
178
  : okResult(vecToCBase32(hash))));
159
179
  }),
160
- toolEntry('cas_get', 'Inspect a blob by hash. Always returns JSON {length,mime_type,type[,url]} where type is "text" or "base64". Pass content:true to also include the inline content string, but content is capped at 128 KiB (131072 bytes) — a larger blob is rejected with an error. To download a blob, prefer the url field returned in the result instead of requesting inline content.', casGetArgs, r => {
180
+ toolEntry('cas_get', 'Inspect a blob by hash. Always returns JSON {length,mimeType,type[,uri]} where type is "text" or "base64". Pass content:true to also include the inline payload as text (type:"text") or blob (type:"base64"), but content is capped at 128 KiB (131072 bytes) — a larger blob is rejected with an error. To download a blob, prefer the uri field returned in the result instead of requesting inline content.', casGetArgs, r => {
161
181
  const key = cBase32ToVec(r.hash);
162
182
  if (key === null) {
163
183
  return pure(errorResult(`invalid cBase32 hash: ${r.hash}`));
164
184
  }
165
- const url = c.url(key);
185
+ const uri = c.url(key);
166
186
  return detectStream(c.read(key)).step(([tag, detected]) => {
167
187
  if (tag === 'error') {
168
188
  return pure(errorResult(`no such hash: ${r.hash}`));
169
189
  }
170
- const { length, mime_type, type } = detected;
171
- const meta = { length: Number(length), mime_type, type, url };
190
+ const { length, mime_type: mimeType, type } = detected;
191
+ const meta = { length: Number(length), mimeType, type, uri };
172
192
  if (r.content !== true) {
173
- // content:true path continues below; this is just the metadata step.
174
- return pure(okResult(toJson(meta)));
193
+ // A dialect match can only be decided from the whole parsed blob;
194
+ // only attempt the extra bounded read when it stands a chance
195
+ // (whole-blob text within the same cap `content: true` allows).
196
+ if (type !== 'text' || length > maxLengthBytes) {
197
+ return pure(okResult(toJson(meta)));
198
+ }
199
+ return collectRead(c.read(key)).step(([collectTag, value]) => {
200
+ // Already known to fit from the streaming pass above, so an
201
+ // error here means the hash vanished between reads; fall back
202
+ // to the streaming verdict rather than fail the whole request.
203
+ if (collectTag === 'error') {
204
+ return pure(okResult(toJson(meta)));
205
+ }
206
+ const refined = detectDialect(value);
207
+ return pure(okResult(toJson({ ...meta, mimeType: refined.mime_type })));
208
+ });
175
209
  }
176
210
  // A single `Vec` caps at `maxLength` bits (`maxLengthBytes` bytes), so
177
211
  // a larger blob cannot be buffered for inline transfer. Report the
178
212
  // size and point at the size-independent alternatives instead of
179
213
  // misreporting an existing blob as `no such hash`.
180
214
  if (length > maxLengthBytes) {
181
- return pure(errorResult(`blob too large to fetch inline (${length} bytes, limit ${maxLengthBytes} bytes); use the url field (${url}) or omit content for metadata`));
215
+ return pure(errorResult(`blob too large to fetch inline (${length} bytes, limit ${maxLengthBytes} bytes); use the uri field (${uri}) or omit content for metadata`));
182
216
  }
183
217
  return collectRead(c.read(key)).step(([collectTag, value]) => {
184
218
  if (collectTag === 'error') {
185
219
  return pure(errorResult(`no such hash: ${r.hash}`));
186
220
  }
187
- if (type === 'text') {
221
+ // Re-derive the verdict from the now-materialized blob so a
222
+ // dialect match — only decidable with the whole parsed JSON in
223
+ // hand — is reflected in the inline result too, not just the
224
+ // streaming guess.
225
+ const refined = detectDialect(value);
226
+ const refinedMeta = { length: Number(refined.length), mimeType: refined.mime_type, type: refined.type, uri };
227
+ if (refined.type === 'text') {
188
228
  // `type: 'text'` means the detector validated `value` as UTF-8,
189
229
  // so `fromVec` is non-null here; guard defensively regardless.
190
230
  const str = fromVec(value);
191
231
  return pure(str === null
192
232
  ? errorResult(`content is not byte-aligned: ${r.hash}`)
193
- : okResult(toJson({ ...meta, content: str })));
233
+ : okResult(toJson({ ...refinedMeta, text: str })));
194
234
  }
195
235
  const blob = base64Encode(value);
196
236
  return pure(blob === null
197
237
  ? errorResult(`content is not byte-aligned: ${r.hash}`)
198
- : okResult(toJson({ ...meta, content: blob })));
238
+ : okResult(toJson({ ...refinedMeta, blob })));
199
239
  });
200
240
  });
201
241
  }),
@@ -16,13 +16,15 @@ export declare const proof: {
16
16
  addGetRoundTrips: () => void;
17
17
  getUntypedReturnsText: () => void;
18
18
  getTypedReturnsBinaryJson: () => void;
19
+ getMetaRecognizesRevisionDialect: () => void;
20
+ getContentRecognizesRevisionDialect: () => void;
19
21
  listEnumeratesStoredHashes: () => void;
20
22
  addInvalidContentIsError: () => void;
21
23
  addBadLengthContentIsError: () => void;
22
24
  addBase64OverLimitIsError: () => void;
23
25
  addTextOverLimitIsError: () => void;
24
26
  addTextAtLimitSucceeds: () => void;
25
- addBase64AtLimitIsError: () => void;
27
+ addBase64AtLimitSucceeds: () => void;
26
28
  getUnterminatedHashIsError: () => void;
27
29
  addMissingContentIsError: () => void;
28
30
  getMissingHashArgumentIsError: () => void;
@@ -1,20 +1,21 @@
1
- import { assert, assertEq } from "../../asserts/module.f.js";
2
- import { pure } from "../../effects/module.f.js";
3
- import { run } from "../../effects/mock/module.f.js";
4
- import { asBase, asNominal, create } from "../../effects/memory/module.f.js";
5
- import { msb, u8ListToVec, vec8, repeat, length, maxLengthBytes } from "../../types/bit_vec/module.f.js";
6
- import { vecToCBase32 } from "../../cbase32/module.f.js";
7
- import { encode as base64Encode } from "../../base64/module.f.js";
8
- import { utf8 } from "../../text/module.f.js";
9
- import { fileCas } from "../module.f.js";
10
- import { sha256 } from "../../crypto/sha2/module.f.js";
11
- import { nonEmpty, empty as elEmpty } from "../../effects/list/module.f.js";
12
- import { mcpStep, uninitializedState, } from "../../mcp/module.f.js";
13
- import { emptyState, virtual } from "../../effects/node/virtual/module.f.js";
14
- import { casConfig, casMcpHandlers } from "./module.f.js";
15
- import { ok as resultOk } from "../../types/result/module.f.js";
16
- import { stdioTransport } from "../../mcp/stdio/module.f.js";
17
- import { fromVec } from "../../types/uint8array/module.f.js";
1
+ import { assert, assertEq } from '../../asserts/module.f.js';
2
+ import { pure } from '../../effects/module.f.js';
3
+ import { run } from '../../effects/mock/module.f.js';
4
+ import { asBase, asNominal, create } from '../../effects/memory/module.f.js';
5
+ import { msb, u8ListToVec, vec8, repeat, length, maxLengthBytes } from '../../types/bit_vec/module.f.js';
6
+ import { vecToCBase32 } from '../../basen/cbase32/module.f.js';
7
+ import { encode as base64Encode } from '../../basen/base64/module.f.js';
8
+ import { utf8 } from '../../text/module.f.js';
9
+ import { fileCas } from '../module.f.js';
10
+ import { dialect as revisionDialect, mediaType as revisionMediaType } from '../../media/revision/module.f.js';
11
+ import { sha256 } from '../../crypto/sha2/module.f.js';
12
+ import { nonEmpty, empty as elEmpty } from '../../effects/list/module.f.js';
13
+ import { mcpStep, uninitializedState, } from '../../mcp/module.f.js';
14
+ import { emptyState, virtual } from '../../effects/node/virtual/module.f.js';
15
+ import { casConfig, casMcpHandlers } from './module.f.js';
16
+ import { ok as resultOk } from '../../types/result/module.f.js';
17
+ import { stdioTransport } from '../../mcp/stdio/module.f.js';
18
+ import { fromVec } from '../../types/uint8array/module.f.js';
18
19
  const initialTestState = { memory: { next: 0, values: {} } };
19
20
  const mock = {
20
21
  memCreate: value => state => {
@@ -104,10 +105,13 @@ const item0 = (resp) => resultOf(resp).content[0];
104
105
  const textOf = (resp) => item0(resp).text;
105
106
  // A plain text sample for text add→get round-trips.
106
107
  const textSample = 'hello, world!';
108
+ // A valid `vnd.fjs.revision` blob: zero parents, so `subject` must be (and is,
109
+ // per `fs/media/revision/proof.f.ts`) a valid cbase32 hash on its own.
110
+ const revisionSample = `{"dialect":"${revisionDialect}","subject":"8","parents":[]}`;
107
111
  // A base64-encoded binary payload for binary add→get round-trips.
108
112
  const binarySample = base64Encode(vec8(0x2an));
109
113
  // A base64 blob whose leading bytes are the PNG magic-byte signature, so
110
- // `cas_get` detects its type and returns base64 with mime_type image/png.
114
+ // `cas_get` detects its type and returns base64 with mimeType image/png.
111
115
  const pngSample = base64Encode(u8ListToVec(msb)([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x01]));
112
116
  // Returns the RFC 4648 base64 encoding of `n` zero bytes, computed directly
113
117
  // without bigint arithmetic — independent of `base64.encode` so these tests
@@ -141,9 +145,10 @@ const largeMultiChunkBlobMeta = (chunk0, chunk1, expectedType, expectedMime) =>
141
145
  assert(!resultOf(metaResp).isError);
142
146
  const meta = JSON.parse(textOf(metaResp));
143
147
  assertEq(meta.type, expectedType);
144
- assertEq(meta.mime_type, expectedMime);
148
+ assertEq(meta.mimeType, expectedMime);
145
149
  assertEq(meta.length, Number((length(chunk0) + length(chunk1)) / 8n));
146
- assertEq(meta.content, undefined);
150
+ assertEq(meta.text, undefined);
151
+ assertEq(meta.blob, undefined);
147
152
  };
148
153
  // A full `maxLengthBytes`-long chunk of repeated ASCII 'a' — valid UTF-8.
149
154
  const asciiChunk = repeat(maxLengthBytes)(vec8(0x61n));
@@ -207,7 +212,7 @@ export const proof = {
207
212
  // This test originally timed out under `bun test`'s native 5s per-test
208
213
  // limit (12-14s observed in CI on PR #1201) — the cost was in
209
214
  // `base64Encode`, quadratic before the `baseN.vecToString` fix (see
210
- // `fs/base64/proof.f.ts` `encodeLargeVecIsSlow`). Now well under budget on
215
+ // `fs/basen/base64/proof.f.ts` `encodeLargeVecIsSlow`). Now well under budget on
211
216
  // both engines.
212
217
  getContentBase64InflationOverflowWritesInternalError: () => {
213
218
  const [root, hash] = seedBlob({})([oversizedBase64Chunk]);
@@ -271,10 +276,10 @@ export const proof = {
271
276
  const [, getResp] = session(call(2, 'cas_add', { content: textSample }), call(3, 'cas_get', { hash }));
272
277
  assert(!resultOf(getResp).isError);
273
278
  const result = JSON.parse(textOf(getResp));
274
- assertEq(result.mime_type, 'text/plain');
279
+ assertEq(result.mimeType, 'text/plain');
275
280
  assertEq(result.type, 'text');
276
281
  assertEq(result.length, textSample.length);
277
- assertEq(result.content, undefined);
282
+ assertEq(result.text, undefined);
278
283
  },
279
284
  // cas_get with content:true returns inline content.
280
285
  textAddGetContentRoundTrips: () => {
@@ -284,8 +289,8 @@ export const proof = {
284
289
  assert(!resultOf(getResp).isError);
285
290
  const result = JSON.parse(textOf(getResp));
286
291
  assertEq(result.type, 'text');
287
- assertEq(result.mime_type, 'text/plain');
288
- assertEq(result.content, textSample);
292
+ assertEq(result.mimeType, 'text/plain');
293
+ assertEq(result.text, textSample);
289
294
  },
290
295
  // Binary add→get round-trip: store as base64, retrieve metadata without content.
291
296
  binaryAddGetMetaRoundTrips: () => {
@@ -294,9 +299,9 @@ export const proof = {
294
299
  const [, getResp] = session(call(2, 'cas_add', { content: binarySample, type: 'base64' }), call(3, 'cas_get', { hash }));
295
300
  assert(!resultOf(getResp).isError);
296
301
  const result = JSON.parse(textOf(getResp));
297
- assertEq(result.content, undefined);
302
+ assertEq(result.text, undefined);
298
303
  assertEq(result.type, 'text');
299
- assertEq(result.mime_type, 'text/plain');
304
+ assertEq(result.mimeType, 'text/plain');
300
305
  },
301
306
  // Binary add→get with content:true returns inline base64 content.
302
307
  binaryAddGetContentRoundTrips: () => {
@@ -306,7 +311,7 @@ export const proof = {
306
311
  assert(!resultOf(getResp).isError);
307
312
  const result = JSON.parse(textOf(getResp));
308
313
  assertEq(result.type, 'text');
309
- assertEq(result.content, '*');
314
+ assertEq(result.text, '*');
310
315
  },
311
316
  addGetRoundTrips: () => {
312
317
  const [addResp] = session(call(2, 'cas_add', { content: textSample }));
@@ -314,7 +319,7 @@ export const proof = {
314
319
  const [, getResp] = session(call(2, 'cas_add', { content: textSample }), call(3, 'cas_get', { hash, content: true }));
315
320
  assert(!resultOf(getResp).isError);
316
321
  const result = JSON.parse(textOf(getResp));
317
- assertEq(result.content, textSample);
322
+ assertEq(result.text, textSample);
318
323
  },
319
324
  // Text content (no magic-byte match, valid UTF-8) comes back with type:'text' when content requested.
320
325
  getUntypedReturnsText: () => {
@@ -324,9 +329,9 @@ export const proof = {
324
329
  assertEq(item0(getResp) === null ? null : item0(getResp).type, 'text');
325
330
  const result = JSON.parse(textOf(getResp));
326
331
  assertEq(result.type, 'text');
327
- assertEq(result.mime_type, 'text/plain');
332
+ assertEq(result.mimeType, 'text/plain');
328
333
  },
329
- // Bytes with a recognised PNG signature come back as base64 with mime_type image/png when content requested.
334
+ // Bytes with a recognised PNG signature come back as base64 with mimeType image/png when content requested.
330
335
  getTypedReturnsBinaryJson: () => {
331
336
  const [addResp] = session(call(2, 'cas_add', { content: pngSample, type: 'base64' }));
332
337
  const hash = textOf(addResp);
@@ -335,8 +340,33 @@ export const proof = {
335
340
  assertEq(item0(getResp).type, 'text');
336
341
  const result = JSON.parse(textOf(getResp));
337
342
  assertEq(result.type, 'base64');
338
- assertEq(result.mime_type, 'image/png');
339
- assertEq(result.content, pngSample);
343
+ assertEq(result.mimeType, 'image/png');
344
+ assertEq(result.blob, pngSample);
345
+ },
346
+ // A stored `vnd.fjs.revision` blob is recognized by metadata-only
347
+ // `cas_get` (content:false, the default) — the CAS read path routes the
348
+ // bounded, whole-blob-text case through the dialect-aware detector rather
349
+ // than only reporting the streaming text/plain verdict.
350
+ getMetaRecognizesRevisionDialect: () => {
351
+ const [addResp] = session(call(2, 'cas_add', { content: revisionSample }));
352
+ const hash = textOf(addResp);
353
+ const [, metaResp] = session(call(2, 'cas_add', { content: revisionSample }), call(3, 'cas_get', { hash }));
354
+ assert(!resultOf(metaResp).isError);
355
+ const meta = JSON.parse(textOf(metaResp));
356
+ assertEq(meta.mimeType, revisionMediaType);
357
+ assertEq(meta.type, 'text');
358
+ },
359
+ // Same dialect recognition on the `content: true` path, alongside the
360
+ // inline text payload.
361
+ getContentRecognizesRevisionDialect: () => {
362
+ const [addResp] = session(call(2, 'cas_add', { content: revisionSample }));
363
+ const hash = textOf(addResp);
364
+ const [, getResp] = session(call(2, 'cas_add', { content: revisionSample }), call(3, 'cas_get', { hash, content: true }));
365
+ assert(!resultOf(getResp).isError);
366
+ const result = JSON.parse(textOf(getResp));
367
+ assertEq(result.mimeType, revisionMediaType);
368
+ assertEq(result.type, 'text');
369
+ assertEq(result.text, revisionSample);
340
370
  },
341
371
  listEnumeratesStoredHashes: () => {
342
372
  const [addResp, listResp] = session(call(2, 'cas_add', { content: textSample }), call(3, 'cas_list', {}));
@@ -375,16 +405,14 @@ export const proof = {
375
405
  assert(!resultOf(resp).isError);
376
406
  assert(textOf(resp).length > 0);
377
407
  },
378
- // base64 of exactly maxLengthBytes — currently returns isError because
379
- // base64Decode measures the raw pre-trim body (1_048_578 bits) against
380
- // maxLength before stripping the 2 padding bits that would land it exactly at
381
- // maxLength. Assert the current failing behavior; flip to a success assertion
382
- // once `fs/base64/todo/decode-rejects-max-size-input.md` is fixed.
383
- addBase64AtLimitIsError: () => {
408
+ // base64 of exactly maxLengthBytes — base64Decode trims the encoding's
409
+ // padding bits from the last character before measuring the result
410
+ // against maxLength, so a payload landing exactly at the limit decodes
411
+ // and stores cleanly.
412
+ addBase64AtLimitSucceeds: () => {
384
413
  const [resp] = session(call(2, 'cas_add', { content: base64OfA(maxLengthBytes), type: 'base64' }));
385
- assertEq(resultOf(resp).isError, true);
386
- assert(textOf(resp).includes('too large or malformed'));
387
- assert(textOf(resp).includes('cas add'));
414
+ assert(!resultOf(resp).isError);
415
+ assert(textOf(resp).length > 0);
388
416
  },
389
417
  getUnterminatedHashIsError: () => {
390
418
  const [resp] = session(call(2, 'cas_get', { hash: '0' }));
@@ -423,10 +451,10 @@ export const proof = {
423
451
  const [, metaResp] = session(call(2, 'cas_add', { content: 'text content' }), call(3, 'cas_get', { hash }));
424
452
  assert(!resultOf(metaResp).isError);
425
453
  const meta = JSON.parse(textOf(metaResp));
426
- assertEq(meta.mime_type, 'text/plain');
454
+ assertEq(meta.mimeType, 'text/plain');
427
455
  assertEq(meta.type, 'text');
428
456
  assertEq(meta.length, 12);
429
- assertEq(meta.content, undefined);
457
+ assertEq(meta.text, undefined);
430
458
  },
431
459
  getMetaBinaryBlob: () => {
432
460
  const [addResp] = session(call(2, 'cas_add', { content: pngSample, type: 'base64' }));
@@ -434,10 +462,10 @@ export const proof = {
434
462
  const [, metaResp] = session(call(2, 'cas_add', { content: pngSample, type: 'base64' }), call(3, 'cas_get', { hash }));
435
463
  assert(!resultOf(metaResp).isError);
436
464
  const meta = JSON.parse(textOf(metaResp));
437
- assertEq(meta.mime_type, 'image/png');
465
+ assertEq(meta.mimeType, 'image/png');
438
466
  assertEq(meta.type, 'base64');
439
467
  assertEq(meta.length, 10);
440
- assertEq(meta.content, undefined);
468
+ assertEq(meta.blob, undefined);
441
469
  },
442
470
  getMetaOctetStreamForUnknownBinary: () => {
443
471
  const binaryContent = u8ListToVec(msb)([0xFF, 0xFE, 0x00, 0x01]);
@@ -447,9 +475,9 @@ export const proof = {
447
475
  const [, metaResp] = session(call(2, 'cas_add', { content: binaryB64, type: 'base64' }), call(3, 'cas_get', { hash }));
448
476
  assert(!resultOf(metaResp).isError);
449
477
  const meta = JSON.parse(textOf(metaResp));
450
- assertEq(meta.mime_type, 'application/octet-stream');
478
+ assertEq(meta.mimeType, 'application/octet-stream');
451
479
  assertEq(meta.type, 'base64');
452
- assertEq(meta.content, undefined);
480
+ assertEq(meta.blob, undefined);
453
481
  },
454
482
  // A NUL-bearing blob is valid UTF-8 yet binary: cas_get must report
455
483
  // base64/octet-stream, not text/plain.
@@ -461,7 +489,7 @@ export const proof = {
461
489
  const [, metaResp] = session(call(2, 'cas_add', { content: nulB64, type: 'base64' }), call(3, 'cas_get', { hash }));
462
490
  assert(!resultOf(metaResp).isError);
463
491
  const meta = JSON.parse(textOf(metaResp));
464
- assertEq(meta.mime_type, 'application/octet-stream');
492
+ assertEq(meta.mimeType, 'application/octet-stream');
465
493
  assertEq(meta.type, 'base64');
466
494
  },
467
495
  getMetaMissingHashIsError: () => {
@@ -482,8 +510,8 @@ export const proof = {
482
510
  const [, getResp] = session(call(2, 'cas_add', { content: binaryB64, type: 'base64' }), call(3, 'cas_get', { hash, content: true }));
483
511
  assert(!resultOf(getResp).isError);
484
512
  const result = JSON.parse(textOf(getResp));
485
- assertEq(result.mime_type, 'application/octet-stream');
513
+ assertEq(result.mimeType, 'application/octet-stream');
486
514
  assertEq(result.type, 'base64');
487
- assertEq(result.content, binaryB64);
515
+ assertEq(result.blob, binaryB64);
488
516
  },
489
517
  };
@@ -3,16 +3,16 @@
3
3
  *
4
4
  * @module
5
5
  */
6
- import { sha256 } from "../crypto/sha2/module.f.js";
7
- import { join, normalize, parse } from "../path/module.f.js";
8
- import { empty, length, maxLengthBytes, msb, vec } from "../types/bit_vec/module.f.js";
9
- import { cBase32ToVec, vecToCBase32 } from "../cbase32/module.f.js";
10
- import { foldStep, forEachStep, okStep, pure } from "../effects/module.f.js";
11
- import { access, createExclusive, isNotFound, mkdir, now, randomInt, readBytes, readdir, rename, rm, stat, writeBytes, } from "../effects/node/module.f.js";
12
- import { toOption } from "../types/nullable/module.f.js";
13
- import { error, ok, unwrap } from "../types/result/module.f.js";
14
- import { splitAt } from "../types/string/module.f.js";
15
- import { nonEmpty, empty as elEmpty } from "../effects/list/module.f.js";
6
+ import { sha256 } from '../crypto/sha2/module.f.js';
7
+ import { join, normalize, parse } from '../path/module.f.js';
8
+ import { empty, length, maxLengthBytes, msb, vec } from '../types/bit_vec/module.f.js';
9
+ import { cBase32ToVec, vecToCBase32 } from '../basen/cbase32/module.f.js';
10
+ import { foldStep, forEachStep, okStep, pure } from '../effects/module.f.js';
11
+ import { access, createExclusive, isNotFound, mkdir, now, randomInt, readBytes, readdir, rename, rm, stat, writeBytes, } from '../effects/node/module.f.js';
12
+ import { toOption } from '../types/nullable/module.f.js';
13
+ import { error, ok, unwrap } from '../types/result/module.f.js';
14
+ import { splitAt } from '../types/string/module.f.js';
15
+ import { nonEmpty, empty as elEmpty } from '../effects/list/module.f.js';
16
16
  const split2 = splitAt(2);
17
17
  const prefix = '.cas';
18
18
  /** Converts a content key to its sharded relative CAS file path. */
@@ -2,9 +2,11 @@ import { type FileCasOperation } from './module.f.ts';
2
2
  import { type Effect } from '../effects/module.f.ts';
3
3
  import { type ReadFile, type WriteFile, type Rm, type Mkdir } from '../effects/node/module.f.ts';
4
4
  type TestOp = FileCasOperation | WriteFile | ReadFile | Rm | Mkdir;
5
+ declare const testAddBigFile: () => Effect<TestOp, void>;
6
+ declare const testAddAndGetBigFile: () => Effect<TestOp, void>;
5
7
  export declare const proof: {
6
- addBigFile: () => Effect<TestOp, void>;
7
- addAndGetBigFile: () => Effect<TestOp, void>;
8
+ addBigFile: typeof testAddBigFile;
9
+ addAndGetBigFile: typeof testAddAndGetBigFile;
8
10
  casWriteRead: () => void;
9
11
  casReadMissingShard: () => void;
10
12
  casWriteMultiChunk: () => void;
package/fs/cas/proof.f.js CHANGED
@@ -1,13 +1,13 @@
1
- import { length, maxLength, msb, vec, vec8 } from "../types/bit_vec/module.f.js";
2
- import { cBase32ToVec, vecToCBase32 } from "../cbase32/module.f.js";
3
- import { computeSync, sha256 } from "../crypto/sha2/module.f.js";
4
- import { fileCas, casAddFile, casUpload } from "./module.f.js";
5
- import { pure } from "../effects/module.f.js";
6
- import { mkdir, writeFile, rm, readFile, access } from "../effects/node/module.f.js";
7
- import { error, ok } from "../types/result/module.f.js";
8
- import { emptyState, virtual } from "../effects/node/virtual/module.f.js";
9
- import { join } from "../path/module.f.js";
10
- import { nonEmpty, empty } from "../effects/list/module.f.js";
1
+ import { length, maxLength, msb, vec, vec8 } from '../types/bit_vec/module.f.js';
2
+ import { cBase32ToVec, vecToCBase32 } from '../basen/cbase32/module.f.js';
3
+ import { computeSync, sha256 } from '../crypto/sha2/module.f.js';
4
+ import { fileCas, casAddFile, casUpload } from './module.f.js';
5
+ import { pure } from '../effects/module.f.js';
6
+ import { mkdir, writeFile, rm, readFile, access } from '../effects/node/module.f.js';
7
+ import { error, ok } from '../types/result/module.f.js';
8
+ import { emptyState, virtual } from '../effects/node/virtual/module.f.js';
9
+ import { join } from '../path/module.f.js';
10
+ import { nonEmpty, empty } from '../effects/list/module.f.js';
11
11
  const testDir = './test-cas-cli';
12
12
  // Create a 128 KiB big file content (at the max Vec size limit)
13
13
  // This tests the boundary where files are at the chunk size limit
@@ -4,8 +4,8 @@
4
4
  *
5
5
  * @module
6
6
  */
7
- import { bun } from "../config/module.f.js";
8
- import { clean, install, test, uses } from "../common/module.f.js";
7
+ import { bun } from '../config/module.f.js';
8
+ import { clean, install, test, uses } from '../common/module.f.js';
9
9
  export const bunSteps = (version) => clean([
10
10
  install(uses('oven-sh/setup-bun', { 'bun-version': bun })),
11
11
  install({ run: `bun install -g functionalscript@${version}` }),
@@ -7,9 +7,9 @@
7
7
  */
8
8
  import { actions, images } from '../config/module.f.ts';
9
9
  import { type Ts } from '../../types/rtti/ts/module.f.ts';
10
- export declare const os: readonly ["ubuntu", "macos", "windows"];
10
+ export declare const os: readonly ['ubuntu', 'macos', 'windows'];
11
11
  export type Os = typeof os[number];
12
- export declare const architecture: readonly ["intel", "arm"];
12
+ export declare const architecture: readonly ['intel', 'arm'];
13
13
  export type Architecture = typeof architecture[number];
14
14
  export type Image = typeof images[Os][Architecture];
15
15
  export declare const stepSchema: {
@@ -5,10 +5,10 @@
5
5
  *
6
6
  * @module
7
7
  */
8
- import { actions, images } from "../config/module.f.js";
9
- import { option, array, record, string } from "../../types/rtti/module.f.js";
10
- import {} from "../../types/rtti/ts/module.f.js";
11
- import { parse as rttiParse } from "../../types/rtti/parse/module.f.js";
8
+ import { actions, images } from '../config/module.f.js';
9
+ import { option, array, record, string } from '../../types/rtti/module.f.js';
10
+ import {} from '../../types/rtti/ts/module.f.js';
11
+ import { parse as rttiParse } from '../../types/rtti/parse/module.f.js';
12
12
  export const os = ['ubuntu', 'macos', 'windows'];
13
13
  export const architecture = ['intel', 'arm'];
14
14
  export const stepSchema = {