@earendil-works/pi-durable 1.0.4 → 1.2.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 (196) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/README.md +149 -11
  3. package/dist/codemode/codemode.d.ts +173 -0
  4. package/dist/codemode/codemode.d.ts.map +1 -0
  5. package/dist/codemode/codemode.js +886 -0
  6. package/dist/codemode/codemode.js.map +1 -0
  7. package/dist/codemode/describe.d.ts +38 -0
  8. package/dist/codemode/describe.d.ts.map +1 -0
  9. package/dist/codemode/describe.js +119 -0
  10. package/dist/codemode/describe.js.map +1 -0
  11. package/dist/codemode/index.d.ts +3 -0
  12. package/dist/codemode/index.d.ts.map +1 -0
  13. package/dist/codemode/index.js +3 -0
  14. package/dist/codemode/index.js.map +1 -0
  15. package/dist/codemode/models.d.ts +28 -0
  16. package/dist/codemode/models.d.ts.map +1 -0
  17. package/dist/codemode/models.js +231 -0
  18. package/dist/codemode/models.js.map +1 -0
  19. package/dist/codemode/output.d.ts +41 -0
  20. package/dist/codemode/output.d.ts.map +1 -0
  21. package/dist/codemode/output.js +167 -0
  22. package/dist/codemode/output.js.map +1 -0
  23. package/dist/env/index.d.ts +42 -0
  24. package/dist/env/index.d.ts.map +1 -1
  25. package/dist/env/index.js.map +1 -1
  26. package/dist/errors.d.ts +20 -3
  27. package/dist/errors.d.ts.map +1 -1
  28. package/dist/errors.js +34 -5
  29. package/dist/errors.js.map +1 -1
  30. package/dist/harness/agent.d.ts +5 -2
  31. package/dist/harness/agent.d.ts.map +1 -1
  32. package/dist/harness/agent.js +72 -25
  33. package/dist/harness/agent.js.map +1 -1
  34. package/dist/harness/compaction.d.ts +6 -1
  35. package/dist/harness/compaction.d.ts.map +1 -1
  36. package/dist/harness/compaction.js +11 -8
  37. package/dist/harness/compaction.js.map +1 -1
  38. package/dist/harness/context.d.ts +29 -1
  39. package/dist/harness/context.d.ts.map +1 -1
  40. package/dist/harness/context.js +125 -24
  41. package/dist/harness/context.js.map +1 -1
  42. package/dist/harness/events.d.ts +35 -15
  43. package/dist/harness/events.d.ts.map +1 -1
  44. package/dist/harness/events.js +77 -23
  45. package/dist/harness/events.js.map +1 -1
  46. package/dist/harness/generation.d.ts +2 -0
  47. package/dist/harness/generation.d.ts.map +1 -1
  48. package/dist/harness/generation.js +34 -11
  49. package/dist/harness/generation.js.map +1 -1
  50. package/dist/harness/harness.d.ts +7 -0
  51. package/dist/harness/harness.d.ts.map +1 -1
  52. package/dist/harness/harness.js +56 -28
  53. package/dist/harness/harness.js.map +1 -1
  54. package/dist/harness/inbox.d.ts +16 -4
  55. package/dist/harness/inbox.d.ts.map +1 -1
  56. package/dist/harness/inbox.js +26 -3
  57. package/dist/harness/inbox.js.map +1 -1
  58. package/dist/harness/live.d.ts +74 -17
  59. package/dist/harness/live.d.ts.map +1 -1
  60. package/dist/harness/live.js +66 -14
  61. package/dist/harness/live.js.map +1 -1
  62. package/dist/harness/scheduler.d.ts +18 -5
  63. package/dist/harness/scheduler.d.ts.map +1 -1
  64. package/dist/harness/scheduler.js +794 -168
  65. package/dist/harness/scheduler.js.map +1 -1
  66. package/dist/harness/submissions.d.ts +7 -4
  67. package/dist/harness/submissions.d.ts.map +1 -1
  68. package/dist/harness/submissions.js +32 -13
  69. package/dist/harness/submissions.js.map +1 -1
  70. package/dist/harness/task-graph.d.ts +1 -1
  71. package/dist/harness/task-graph.d.ts.map +1 -1
  72. package/dist/harness/task-graph.js +15 -10
  73. package/dist/harness/task-graph.js.map +1 -1
  74. package/dist/harness/tool.d.ts +45 -5
  75. package/dist/harness/tool.d.ts.map +1 -1
  76. package/dist/harness/tool.js +388 -63
  77. package/dist/harness/tool.js.map +1 -1
  78. package/dist/harness/types.d.ts +171 -15
  79. package/dist/harness/types.d.ts.map +1 -1
  80. package/dist/harness/types.js.map +1 -1
  81. package/dist/harness/util.d.ts +6 -1
  82. package/dist/harness/util.d.ts.map +1 -1
  83. package/dist/harness/util.js +5 -2
  84. package/dist/harness/util.js.map +1 -1
  85. package/dist/harness/view.d.ts +6 -2
  86. package/dist/harness/view.d.ts.map +1 -1
  87. package/dist/harness/view.js +22 -12
  88. package/dist/harness/view.js.map +1 -1
  89. package/dist/images/cloudflare.d.ts +4 -0
  90. package/dist/images/cloudflare.d.ts.map +1 -0
  91. package/dist/images/cloudflare.js +9 -0
  92. package/dist/images/cloudflare.js.map +1 -0
  93. package/dist/images/exif.d.ts +3 -0
  94. package/dist/images/exif.d.ts.map +1 -0
  95. package/dist/images/exif.js +71 -0
  96. package/dist/images/exif.js.map +1 -0
  97. package/dist/images/index.d.ts +18 -0
  98. package/dist/images/index.d.ts.map +1 -0
  99. package/dist/images/index.js +125 -0
  100. package/dist/images/index.js.map +1 -0
  101. package/dist/images/node-worker.d.ts +17 -0
  102. package/dist/images/node-worker.d.ts.map +1 -0
  103. package/dist/images/node-worker.js +16 -0
  104. package/dist/images/node-worker.js.map +1 -0
  105. package/dist/images/node.d.ts +21 -0
  106. package/dist/images/node.d.ts.map +1 -0
  107. package/dist/images/node.js +121 -0
  108. package/dist/images/node.js.map +1 -0
  109. package/dist/index.d.ts +6 -6
  110. package/dist/index.d.ts.map +1 -1
  111. package/dist/index.js +3 -3
  112. package/dist/index.js.map +1 -1
  113. package/dist/search.d.ts +13 -0
  114. package/dist/search.d.ts.map +1 -0
  115. package/dist/search.js +85 -0
  116. package/dist/search.js.map +1 -0
  117. package/dist/session/observation.d.ts +10 -3
  118. package/dist/session/observation.d.ts.map +1 -1
  119. package/dist/session/observation.js +24 -34
  120. package/dist/session/observation.js.map +1 -1
  121. package/dist/session/session.d.ts +71 -6
  122. package/dist/session/session.d.ts.map +1 -1
  123. package/dist/session/session.js +463 -50
  124. package/dist/session/session.js.map +1 -1
  125. package/dist/session/transaction.d.ts +2 -0
  126. package/dist/session/transaction.d.ts.map +1 -1
  127. package/dist/session/transaction.js +19 -1
  128. package/dist/session/transaction.js.map +1 -1
  129. package/dist/storage/jsonl/storage.d.ts +8 -0
  130. package/dist/storage/jsonl/storage.d.ts.map +1 -1
  131. package/dist/storage/jsonl/storage.js +2 -1
  132. package/dist/storage/jsonl/storage.js.map +1 -1
  133. package/dist/storage/memory.d.ts +2 -0
  134. package/dist/storage/memory.d.ts.map +1 -1
  135. package/dist/storage/memory.js +79 -27
  136. package/dist/storage/memory.js.map +1 -1
  137. package/dist/storage/scan.d.ts +18 -0
  138. package/dist/storage/scan.d.ts.map +1 -0
  139. package/dist/storage/scan.js +29 -0
  140. package/dist/storage/scan.js.map +1 -0
  141. package/dist/storage/sqlite/cloudflare.d.ts +46 -0
  142. package/dist/storage/sqlite/cloudflare.d.ts.map +1 -0
  143. package/dist/storage/sqlite/cloudflare.js +106 -0
  144. package/dist/storage/sqlite/cloudflare.js.map +1 -0
  145. package/dist/storage/sqlite/storage.d.ts +2 -0
  146. package/dist/storage/sqlite/storage.d.ts.map +1 -1
  147. package/dist/storage/sqlite/storage.js +77 -27
  148. package/dist/storage/sqlite/storage.js.map +1 -1
  149. package/dist/testing/env-conformance.d.ts.map +1 -1
  150. package/dist/testing/env-conformance.js +100 -0
  151. package/dist/testing/env-conformance.js.map +1 -1
  152. package/dist/testing/runner.d.ts +1 -1
  153. package/dist/testing/runner.d.ts.map +1 -1
  154. package/dist/testing/runner.js.map +1 -1
  155. package/dist/testing/storage-conformance.d.ts.map +1 -1
  156. package/dist/testing/storage-conformance.js +61 -2
  157. package/dist/testing/storage-conformance.js.map +1 -1
  158. package/dist/testing/types.d.ts +2 -0
  159. package/dist/testing/types.d.ts.map +1 -1
  160. package/dist/testing/types.js.map +1 -1
  161. package/dist/tool-search/index.d.ts +2 -0
  162. package/dist/tool-search/index.d.ts.map +1 -0
  163. package/dist/tool-search/index.js +2 -0
  164. package/dist/tool-search/index.js.map +1 -0
  165. package/dist/tool-search/tool-search.d.ts +23 -0
  166. package/dist/tool-search/tool-search.d.ts.map +1 -0
  167. package/dist/tool-search/tool-search.js +84 -0
  168. package/dist/tool-search/tool-search.js.map +1 -0
  169. package/dist/tools/bash.d.ts +10 -2
  170. package/dist/tools/bash.d.ts.map +1 -1
  171. package/dist/tools/bash.js +27 -9
  172. package/dist/tools/bash.js.map +1 -1
  173. package/dist/tools/edit.js +1 -1
  174. package/dist/tools/edit.js.map +1 -1
  175. package/dist/tools/image-processor.d.ts +47 -0
  176. package/dist/tools/image-processor.d.ts.map +1 -0
  177. package/dist/tools/image-processor.js +30 -0
  178. package/dist/tools/image-processor.js.map +1 -0
  179. package/dist/tools/image.d.ts +8 -0
  180. package/dist/tools/image.d.ts.map +1 -1
  181. package/dist/tools/image.js +47 -0
  182. package/dist/tools/image.js.map +1 -1
  183. package/dist/tools/index.d.ts +25 -2
  184. package/dist/tools/index.d.ts.map +1 -1
  185. package/dist/tools/index.js +13 -5
  186. package/dist/tools/index.js.map +1 -1
  187. package/dist/tools/read.d.ts +10 -2
  188. package/dist/tools/read.d.ts.map +1 -1
  189. package/dist/tools/read.js +87 -28
  190. package/dist/tools/read.js.map +1 -1
  191. package/dist/tools/write.js +1 -1
  192. package/dist/tools/write.js.map +1 -1
  193. package/dist/types.d.ts +89 -12
  194. package/dist/types.d.ts.map +1 -1
  195. package/dist/types.js.map +1 -1
  196. package/package.json +50 -5
@@ -0,0 +1,71 @@
1
+ // EXIF orientation of JPEG and WebP files, read from the bytes without decoding the image.
2
+ /** The EXIF orientation of a JPEG or WebP, 1 to 8; 1 when absent or unreadable. */
3
+ export function exifOrientation(bytes) {
4
+ const tiff = tiffStart(bytes);
5
+ if (tiff < 0 || tiff + 8 > bytes.length)
6
+ return 1;
7
+ const little = bytes[tiff] === 0x49 && bytes[tiff + 1] === 0x49;
8
+ const u16 = (at) => little ? bytes[at] | (bytes[at + 1] << 8) : (bytes[at] << 8) | bytes[at + 1];
9
+ const u32 = (at) => little
10
+ ? (bytes[at] | (bytes[at + 1] << 8) | (bytes[at + 2] << 16) | (bytes[at + 3] << 24)) >>> 0
11
+ : ((bytes[at] << 24) | (bytes[at + 1] << 16) | (bytes[at + 2] << 8) | bytes[at + 3]) >>> 0;
12
+ const directory = tiff + u32(tiff + 4);
13
+ if (directory + 2 > bytes.length)
14
+ return 1;
15
+ const entries = u16(directory);
16
+ for (let index = 0; index < entries; index++) {
17
+ const entry = directory + 2 + index * 12;
18
+ if (entry + 12 > bytes.length)
19
+ return 1;
20
+ // Tag 0x0112 is Orientation, a SHORT whose value sits in the entry.
21
+ if (u16(entry) === 0x0112) {
22
+ const value = u16(entry + 8);
23
+ return value >= 1 && value <= 8 ? value : 1;
24
+ }
25
+ }
26
+ return 1;
27
+ }
28
+ /** Where the TIFF header of a JPEG's APP1 or a WebP's EXIF chunk starts; -1 when there is none. */
29
+ function tiffStart(bytes) {
30
+ if (bytes[0] === 0xff && bytes[1] === 0xd8) {
31
+ for (let offset = 2; offset + 4 <= bytes.length;) {
32
+ if (bytes[offset] !== 0xff)
33
+ return -1;
34
+ const marker = bytes[offset + 1];
35
+ if (marker === 0xff) {
36
+ offset++;
37
+ continue;
38
+ }
39
+ if (marker === 0xe1 && isExifHeader(bytes, offset + 4))
40
+ return offset + 10;
41
+ offset += 2 + ((bytes[offset + 2] << 8) | bytes[offset + 3]);
42
+ }
43
+ return -1;
44
+ }
45
+ if (ascii(bytes, 0, "RIFF") && ascii(bytes, 8, "WEBP")) {
46
+ for (let offset = 12; offset + 8 <= bytes.length;) {
47
+ const size = (bytes[offset + 4] |
48
+ (bytes[offset + 5] << 8) |
49
+ (bytes[offset + 6] << 16) |
50
+ (bytes[offset + 7] << 24)) >>>
51
+ 0;
52
+ // Some WebP files prefix the TIFF header with "Exif\0\0".
53
+ if (ascii(bytes, offset, "EXIF"))
54
+ return isExifHeader(bytes, offset + 8) ? offset + 14 : offset + 8;
55
+ // RIFF chunks are padded to an even size.
56
+ offset += 8 + size + (size % 2);
57
+ }
58
+ }
59
+ return -1;
60
+ }
61
+ function isExifHeader(bytes, offset) {
62
+ return ascii(bytes, offset, "Exif") && bytes[offset + 4] === 0 && bytes[offset + 5] === 0;
63
+ }
64
+ function ascii(bytes, offset, text) {
65
+ for (let index = 0; index < text.length; index++) {
66
+ if (bytes[offset + index] !== text.charCodeAt(index))
67
+ return false;
68
+ }
69
+ return true;
70
+ }
71
+ //# sourceMappingURL=exif.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exif.js","sourceRoot":"","sources":["../../src/images/exif.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAE3F,mFAAmF;AACnF,MAAM,UAAU,eAAe,CAAC,KAAiB;IAChD,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAC9B,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM;QAAE,OAAO,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC;IAChE,MAAM,GAAG,GAAG,CAAC,EAAU,EAAU,EAAE,CAClC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAE,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAE,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,EAAE,GAAG,CAAC,CAAE,CAAC;IAClF,MAAM,GAAG,GAAG,CAAC,EAAU,EAAU,EAAE,CAClC,MAAM;QACL,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAE,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAE,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAE,IAAI,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC;QAC9F,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAE,IAAI,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAE,IAAI,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAE,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,EAAE,GAAG,CAAC,CAAE,CAAC,KAAK,CAAC,CAAC;IACjG,MAAM,SAAS,GAAG,IAAI,GAAG,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;IACvC,IAAI,SAAS,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM;QAAE,OAAO,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC;IAC/B,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC;QAC9C,MAAM,KAAK,GAAG,SAAS,GAAG,CAAC,GAAG,KAAK,GAAG,EAAE,CAAC;QACzC,IAAI,KAAK,GAAG,EAAE,GAAG,KAAK,CAAC,MAAM;YAAE,OAAO,CAAC,CAAC;QACxC,oEAAoE;QACpE,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,MAAM,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;YAC7B,OAAO,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7C,CAAC;IACF,CAAC;IACD,OAAO,CAAC,CAAC;AACV,CAAC;AAED,mGAAmG;AACnG,SAAS,SAAS,CAAC,KAAiB;IACnC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC5C,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,GAAI,CAAC;YACnD,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI;gBAAE,OAAO,CAAC,CAAC,CAAC;YACtC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;YAClC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBACrB,MAAM,EAAE,CAAC;gBACT,SAAS;YACV,CAAC;YACD,IAAI,MAAM,KAAK,IAAI,IAAI,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,CAAC;gBAAE,OAAO,MAAM,GAAG,EAAE,CAAC;YAC3E,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,CAAC;QAChE,CAAC;QACD,OAAO,CAAC,CAAC,CAAC;IACX,CAAC;IACD,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,CAAC,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC;QACxD,KAAK,IAAI,MAAM,GAAG,EAAE,EAAE,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,GAAI,CAAC;YACpD,MAAM,IAAI,GACT,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE;gBAClB,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,IAAI,CAAC,CAAC;gBACzB,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,IAAI,EAAE,CAAC;gBAC1B,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,IAAI,EAAE,CAAC,CAAC;gBAC5B,CAAC,CAAC;YACH,0DAA0D;YAC1D,IAAI,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC;gBAAE,OAAO,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;YACpG,0CAA0C;YAC1C,MAAM,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;QACjC,CAAC;IACF,CAAC;IACD,OAAO,CAAC,CAAC,CAAC;AACX,CAAC;AAED,SAAS,YAAY,CAAC,KAAiB,EAAE,MAAc;IACtD,OAAO,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;AAC3F,CAAC;AAED,SAAS,KAAK,CAAC,KAAiB,EAAE,MAAc,EAAE,IAAY;IAC7D,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;QAClD,IAAI,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,KAAK,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;IACpE,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC","sourcesContent":["// EXIF orientation of JPEG and WebP files, read from the bytes without decoding the image.\n\n/** The EXIF orientation of a JPEG or WebP, 1 to 8; 1 when absent or unreadable. */\nexport function exifOrientation(bytes: Uint8Array): number {\n\tconst tiff = tiffStart(bytes);\n\tif (tiff < 0 || tiff + 8 > bytes.length) return 1;\n\tconst little = bytes[tiff] === 0x49 && bytes[tiff + 1] === 0x49;\n\tconst u16 = (at: number): number =>\n\t\tlittle ? bytes[at]! | (bytes[at + 1]! << 8) : (bytes[at]! << 8) | bytes[at + 1]!;\n\tconst u32 = (at: number): number =>\n\t\tlittle\n\t\t\t? (bytes[at]! | (bytes[at + 1]! << 8) | (bytes[at + 2]! << 16) | (bytes[at + 3]! << 24)) >>> 0\n\t\t\t: ((bytes[at]! << 24) | (bytes[at + 1]! << 16) | (bytes[at + 2]! << 8) | bytes[at + 3]!) >>> 0;\n\tconst directory = tiff + u32(tiff + 4);\n\tif (directory + 2 > bytes.length) return 1;\n\tconst entries = u16(directory);\n\tfor (let index = 0; index < entries; index++) {\n\t\tconst entry = directory + 2 + index * 12;\n\t\tif (entry + 12 > bytes.length) return 1;\n\t\t// Tag 0x0112 is Orientation, a SHORT whose value sits in the entry.\n\t\tif (u16(entry) === 0x0112) {\n\t\t\tconst value = u16(entry + 8);\n\t\t\treturn value >= 1 && value <= 8 ? value : 1;\n\t\t}\n\t}\n\treturn 1;\n}\n\n/** Where the TIFF header of a JPEG's APP1 or a WebP's EXIF chunk starts; -1 when there is none. */\nfunction tiffStart(bytes: Uint8Array): number {\n\tif (bytes[0] === 0xff && bytes[1] === 0xd8) {\n\t\tfor (let offset = 2; offset + 4 <= bytes.length; ) {\n\t\t\tif (bytes[offset] !== 0xff) return -1;\n\t\t\tconst marker = bytes[offset + 1]!;\n\t\t\tif (marker === 0xff) {\n\t\t\t\toffset++;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (marker === 0xe1 && isExifHeader(bytes, offset + 4)) return offset + 10;\n\t\t\toffset += 2 + ((bytes[offset + 2]! << 8) | bytes[offset + 3]!);\n\t\t}\n\t\treturn -1;\n\t}\n\tif (ascii(bytes, 0, \"RIFF\") && ascii(bytes, 8, \"WEBP\")) {\n\t\tfor (let offset = 12; offset + 8 <= bytes.length; ) {\n\t\t\tconst size =\n\t\t\t\t(bytes[offset + 4]! |\n\t\t\t\t\t(bytes[offset + 5]! << 8) |\n\t\t\t\t\t(bytes[offset + 6]! << 16) |\n\t\t\t\t\t(bytes[offset + 7]! << 24)) >>>\n\t\t\t\t0;\n\t\t\t// Some WebP files prefix the TIFF header with \"Exif\\0\\0\".\n\t\t\tif (ascii(bytes, offset, \"EXIF\")) return isExifHeader(bytes, offset + 8) ? offset + 14 : offset + 8;\n\t\t\t// RIFF chunks are padded to an even size.\n\t\t\toffset += 8 + size + (size % 2);\n\t\t}\n\t}\n\treturn -1;\n}\n\nfunction isExifHeader(bytes: Uint8Array, offset: number): boolean {\n\treturn ascii(bytes, offset, \"Exif\") && bytes[offset + 4] === 0 && bytes[offset + 5] === 0;\n}\n\nfunction ascii(bytes: Uint8Array, offset: number, text: string): boolean {\n\tfor (let index = 0; index < text.length; index++) {\n\t\tif (bytes[offset + index] !== text.charCodeAt(index)) return false;\n\t}\n\treturn true;\n}\n"]}
@@ -0,0 +1,18 @@
1
+ import { type SyncInitInput } from "@silvia-odwyer/photon/photon_rs.js";
2
+ import type { ImageProcessor } from "../tools/image-processor.ts";
3
+ /**
4
+ * An `ImageProcessor` on Photon (Rust compiled to WebAssembly), for `createCodingTools({ images })`. `wasm` is
5
+ * Photon's `photon_rs_bg.wasm` as bytes or as a compiled module: `@earendil-works/pi-durable/images/node` reads it from
6
+ * the installed package, `@earendil-works/pi-durable/images/cloudflare` imports it as a Workers module. Elsewhere, such
7
+ * as a browser, fetch the file and pass its bytes. Photon loads once per process; later calls reuse the first `wasm`.
8
+ *
9
+ * An image already upright, in a format providers take inline, and within the limits is returned as it is, once it
10
+ * decodes. Otherwise it is turned upright by its EXIF orientation, scaled to the
11
+ * maximum width and height, and encoded as PNG or JPEG at falling qualities (JPEG first for JPEG sources), then at
12
+ * smaller dimensions, 3/4 at a time, until the base64 fits. Formats providers do not take inline (BMP) become PNG.
13
+ *
14
+ * The work runs on the calling thread: about a second and a half for a 12-megapixel photo. Decoding takes the image's
15
+ * RGBA size in WebAssembly memory, which does not shrink again; leave the processor out on memory-constrained hosts.
16
+ */
17
+ export declare function createPhotonImages(wasm: SyncInitInput): ImageProcessor;
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/images/index.ts"],"names":[],"mappings":"AACA,OAAO,EAON,KAAK,aAAa,EAClB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAK,EAAe,cAAc,EAAiB,MAAM,6BAA6B,CAAC;AAO9F;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,aAAa,GAAG,cAAc,CAGtE"}
@@ -0,0 +1,125 @@
1
+ // The package declares only `module`, which bundlers use but Node does not: import the file itself.
2
+ import { fliph, flipv, initSync, PhotonImage, resize, SamplingFilter, } from "@silvia-odwyer/photon/photon_rs.js";
3
+ import { base64Length, INLINE_IMAGE_TYPES, toBase64 } from "../tools/image-processor.js";
4
+ import { exifOrientation } from "./exif.js";
5
+ /** JPEG qualities tried in order. */
6
+ const JPEG_QUALITIES = [80, 70, 55, 40];
7
+ /**
8
+ * An `ImageProcessor` on Photon (Rust compiled to WebAssembly), for `createCodingTools({ images })`. `wasm` is
9
+ * Photon's `photon_rs_bg.wasm` as bytes or as a compiled module: `@earendil-works/pi-durable/images/node` reads it from
10
+ * the installed package, `@earendil-works/pi-durable/images/cloudflare` imports it as a Workers module. Elsewhere, such
11
+ * as a browser, fetch the file and pass its bytes. Photon loads once per process; later calls reuse the first `wasm`.
12
+ *
13
+ * An image already upright, in a format providers take inline, and within the limits is returned as it is, once it
14
+ * decodes. Otherwise it is turned upright by its EXIF orientation, scaled to the
15
+ * maximum width and height, and encoded as PNG or JPEG at falling qualities (JPEG first for JPEG sources), then at
16
+ * smaller dimensions, 3/4 at a time, until the base64 fits. Formats providers do not take inline (BMP) become PNG.
17
+ *
18
+ * The work runs on the calling thread: about a second and a half for a 12-megapixel photo. Decoding takes the image's
19
+ * RGBA size in WebAssembly memory, which does not shrink again; leave the processor out on memory-constrained hosts.
20
+ */
21
+ export function createPhotonImages(wasm) {
22
+ initSync({ module: wasm });
23
+ return { prepare: async (bytes, mimeType, limits) => prepare(bytes, mimeType, limits) };
24
+ }
25
+ function prepare(bytes, mimeType, limits) {
26
+ const orientation = exifOrientation(bytes);
27
+ const inline = INLINE_IMAGE_TYPES.has(mimeType);
28
+ let image;
29
+ try {
30
+ // Decoded even when it is returned as it is: a damaged file is an error, not an image the provider rejects.
31
+ image = PhotonImage.new_from_byteslice(bytes);
32
+ if (inline &&
33
+ orientation === 1 &&
34
+ image.get_width() <= limits.maxWidth &&
35
+ image.get_height() <= limits.maxHeight &&
36
+ base64Length(bytes.byteLength) <= limits.maxBytes) {
37
+ return { data: toBase64(bytes), mimeType };
38
+ }
39
+ if (orientation >= 5) {
40
+ const upright = transposed(image, orientation);
41
+ // Freed first, so the upright copy reuses its WebAssembly memory.
42
+ image.free();
43
+ image = undefined;
44
+ image = new PhotonImage(upright.pixels, upright.width, upright.height);
45
+ }
46
+ else if (orientation !== 1) {
47
+ if (orientation !== 4)
48
+ fliph(image);
49
+ if (orientation !== 2)
50
+ flipv(image);
51
+ }
52
+ const width = image.get_width();
53
+ const height = image.get_height();
54
+ const scale = Math.min(1, limits.maxWidth / width, limits.maxHeight / height);
55
+ let target = { width: Math.max(1, Math.round(width * scale)), height: Math.max(1, Math.round(height * scale)) };
56
+ for (;;) {
57
+ const encoded = encodeWithin(image, target, limits.maxBytes, mimeType === "image/jpeg");
58
+ if (encoded !== undefined) {
59
+ const resized = target.width === width && target.height === height
60
+ ? {}
61
+ : { resized: { from: { width, height }, to: target } };
62
+ const converted = encoded.mimeType === mimeType ? {} : { convertedFrom: mimeType };
63
+ return { ...encoded, ...converted, ...resized };
64
+ }
65
+ if (target.width === 1 && target.height === 1)
66
+ return undefined;
67
+ target = {
68
+ width: Math.max(1, Math.floor(target.width * 0.75)),
69
+ height: Math.max(1, Math.floor(target.height * 0.75)),
70
+ };
71
+ }
72
+ }
73
+ catch {
74
+ // Photon throws for bytes it cannot decode.
75
+ return undefined;
76
+ }
77
+ finally {
78
+ image?.free();
79
+ }
80
+ }
81
+ /**
82
+ * `image` at `size` in the first encoding whose base64 fits `maxBytes`: PNG, then JPEG at falling qualities, or the
83
+ * JPEG qualities first when `jpegFirst`; `undefined` if none fits.
84
+ */
85
+ function encodeWithin(image, size, maxBytes, jpegFirst) {
86
+ const same = size.width === image.get_width() && size.height === image.get_height();
87
+ const scaled = same ? image : resize(image, size.width, size.height, SamplingFilter.Lanczos3);
88
+ try {
89
+ const png = { mimeType: "image/png", encode: () => scaled.get_bytes() };
90
+ const jpegs = JPEG_QUALITIES.map((quality) => ({
91
+ mimeType: "image/jpeg",
92
+ encode: () => scaled.get_bytes_jpeg(quality),
93
+ }));
94
+ for (const candidate of jpegFirst ? [...jpegs, png] : [png, ...jpegs]) {
95
+ const bytes = candidate.encode();
96
+ if (base64Length(bytes.byteLength) <= maxBytes)
97
+ return { data: toBase64(bytes), mimeType: candidate.mimeType };
98
+ }
99
+ return undefined;
100
+ }
101
+ finally {
102
+ if (!same)
103
+ scaled.free();
104
+ }
105
+ }
106
+ /**
107
+ * The RGBA pixels of `image` turned upright for EXIF `orientation` 5 to 8, the orientations that swap width and
108
+ * height. Photon's own `rotate` drops pixels at right angles, so the pixels are moved here.
109
+ */
110
+ function transposed(image, orientation) {
111
+ const width = image.get_width();
112
+ const height = image.get_height();
113
+ const source = image.get_raw_pixels();
114
+ const pixels = new Uint8Array(source.length);
115
+ for (let y = 0; y < height; y++) {
116
+ for (let x = 0; x < width; x++) {
117
+ // Where (x, y) lands in the upright image, which is `height` wide.
118
+ const outX = orientation === 5 || orientation === 8 ? y : height - 1 - y;
119
+ const outY = orientation === 5 || orientation === 6 ? x : width - 1 - x;
120
+ pixels.set(source.subarray((y * width + x) * 4, (y * width + x) * 4 + 4), (outY * height + outX) * 4);
121
+ }
122
+ }
123
+ return { pixels, width: height, height: width };
124
+ }
125
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/images/index.ts"],"names":[],"mappings":"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","sourcesContent":["// The package declares only `module`, which bundlers use but Node does not: import the file itself.\nimport {\n\tfliph,\n\tflipv,\n\tinitSync,\n\tPhotonImage,\n\tresize,\n\tSamplingFilter,\n\ttype SyncInitInput,\n} from \"@silvia-odwyer/photon/photon_rs.js\";\nimport type { ImageLimits, ImageProcessor, PreparedImage } from \"../tools/image-processor.ts\";\nimport { base64Length, INLINE_IMAGE_TYPES, toBase64 } from \"../tools/image-processor.ts\";\nimport { exifOrientation } from \"./exif.ts\";\n\n/** JPEG qualities tried in order. */\nconst JPEG_QUALITIES = [80, 70, 55, 40];\n\n/**\n * An `ImageProcessor` on Photon (Rust compiled to WebAssembly), for `createCodingTools({ images })`. `wasm` is\n * Photon's `photon_rs_bg.wasm` as bytes or as a compiled module: `@earendil-works/pi-durable/images/node` reads it from\n * the installed package, `@earendil-works/pi-durable/images/cloudflare` imports it as a Workers module. Elsewhere, such\n * as a browser, fetch the file and pass its bytes. Photon loads once per process; later calls reuse the first `wasm`.\n *\n * An image already upright, in a format providers take inline, and within the limits is returned as it is, once it\n * decodes. Otherwise it is turned upright by its EXIF orientation, scaled to the\n * maximum width and height, and encoded as PNG or JPEG at falling qualities (JPEG first for JPEG sources), then at\n * smaller dimensions, 3/4 at a time, until the base64 fits. Formats providers do not take inline (BMP) become PNG.\n *\n * The work runs on the calling thread: about a second and a half for a 12-megapixel photo. Decoding takes the image's\n * RGBA size in WebAssembly memory, which does not shrink again; leave the processor out on memory-constrained hosts.\n */\nexport function createPhotonImages(wasm: SyncInitInput): ImageProcessor {\n\tinitSync({ module: wasm });\n\treturn { prepare: async (bytes, mimeType, limits) => prepare(bytes, mimeType, limits) };\n}\n\nfunction prepare(bytes: Uint8Array, mimeType: string, limits: ImageLimits): PreparedImage | undefined {\n\tconst orientation = exifOrientation(bytes);\n\tconst inline = INLINE_IMAGE_TYPES.has(mimeType);\n\tlet image: PhotonImage | undefined;\n\ttry {\n\t\t// Decoded even when it is returned as it is: a damaged file is an error, not an image the provider rejects.\n\t\timage = PhotonImage.new_from_byteslice(bytes);\n\t\tif (\n\t\t\tinline &&\n\t\t\torientation === 1 &&\n\t\t\timage.get_width() <= limits.maxWidth &&\n\t\t\timage.get_height() <= limits.maxHeight &&\n\t\t\tbase64Length(bytes.byteLength) <= limits.maxBytes\n\t\t) {\n\t\t\treturn { data: toBase64(bytes), mimeType };\n\t\t}\n\t\tif (orientation >= 5) {\n\t\t\tconst upright = transposed(image, orientation);\n\t\t\t// Freed first, so the upright copy reuses its WebAssembly memory.\n\t\t\timage.free();\n\t\t\timage = undefined;\n\t\t\timage = new PhotonImage(upright.pixels, upright.width, upright.height);\n\t\t} else if (orientation !== 1) {\n\t\t\tif (orientation !== 4) fliph(image);\n\t\t\tif (orientation !== 2) flipv(image);\n\t\t}\n\t\tconst width = image.get_width();\n\t\tconst height = image.get_height();\n\t\tconst scale = Math.min(1, limits.maxWidth / width, limits.maxHeight / height);\n\t\tlet target = { width: Math.max(1, Math.round(width * scale)), height: Math.max(1, Math.round(height * scale)) };\n\t\tfor (;;) {\n\t\t\tconst encoded = encodeWithin(image, target, limits.maxBytes, mimeType === \"image/jpeg\");\n\t\t\tif (encoded !== undefined) {\n\t\t\t\tconst resized =\n\t\t\t\t\ttarget.width === width && target.height === height\n\t\t\t\t\t\t? {}\n\t\t\t\t\t\t: { resized: { from: { width, height }, to: target } };\n\t\t\t\tconst converted = encoded.mimeType === mimeType ? {} : { convertedFrom: mimeType };\n\t\t\t\treturn { ...encoded, ...converted, ...resized };\n\t\t\t}\n\t\t\tif (target.width === 1 && target.height === 1) return undefined;\n\t\t\ttarget = {\n\t\t\t\twidth: Math.max(1, Math.floor(target.width * 0.75)),\n\t\t\t\theight: Math.max(1, Math.floor(target.height * 0.75)),\n\t\t\t};\n\t\t}\n\t} catch {\n\t\t// Photon throws for bytes it cannot decode.\n\t\treturn undefined;\n\t} finally {\n\t\timage?.free();\n\t}\n}\n\n/**\n * `image` at `size` in the first encoding whose base64 fits `maxBytes`: PNG, then JPEG at falling qualities, or the\n * JPEG qualities first when `jpegFirst`; `undefined` if none fits.\n */\nfunction encodeWithin(\n\timage: PhotonImage,\n\tsize: { readonly width: number; readonly height: number },\n\tmaxBytes: number,\n\tjpegFirst: boolean,\n): { readonly data: string; readonly mimeType: string } | undefined {\n\tconst same = size.width === image.get_width() && size.height === image.get_height();\n\tconst scaled = same ? image : resize(image, size.width, size.height, SamplingFilter.Lanczos3);\n\ttry {\n\t\tconst png = { mimeType: \"image/png\", encode: () => scaled.get_bytes() };\n\t\tconst jpegs = JPEG_QUALITIES.map((quality) => ({\n\t\t\tmimeType: \"image/jpeg\",\n\t\t\tencode: () => scaled.get_bytes_jpeg(quality),\n\t\t}));\n\t\tfor (const candidate of jpegFirst ? [...jpegs, png] : [png, ...jpegs]) {\n\t\t\tconst bytes = candidate.encode();\n\t\t\tif (base64Length(bytes.byteLength) <= maxBytes) return { data: toBase64(bytes), mimeType: candidate.mimeType };\n\t\t}\n\t\treturn undefined;\n\t} finally {\n\t\tif (!same) scaled.free();\n\t}\n}\n\n/**\n * The RGBA pixels of `image` turned upright for EXIF `orientation` 5 to 8, the orientations that swap width and\n * height. Photon's own `rotate` drops pixels at right angles, so the pixels are moved here.\n */\nfunction transposed(\n\timage: PhotonImage,\n\torientation: number,\n): { readonly pixels: Uint8Array; readonly width: number; readonly height: number } {\n\tconst width = image.get_width();\n\tconst height = image.get_height();\n\tconst source = image.get_raw_pixels();\n\tconst pixels = new Uint8Array(source.length);\n\tfor (let y = 0; y < height; y++) {\n\t\tfor (let x = 0; x < width; x++) {\n\t\t\t// Where (x, y) lands in the upright image, which is `height` wide.\n\t\t\tconst outX = orientation === 5 || orientation === 8 ? y : height - 1 - y;\n\t\t\tconst outY = orientation === 5 || orientation === 6 ? x : width - 1 - x;\n\t\t\tpixels.set(source.subarray((y * width + x) * 4, (y * width + x) * 4 + 4), (outY * height + outX) * 4);\n\t\t}\n\t}\n\treturn { pixels, width: height, height: width };\n}\n"]}
@@ -0,0 +1,17 @@
1
+ import type { ImageLimits, PreparedImage } from "../tools/image-processor.ts";
2
+ /** One request: the image to prepare, and its ID for the reply. */
3
+ export type PrepareRequest = {
4
+ readonly id: number;
5
+ readonly bytes: Uint8Array;
6
+ readonly mimeType: string;
7
+ readonly limits: ImageLimits;
8
+ };
9
+ /** The reply to a request: its result, or why it failed. */
10
+ export type PrepareReply = {
11
+ readonly id: number;
12
+ readonly result: PreparedImage | undefined;
13
+ } | {
14
+ readonly id: number;
15
+ readonly error: string;
16
+ };
17
+ //# sourceMappingURL=node-worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-worker.d.ts","sourceRoot":"","sources":["../../src/images/node-worker.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAG9E,mEAAmE;AACnE,MAAM,MAAM,cAAc,GAAG;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;CAC7B,CAAC;AAEF,4DAA4D;AAC5D,MAAM,MAAM,YAAY,GACrB;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,aAAa,GAAG,SAAS,CAAA;CAAE,GACnE;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC"}
@@ -0,0 +1,16 @@
1
+ // The worker thread of `createNodePhotonImages()`: Photon prepares images here, off the caller's event loop.
2
+ import { readFileSync } from "node:fs";
3
+ import { createRequire } from "node:module";
4
+ import { parentPort } from "node:worker_threads";
5
+ import { createPhotonImages } from "./index.js";
6
+ const port = parentPort;
7
+ if (port === null)
8
+ throw new Error("The Photon image worker needs a parent thread");
9
+ const images = createPhotonImages(readFileSync(createRequire(import.meta.url).resolve("@silvia-odwyer/photon/photon_rs_bg.wasm")));
10
+ port.on("message", (request) => {
11
+ void images.prepare(request.bytes, request.mimeType, request.limits).then((result) => port.postMessage({ id: request.id, result }), (error) => port.postMessage({
12
+ id: request.id,
13
+ error: error instanceof Error ? error.message : String(error),
14
+ }));
15
+ });
16
+ //# sourceMappingURL=node-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-worker.js","sourceRoot":"","sources":["../../src/images/node-worker.ts"],"names":[],"mappings":"AAAA,6GAA6G;AAC7G,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAehD,MAAM,IAAI,GAAG,UAAU,CAAC;AACxB,IAAI,IAAI,KAAK,IAAI;IAAE,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;AACpF,MAAM,MAAM,GAAG,kBAAkB,CAChC,YAAY,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,yCAAyC,CAAC,CAAC,CAC/F,CAAC;AACF,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,OAAuB,EAAE,EAAE;IAC9C,KAAK,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CACxE,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,MAAM,EAAyB,CAAC,EAC/E,CAAC,KAAc,EAAE,EAAE,CAClB,IAAI,CAAC,WAAW,CAAC;QAChB,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;KACtC,CAAC,CAC1B,CAAC;AACH,CAAC,CAAC,CAAC","sourcesContent":["// The worker thread of `createNodePhotonImages()`: Photon prepares images here, off the caller's event loop.\nimport { readFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { parentPort } from \"node:worker_threads\";\nimport type { ImageLimits, PreparedImage } from \"../tools/image-processor.ts\";\nimport { createPhotonImages } from \"./index.ts\";\n\n/** One request: the image to prepare, and its ID for the reply. */\nexport type PrepareRequest = {\n\treadonly id: number;\n\treadonly bytes: Uint8Array;\n\treadonly mimeType: string;\n\treadonly limits: ImageLimits;\n};\n\n/** The reply to a request: its result, or why it failed. */\nexport type PrepareReply =\n\t| { readonly id: number; readonly result: PreparedImage | undefined }\n\t| { readonly id: number; readonly error: string };\n\nconst port = parentPort;\nif (port === null) throw new Error(\"The Photon image worker needs a parent thread\");\nconst images = createPhotonImages(\n\treadFileSync(createRequire(import.meta.url).resolve(\"@silvia-odwyer/photon/photon_rs_bg.wasm\")),\n);\nport.on(\"message\", (request: PrepareRequest) => {\n\tvoid images.prepare(request.bytes, request.mimeType, request.limits).then(\n\t\t(result) => port.postMessage({ id: request.id, result } satisfies PrepareReply),\n\t\t(error: unknown) =>\n\t\t\tport.postMessage({\n\t\t\t\tid: request.id,\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t} satisfies PrepareReply),\n\t);\n});\n"]}
@@ -0,0 +1,21 @@
1
+ import type { ImageProcessor } from "../tools/image-processor.ts";
2
+ export type NodePhotonImagesOptions = {
3
+ /**
4
+ * Prepare images in a worker thread, so a large photo does not block the event loop for the second or two Photon
5
+ * takes. Default `true`; `false` prepares them on the calling thread.
6
+ */
7
+ readonly worker?: boolean;
8
+ /**
9
+ * How long the worker stays after its last image before it exits, freeing Photon's WebAssembly memory, which never
10
+ * shrinks while it lives. The next image starts a new one. Default 30 s.
11
+ */
12
+ readonly idleMs?: number;
13
+ };
14
+ /**
15
+ * `createPhotonImages()` for Node and Bun, with Photon's WebAssembly read from the installed `@silvia-odwyer/photon`,
16
+ * by default in a worker thread that keeps the process alive only while it prepares an image. A worker that cannot
17
+ * start falls back to the calling thread. A single-file binary cannot resolve the package: read its own copy of
18
+ * `photon_rs_bg.wasm` and call `createPhotonImages()`.
19
+ */
20
+ export declare function createNodePhotonImages(options?: NodePhotonImagesOptions): Promise<ImageProcessor>;
21
+ //# sourceMappingURL=node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/images/node.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAe,cAAc,EAAiB,MAAM,6BAA6B,CAAC;AAI9F,MAAM,MAAM,uBAAuB,GAAG;IACrC;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAAC,OAAO,GAAE,uBAA4B,GAAG,OAAO,CAAC,cAAc,CAAC,CAqB3G"}
@@ -0,0 +1,121 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { createRequire } from "node:module";
3
+ import { Worker } from "node:worker_threads";
4
+ import { createPhotonImages } from "./index.js";
5
+ /**
6
+ * `createPhotonImages()` for Node and Bun, with Photon's WebAssembly read from the installed `@silvia-odwyer/photon`,
7
+ * by default in a worker thread that keeps the process alive only while it prepares an image. A worker that cannot
8
+ * start falls back to the calling thread. A single-file binary cannot resolve the package: read its own copy of
9
+ * `photon_rs_bg.wasm` and call `createPhotonImages()`.
10
+ */
11
+ export async function createNodePhotonImages(options = {}) {
12
+ if (options.worker === false)
13
+ return inProcess();
14
+ const idleMs = options.idleMs ?? 30_000;
15
+ let thread;
16
+ let fallback;
17
+ return {
18
+ async prepare(bytes, mimeType, limits) {
19
+ if (fallback !== undefined)
20
+ return (await fallback).prepare(bytes, mimeType, limits);
21
+ try {
22
+ thread ??= new PhotonThread(idleMs, () => {
23
+ thread = undefined;
24
+ });
25
+ return await thread.prepare(bytes, mimeType, limits);
26
+ }
27
+ catch (error) {
28
+ if (!(error instanceof WorkerUnavailable))
29
+ throw error;
30
+ // No worker on this platform or build: prepare here from now on.
31
+ fallback = inProcess();
32
+ return (await fallback).prepare(bytes, mimeType, limits);
33
+ }
34
+ },
35
+ };
36
+ }
37
+ async function inProcess() {
38
+ const path = createRequire(import.meta.url).resolve("@silvia-odwyer/photon/photon_rs_bg.wasm");
39
+ return createPhotonImages(await readFile(path));
40
+ }
41
+ /** The worker could not start, as opposed to failing on one image. */
42
+ class WorkerUnavailable extends Error {
43
+ }
44
+ /** One worker thread and the requests it has not answered; it exits after `idleMs` without requests. */
45
+ class PhotonThread {
46
+ #worker;
47
+ #pending = new Map();
48
+ #idleMs;
49
+ #onExit;
50
+ #nextId = 0;
51
+ #idle;
52
+ /** Whether the worker answered once: a failure before that means it is unavailable. */
53
+ #started = false;
54
+ constructor(idleMs, onExit) {
55
+ this.#idleMs = idleMs;
56
+ this.#onExit = onExit;
57
+ // Run from source under a TypeScript runtime, as in tests; built, the worker sits next to this file as JS.
58
+ const file = import.meta.url.endsWith(".ts") ? "./node-worker.ts" : "./node-worker.js";
59
+ try {
60
+ this.#worker = new Worker(new URL(file, import.meta.url));
61
+ }
62
+ catch (error) {
63
+ throw new WorkerUnavailable("The Photon image worker cannot start", { cause: error });
64
+ }
65
+ this.#worker.unref();
66
+ this.#worker.on("message", (reply) => {
67
+ this.#started = true;
68
+ const request = this.#pending.get(reply.id);
69
+ if (request === undefined)
70
+ return;
71
+ this.#pending.delete(reply.id);
72
+ if ("error" in reply)
73
+ request.reject(new Error(reply.error));
74
+ else
75
+ request.resolve(reply.result);
76
+ this.#settled();
77
+ });
78
+ const fail = (error) => {
79
+ const failure = this.#started
80
+ ? error
81
+ : new WorkerUnavailable("The Photon image worker cannot start", { cause: error });
82
+ for (const request of this.#pending.values())
83
+ request.reject(failure);
84
+ this.#pending.clear();
85
+ this.#exit();
86
+ };
87
+ this.#worker.on("error", fail);
88
+ this.#worker.on("exit", (code) => fail(new Error(`The Photon image worker exited with code ${code}`)));
89
+ }
90
+ prepare(bytes, mimeType, limits) {
91
+ const id = this.#nextId++;
92
+ const request = Promise.withResolvers();
93
+ this.#pending.set(id, request);
94
+ if (this.#idle !== undefined)
95
+ clearTimeout(this.#idle);
96
+ this.#idle = undefined;
97
+ // A pending image keeps the process alive, as one prepared on the calling thread would.
98
+ this.#worker.ref();
99
+ // A copy, transferred: the caller keeps its bytes.
100
+ const copy = bytes.slice();
101
+ this.#worker.postMessage({ id, bytes: copy, mimeType, limits }, [copy.buffer]);
102
+ return request.promise;
103
+ }
104
+ #settled() {
105
+ if (this.#pending.size > 0)
106
+ return;
107
+ this.#worker.unref();
108
+ this.#idle = setTimeout(() => {
109
+ this.#exit();
110
+ void this.#worker.terminate();
111
+ }, this.#idleMs);
112
+ this.#idle.unref();
113
+ }
114
+ #exit() {
115
+ if (this.#idle !== undefined)
116
+ clearTimeout(this.#idle);
117
+ this.#idle = undefined;
118
+ this.#onExit();
119
+ }
120
+ }
121
+ //# sourceMappingURL=node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/images/node.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { createRequire } from \"node:module\";\nimport { Worker } from \"node:worker_threads\";\nimport type { ImageLimits, ImageProcessor, PreparedImage } from \"../tools/image-processor.ts\";\nimport { createPhotonImages } from \"./index.ts\";\nimport type { PrepareReply, PrepareRequest } from \"./node-worker.ts\";\n\nexport type NodePhotonImagesOptions = {\n\t/**\n\t * Prepare images in a worker thread, so a large photo does not block the event loop for the second or two Photon\n\t * takes. Default `true`; `false` prepares them on the calling thread.\n\t */\n\treadonly worker?: boolean;\n\t/**\n\t * How long the worker stays after its last image before it exits, freeing Photon's WebAssembly memory, which never\n\t * shrinks while it lives. The next image starts a new one. Default 30 s.\n\t */\n\treadonly idleMs?: number;\n};\n\n/**\n * `createPhotonImages()` for Node and Bun, with Photon's WebAssembly read from the installed `@silvia-odwyer/photon`,\n * by default in a worker thread that keeps the process alive only while it prepares an image. A worker that cannot\n * start falls back to the calling thread. A single-file binary cannot resolve the package: read its own copy of\n * `photon_rs_bg.wasm` and call `createPhotonImages()`.\n */\nexport async function createNodePhotonImages(options: NodePhotonImagesOptions = {}): Promise<ImageProcessor> {\n\tif (options.worker === false) return inProcess();\n\tconst idleMs = options.idleMs ?? 30_000;\n\tlet thread: PhotonThread | undefined;\n\tlet fallback: Promise<ImageProcessor> | undefined;\n\treturn {\n\t\tasync prepare(bytes, mimeType, limits) {\n\t\t\tif (fallback !== undefined) return (await fallback).prepare(bytes, mimeType, limits);\n\t\t\ttry {\n\t\t\t\tthread ??= new PhotonThread(idleMs, () => {\n\t\t\t\t\tthread = undefined;\n\t\t\t\t});\n\t\t\t\treturn await thread.prepare(bytes, mimeType, limits);\n\t\t\t} catch (error) {\n\t\t\t\tif (!(error instanceof WorkerUnavailable)) throw error;\n\t\t\t\t// No worker on this platform or build: prepare here from now on.\n\t\t\t\tfallback = inProcess();\n\t\t\t\treturn (await fallback).prepare(bytes, mimeType, limits);\n\t\t\t}\n\t\t},\n\t};\n}\n\nasync function inProcess(): Promise<ImageProcessor> {\n\tconst path = createRequire(import.meta.url).resolve(\"@silvia-odwyer/photon/photon_rs_bg.wasm\");\n\treturn createPhotonImages(await readFile(path));\n}\n\n/** The worker could not start, as opposed to failing on one image. */\nclass WorkerUnavailable extends Error {}\n\n/** One worker thread and the requests it has not answered; it exits after `idleMs` without requests. */\nclass PhotonThread {\n\treadonly #worker: Worker;\n\treadonly #pending = new Map<number, PromiseWithResolvers<PreparedImage | undefined>>();\n\treadonly #idleMs: number;\n\treadonly #onExit: () => void;\n\t#nextId = 0;\n\t#idle: ReturnType<typeof setTimeout> | undefined;\n\t/** Whether the worker answered once: a failure before that means it is unavailable. */\n\t#started = false;\n\n\tconstructor(idleMs: number, onExit: () => void) {\n\t\tthis.#idleMs = idleMs;\n\t\tthis.#onExit = onExit;\n\t\t// Run from source under a TypeScript runtime, as in tests; built, the worker sits next to this file as JS.\n\t\tconst file = import.meta.url.endsWith(\".ts\") ? \"./node-worker.ts\" : \"./node-worker.js\";\n\t\ttry {\n\t\t\tthis.#worker = new Worker(new URL(file, import.meta.url));\n\t\t} catch (error) {\n\t\t\tthrow new WorkerUnavailable(\"The Photon image worker cannot start\", { cause: error });\n\t\t}\n\t\tthis.#worker.unref();\n\t\tthis.#worker.on(\"message\", (reply: PrepareReply) => {\n\t\t\tthis.#started = true;\n\t\t\tconst request = this.#pending.get(reply.id);\n\t\t\tif (request === undefined) return;\n\t\t\tthis.#pending.delete(reply.id);\n\t\t\tif (\"error\" in reply) request.reject(new Error(reply.error));\n\t\t\telse request.resolve(reply.result);\n\t\t\tthis.#settled();\n\t\t});\n\t\tconst fail = (error: unknown): void => {\n\t\t\tconst failure = this.#started\n\t\t\t\t? error\n\t\t\t\t: new WorkerUnavailable(\"The Photon image worker cannot start\", { cause: error });\n\t\t\tfor (const request of this.#pending.values()) request.reject(failure);\n\t\t\tthis.#pending.clear();\n\t\t\tthis.#exit();\n\t\t};\n\t\tthis.#worker.on(\"error\", fail);\n\t\tthis.#worker.on(\"exit\", (code) => fail(new Error(`The Photon image worker exited with code ${code}`)));\n\t}\n\n\tprepare(bytes: Uint8Array, mimeType: string, limits: ImageLimits): Promise<PreparedImage | undefined> {\n\t\tconst id = this.#nextId++;\n\t\tconst request = Promise.withResolvers<PreparedImage | undefined>();\n\t\tthis.#pending.set(id, request);\n\t\tif (this.#idle !== undefined) clearTimeout(this.#idle);\n\t\tthis.#idle = undefined;\n\t\t// A pending image keeps the process alive, as one prepared on the calling thread would.\n\t\tthis.#worker.ref();\n\t\t// A copy, transferred: the caller keeps its bytes.\n\t\tconst copy = bytes.slice();\n\t\tthis.#worker.postMessage({ id, bytes: copy, mimeType, limits } satisfies PrepareRequest, [copy.buffer]);\n\t\treturn request.promise;\n\t}\n\n\t#settled(): void {\n\t\tif (this.#pending.size > 0) return;\n\t\tthis.#worker.unref();\n\t\tthis.#idle = setTimeout(() => {\n\t\t\tthis.#exit();\n\t\t\tvoid this.#worker.terminate();\n\t\t}, this.#idleMs);\n\t\tthis.#idle.unref();\n\t}\n\n\t#exit(): void {\n\t\tif (this.#idle !== undefined) clearTimeout(this.#idle);\n\t\tthis.#idle = undefined;\n\t\tthis.#onExit();\n\t}\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,24 +1,24 @@
1
1
  export { defineDoc, defineDocFamily } from "./documents.ts";
2
2
  export { AssistantEntry, CompactionEntry, defineEntry, ResetEntry, SystemEntry, ToolResultEntry, UserEntry, } from "./entries.ts";
3
- export { ConversationBusy, ReadAfterWrite, StorageRejected } from "./errors.ts";
3
+ export { ConversationBusy, ReadAfterWrite, SessionFailed, StorageRequestError } from "./errors.ts";
4
4
  export { AgentDoc, configure, DEFAULT_COMPACTION_POLICY, DEFAULT_PROGRESS_POLICY, DEFAULT_RETRY_POLICY, } from "./harness/agent.ts";
5
5
  export { type CompactionCheckpoint, type CompactionInput, CompactionTask, type SummaryRequest, } from "./harness/compaction.ts";
6
6
  export { defineExtension, defineTool, hook, section, wrapSection, wrapTool } from "./harness/define.ts";
7
- export { type AgentEvent, type AgentEventStream, type MessageChange, type SnapshotEvent, watchEvents, } from "./harness/events.ts";
7
+ export { type AgentEvent, type AgentEventStream, type MessageChange, type SnapshotEvent, type ToolEventCall, watchEvents, } from "./harness/events.ts";
8
8
  export { type GenerationCheckpoint, type GenerationInput, type GenerationResult, GenerationTask, } from "./harness/generation.ts";
9
9
  export { Harness } from "./harness/harness.ts";
10
10
  export { InboxDoc, type InboxItem, type InboxState } from "./harness/inbox.ts";
11
- export { type CompactionStatus, LiveDoc, type LiveState, type ToolSlot } from "./harness/live.ts";
11
+ export { type CompactionFailure, type CompactionStatus, LiveDoc, type LiveState, type NestedToolSlot, type NestedToolSummary, type ToolSlot, } from "./harness/live.ts";
12
12
  export { ProviderDoc, type ProviderState } from "./harness/provider.ts";
13
13
  export { createRegistry } from "./harness/registry.ts";
14
14
  export type { TaskGraph, TaskGraphNode, TaskGraphState, TaskGraphWatch } from "./harness/task-graph.ts";
15
- export { ToolTask, type ToolTaskCheckpoint, type ToolTaskInput, type ToolTaskResult } from "./harness/tool.ts";
16
- export type { Agent, AgentChange, AgentState, AnyTask, CompactionHooks, CompactionPolicy, CompactionReason, CompactionResult, ContextView, Conversation, ConversationAbortOptions, ConversationCreateOptions, ConversationHandle, ConversationInit, ConversationRetryPolicy, ConversationStreamOptions, ConversationWatch, EnvTarget, Extension, GenerationHooks, HarnessInspection, HarnessOptions, HarnessSettings, HookApi, HookRegistration, HookResult, HooksOf, InputSubmissionDraft, ModelRef, ProgressPolicy, PromptInput, PromptSection, QueueMode, Registry, RegistryReader, RegistrySnapshot, Settings, SettledSubmissionRecord, SettledTask, Submission, SubmissionDraft, TaskInspection, ToolControl, ToolDiagnostic, ToolExecutionApi, ToolExecutionMode, ToolExecutionResult, ToolHooks, ToolRegistration, UserInput, Wrap, } from "./harness/types.ts";
15
+ export { NestedCallDoc, type NestedCallState, ToolTask, type ToolTaskCheckpoint, type ToolTaskInput, type ToolTaskResult, } from "./harness/tool.ts";
16
+ export type { Agent, AgentChange, AgentState, AnyTask, CompactionHooks, CompactionPolicy, CompactionReason, CompactionResult, ContextView, Conversation, ConversationAbortOptions, ConversationCreateOptions, ConversationHandle, ConversationInit, ConversationRetryPolicy, ConversationStreamOptions, ConversationWatch, EnvTarget, Extension, GenerationHooks, HarnessInspection, HarnessOptions, HarnessSettings, HookApi, HookRegistration, HookResult, HooksOf, InputEntry, InputSubmissionDraft, ModelRef, NestedToolExecutionResult, ProgressPolicy, PromptInput, PromptSection, QueueMode, Registry, RegistryReader, RegistrySnapshot, Settings, SettledSubmissionRecord, SettledTask, Submission, SubmissionDraft, TaskInspection, ToolControl, ToolDiagnostic, ToolExecutionApi, ToolExecutionMode, ToolExecutionResult, ToolHookCall, ToolHooks, ToolRegistration, UserInput, Wrap, } from "./harness/types.ts";
17
17
  export { UsageDoc, type UsageState } from "./harness/usage.ts";
18
18
  export type { ConversationView } from "./harness/view.ts";
19
19
  export { createSession } from "./session/session.ts";
20
20
  export { MemoryStorage } from "./storage/memory.ts";
21
21
  export { defineTask } from "./tasks.ts";
22
- export type { CheckpointInfo, CommitChange, CommitPublication, CommonDocDefinition, ContextEdit, ConversationDocFamilyToken, ConversationDocToken, ConversationId, ConversationOwnership, ConversationQuery, ConversationRecord, Cursor, DocDefinition, DocFamilyDefinition, DocFamilyToken, DocToken, DocumentAddress, DocumentCommitChange, DocumentContent, DocumentCopySource, DocumentCreate, DocumentId, DocumentObserver, DocumentPoint, DocumentQuery, DocumentReader, DocumentRecord, DocumentSemantics, DocumentState, DocumentWatch, Entry, EntryDraft, EntryId, EntryQuery, EntryRecord, HookRunner, Id, JoinPolicy, JsonObject, LatestConversationSemantics, NextTaskState, Page, PhaseHandler, RewindableConversationDocFamilyToken, RewindableConversationDocToken, RewindableConversationSemantics, RunningTask, Seq, Session, SessionDocFamilyToken, SessionDocToken, Storage, StorageWrite, StoredDocument, SubmissionCreate, SubmissionId, SubmissionQuery, SubmissionRecord, SubmissionSettlement, TableCommitChange, Task, TaskDefinition, TaskDocFamilyToken, TaskDocToken, TaskId, TaskOptions, TaskOutcome, TaskOutcomeError, TaskOwnership, TaskQuery, TaskRecord, TaskRuntime, TaskState, Tx, TypedEntry, TypedEntryDraft, WatchEnd, WatchHandle, } from "./types.ts";
22
+ export type { CheckpointInfo, CommitChange, CommitPublication, CommonDocDefinition, ContextEdit, ConversationDocFamilyToken, ConversationDocToken, ConversationId, ConversationOwnership, ConversationQuery, ConversationRecord, Cursor, DocDefinition, DocFamilyDefinition, DocFamilyToken, DocToken, DocumentAddress, DocumentCommitChange, DocumentContent, DocumentCopySource, DocumentCreate, DocumentId, DocumentObserver, DocumentPoint, DocumentQuery, DocumentReader, DocumentRecord, DocumentSemantics, DocumentState, DocumentWatch, Entry, EntryDraft, EntryId, EntryQuery, EntryRecord, HookRunner, Id, JoinPolicy, JsonObject, LatestConversationSemantics, NextTaskState, Page, PhaseHandler, RewindableConversationDocFamilyToken, RewindableConversationDocToken, RewindableConversationSemantics, RunningTask, ScanOrder, Seq, Session, SessionDocFamilyToken, SessionDocToken, SessionEnd, Storage, StorageWrite, StoredDocument, SubmissionCreate, SubmissionId, SubmissionQuery, SubmissionRecord, SubmissionSettlement, TableCommitChange, Task, TaskDefinition, TaskDocFamilyToken, TaskDocToken, TaskId, TaskOptions, TaskOutcome, TaskOutcomeError, TaskOwnership, TaskQuery, TaskRecord, TaskRuntime, TaskState, Tx, TypedEntry, TypedEntryDraft, WatchEnd, WatchHandle, } from "./types.ts";
23
23
  export { ROOT_CONVERSATION_ID } from "./types.ts";
24
24
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export { defineDoc, defineDocFamily } from "./documents.js";
2
2
  export { AssistantEntry, CompactionEntry, defineEntry, ResetEntry, SystemEntry, ToolResultEntry, UserEntry, } from "./entries.js";
3
- export { ConversationBusy, ReadAfterWrite, StorageRejected } from "./errors.js";
3
+ export { ConversationBusy, ReadAfterWrite, SessionFailed, StorageRequestError } from "./errors.js";
4
4
  export { AgentDoc, configure, DEFAULT_COMPACTION_POLICY, DEFAULT_PROGRESS_POLICY, DEFAULT_RETRY_POLICY, } from "./harness/agent.js";
5
5
  export { CompactionTask, } from "./harness/compaction.js";
6
6
  export { defineExtension, defineTool, hook, section, wrapSection, wrapTool } from "./harness/define.js";
@@ -8,10 +8,10 @@ export { watchEvents, } from "./harness/events.js";
8
8
  export { GenerationTask, } from "./harness/generation.js";
9
9
  export { Harness } from "./harness/harness.js";
10
10
  export { InboxDoc } from "./harness/inbox.js";
11
- export { LiveDoc } from "./harness/live.js";
11
+ export { LiveDoc, } from "./harness/live.js";
12
12
  export { ProviderDoc } from "./harness/provider.js";
13
13
  export { createRegistry } from "./harness/registry.js";
14
- export { ToolTask } from "./harness/tool.js";
14
+ export { NestedCallDoc, ToolTask, } from "./harness/tool.js";
15
15
  export { UsageDoc } from "./harness/usage.js";
16
16
  export { createSession } from "./session/session.js";
17
17
  export { MemoryStorage } from "./storage/memory.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EACN,cAAc,EACd,eAAe,EACf,WAAW,EACX,UAAU,EACV,WAAW,EACX,eAAe,EACf,SAAS,GACT,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAChF,OAAO,EACN,QAAQ,EACR,SAAS,EACT,yBAAyB,EACzB,uBAAuB,EACvB,oBAAoB,GACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAGN,cAAc,GAEd,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACxG,OAAO,EAKN,WAAW,GACX,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAIN,cAAc,GACd,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAmC,MAAM,oBAAoB,CAAC;AAC/E,OAAO,EAAyB,OAAO,EAAiC,MAAM,mBAAmB,CAAC;AAClG,OAAO,EAAE,WAAW,EAAsB,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAE,QAAQ,EAAoE,MAAM,mBAAmB,CAAC;AAsD/G,OAAO,EAAE,QAAQ,EAAmB,MAAM,oBAAoB,CAAC;AAE/D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAiFxC,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC","sourcesContent":["export { defineDoc, defineDocFamily } from \"./documents.ts\";\nexport {\n\tAssistantEntry,\n\tCompactionEntry,\n\tdefineEntry,\n\tResetEntry,\n\tSystemEntry,\n\tToolResultEntry,\n\tUserEntry,\n} from \"./entries.ts\";\nexport { ConversationBusy, ReadAfterWrite, StorageRejected } from \"./errors.ts\";\nexport {\n\tAgentDoc,\n\tconfigure,\n\tDEFAULT_COMPACTION_POLICY,\n\tDEFAULT_PROGRESS_POLICY,\n\tDEFAULT_RETRY_POLICY,\n} from \"./harness/agent.ts\";\nexport {\n\ttype CompactionCheckpoint,\n\ttype CompactionInput,\n\tCompactionTask,\n\ttype SummaryRequest,\n} from \"./harness/compaction.ts\";\nexport { defineExtension, defineTool, hook, section, wrapSection, wrapTool } from \"./harness/define.ts\";\nexport {\n\ttype AgentEvent,\n\ttype AgentEventStream,\n\ttype MessageChange,\n\ttype SnapshotEvent,\n\twatchEvents,\n} from \"./harness/events.ts\";\nexport {\n\ttype GenerationCheckpoint,\n\ttype GenerationInput,\n\ttype GenerationResult,\n\tGenerationTask,\n} from \"./harness/generation.ts\";\nexport { Harness } from \"./harness/harness.ts\";\nexport { InboxDoc, type InboxItem, type InboxState } from \"./harness/inbox.ts\";\nexport { type CompactionStatus, LiveDoc, type LiveState, type ToolSlot } from \"./harness/live.ts\";\nexport { ProviderDoc, type ProviderState } from \"./harness/provider.ts\";\nexport { createRegistry } from \"./harness/registry.ts\";\nexport type { TaskGraph, TaskGraphNode, TaskGraphState, TaskGraphWatch } from \"./harness/task-graph.ts\";\nexport { ToolTask, type ToolTaskCheckpoint, type ToolTaskInput, type ToolTaskResult } from \"./harness/tool.ts\";\nexport type {\n\tAgent,\n\tAgentChange,\n\tAgentState,\n\tAnyTask,\n\tCompactionHooks,\n\tCompactionPolicy,\n\tCompactionReason,\n\tCompactionResult,\n\tContextView,\n\tConversation,\n\tConversationAbortOptions,\n\tConversationCreateOptions,\n\tConversationHandle,\n\tConversationInit,\n\tConversationRetryPolicy,\n\tConversationStreamOptions,\n\tConversationWatch,\n\tEnvTarget,\n\tExtension,\n\tGenerationHooks,\n\tHarnessInspection,\n\tHarnessOptions,\n\tHarnessSettings,\n\tHookApi,\n\tHookRegistration,\n\tHookResult,\n\tHooksOf,\n\tInputSubmissionDraft,\n\tModelRef,\n\tProgressPolicy,\n\tPromptInput,\n\tPromptSection,\n\tQueueMode,\n\tRegistry,\n\tRegistryReader,\n\tRegistrySnapshot,\n\tSettings,\n\tSettledSubmissionRecord,\n\tSettledTask,\n\tSubmission,\n\tSubmissionDraft,\n\tTaskInspection,\n\tToolControl,\n\tToolDiagnostic,\n\tToolExecutionApi,\n\tToolExecutionMode,\n\tToolExecutionResult,\n\tToolHooks,\n\tToolRegistration,\n\tUserInput,\n\tWrap,\n} from \"./harness/types.ts\";\nexport { UsageDoc, type UsageState } from \"./harness/usage.ts\";\nexport type { ConversationView } from \"./harness/view.ts\";\nexport { createSession } from \"./session/session.ts\";\nexport { MemoryStorage } from \"./storage/memory.ts\";\nexport { defineTask } from \"./tasks.ts\";\nexport type {\n\tCheckpointInfo,\n\tCommitChange,\n\tCommitPublication,\n\tCommonDocDefinition,\n\tContextEdit,\n\tConversationDocFamilyToken,\n\tConversationDocToken,\n\tConversationId,\n\tConversationOwnership,\n\tConversationQuery,\n\tConversationRecord,\n\tCursor,\n\tDocDefinition,\n\tDocFamilyDefinition,\n\tDocFamilyToken,\n\tDocToken,\n\tDocumentAddress,\n\tDocumentCommitChange,\n\tDocumentContent,\n\tDocumentCopySource,\n\tDocumentCreate,\n\tDocumentId,\n\tDocumentObserver,\n\tDocumentPoint,\n\tDocumentQuery,\n\tDocumentReader,\n\tDocumentRecord,\n\tDocumentSemantics,\n\tDocumentState,\n\tDocumentWatch,\n\tEntry,\n\tEntryDraft,\n\tEntryId,\n\tEntryQuery,\n\tEntryRecord,\n\tHookRunner,\n\tId,\n\tJoinPolicy,\n\tJsonObject,\n\tLatestConversationSemantics,\n\tNextTaskState,\n\tPage,\n\tPhaseHandler,\n\tRewindableConversationDocFamilyToken,\n\tRewindableConversationDocToken,\n\tRewindableConversationSemantics,\n\tRunningTask,\n\tSeq,\n\tSession,\n\tSessionDocFamilyToken,\n\tSessionDocToken,\n\tStorage,\n\tStorageWrite,\n\tStoredDocument,\n\tSubmissionCreate,\n\tSubmissionId,\n\tSubmissionQuery,\n\tSubmissionRecord,\n\tSubmissionSettlement,\n\tTableCommitChange,\n\tTask,\n\tTaskDefinition,\n\tTaskDocFamilyToken,\n\tTaskDocToken,\n\tTaskId,\n\tTaskOptions,\n\tTaskOutcome,\n\tTaskOutcomeError,\n\tTaskOwnership,\n\tTaskQuery,\n\tTaskRecord,\n\tTaskRuntime,\n\tTaskState,\n\tTx,\n\tTypedEntry,\n\tTypedEntryDraft,\n\tWatchEnd,\n\tWatchHandle,\n} from \"./types.ts\";\nexport { ROOT_CONVERSATION_ID } from \"./types.ts\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EACN,cAAc,EACd,eAAe,EACf,WAAW,EACX,UAAU,EACV,WAAW,EACX,eAAe,EACf,SAAS,GACT,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACnG,OAAO,EACN,QAAQ,EACR,SAAS,EACT,yBAAyB,EACzB,uBAAuB,EACvB,oBAAoB,GACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAGN,cAAc,GAEd,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACxG,OAAO,EAMN,WAAW,GACX,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAIN,cAAc,GACd,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAmC,MAAM,oBAAoB,CAAC;AAC/E,OAAO,EAGN,OAAO,GAKP,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAsB,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EACN,aAAa,EAEb,QAAQ,GAIR,MAAM,mBAAmB,CAAC;AAyD3B,OAAO,EAAE,QAAQ,EAAmB,MAAM,oBAAoB,CAAC;AAE/D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAmFxC,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC","sourcesContent":["export { defineDoc, defineDocFamily } from \"./documents.ts\";\nexport {\n\tAssistantEntry,\n\tCompactionEntry,\n\tdefineEntry,\n\tResetEntry,\n\tSystemEntry,\n\tToolResultEntry,\n\tUserEntry,\n} from \"./entries.ts\";\nexport { ConversationBusy, ReadAfterWrite, SessionFailed, StorageRequestError } from \"./errors.ts\";\nexport {\n\tAgentDoc,\n\tconfigure,\n\tDEFAULT_COMPACTION_POLICY,\n\tDEFAULT_PROGRESS_POLICY,\n\tDEFAULT_RETRY_POLICY,\n} from \"./harness/agent.ts\";\nexport {\n\ttype CompactionCheckpoint,\n\ttype CompactionInput,\n\tCompactionTask,\n\ttype SummaryRequest,\n} from \"./harness/compaction.ts\";\nexport { defineExtension, defineTool, hook, section, wrapSection, wrapTool } from \"./harness/define.ts\";\nexport {\n\ttype AgentEvent,\n\ttype AgentEventStream,\n\ttype MessageChange,\n\ttype SnapshotEvent,\n\ttype ToolEventCall,\n\twatchEvents,\n} from \"./harness/events.ts\";\nexport {\n\ttype GenerationCheckpoint,\n\ttype GenerationInput,\n\ttype GenerationResult,\n\tGenerationTask,\n} from \"./harness/generation.ts\";\nexport { Harness } from \"./harness/harness.ts\";\nexport { InboxDoc, type InboxItem, type InboxState } from \"./harness/inbox.ts\";\nexport {\n\ttype CompactionFailure,\n\ttype CompactionStatus,\n\tLiveDoc,\n\ttype LiveState,\n\ttype NestedToolSlot,\n\ttype NestedToolSummary,\n\ttype ToolSlot,\n} from \"./harness/live.ts\";\nexport { ProviderDoc, type ProviderState } from \"./harness/provider.ts\";\nexport { createRegistry } from \"./harness/registry.ts\";\nexport type { TaskGraph, TaskGraphNode, TaskGraphState, TaskGraphWatch } from \"./harness/task-graph.ts\";\nexport {\n\tNestedCallDoc,\n\ttype NestedCallState,\n\tToolTask,\n\ttype ToolTaskCheckpoint,\n\ttype ToolTaskInput,\n\ttype ToolTaskResult,\n} from \"./harness/tool.ts\";\nexport type {\n\tAgent,\n\tAgentChange,\n\tAgentState,\n\tAnyTask,\n\tCompactionHooks,\n\tCompactionPolicy,\n\tCompactionReason,\n\tCompactionResult,\n\tContextView,\n\tConversation,\n\tConversationAbortOptions,\n\tConversationCreateOptions,\n\tConversationHandle,\n\tConversationInit,\n\tConversationRetryPolicy,\n\tConversationStreamOptions,\n\tConversationWatch,\n\tEnvTarget,\n\tExtension,\n\tGenerationHooks,\n\tHarnessInspection,\n\tHarnessOptions,\n\tHarnessSettings,\n\tHookApi,\n\tHookRegistration,\n\tHookResult,\n\tHooksOf,\n\tInputEntry,\n\tInputSubmissionDraft,\n\tModelRef,\n\tNestedToolExecutionResult,\n\tProgressPolicy,\n\tPromptInput,\n\tPromptSection,\n\tQueueMode,\n\tRegistry,\n\tRegistryReader,\n\tRegistrySnapshot,\n\tSettings,\n\tSettledSubmissionRecord,\n\tSettledTask,\n\tSubmission,\n\tSubmissionDraft,\n\tTaskInspection,\n\tToolControl,\n\tToolDiagnostic,\n\tToolExecutionApi,\n\tToolExecutionMode,\n\tToolExecutionResult,\n\tToolHookCall,\n\tToolHooks,\n\tToolRegistration,\n\tUserInput,\n\tWrap,\n} from \"./harness/types.ts\";\nexport { UsageDoc, type UsageState } from \"./harness/usage.ts\";\nexport type { ConversationView } from \"./harness/view.ts\";\nexport { createSession } from \"./session/session.ts\";\nexport { MemoryStorage } from \"./storage/memory.ts\";\nexport { defineTask } from \"./tasks.ts\";\nexport type {\n\tCheckpointInfo,\n\tCommitChange,\n\tCommitPublication,\n\tCommonDocDefinition,\n\tContextEdit,\n\tConversationDocFamilyToken,\n\tConversationDocToken,\n\tConversationId,\n\tConversationOwnership,\n\tConversationQuery,\n\tConversationRecord,\n\tCursor,\n\tDocDefinition,\n\tDocFamilyDefinition,\n\tDocFamilyToken,\n\tDocToken,\n\tDocumentAddress,\n\tDocumentCommitChange,\n\tDocumentContent,\n\tDocumentCopySource,\n\tDocumentCreate,\n\tDocumentId,\n\tDocumentObserver,\n\tDocumentPoint,\n\tDocumentQuery,\n\tDocumentReader,\n\tDocumentRecord,\n\tDocumentSemantics,\n\tDocumentState,\n\tDocumentWatch,\n\tEntry,\n\tEntryDraft,\n\tEntryId,\n\tEntryQuery,\n\tEntryRecord,\n\tHookRunner,\n\tId,\n\tJoinPolicy,\n\tJsonObject,\n\tLatestConversationSemantics,\n\tNextTaskState,\n\tPage,\n\tPhaseHandler,\n\tRewindableConversationDocFamilyToken,\n\tRewindableConversationDocToken,\n\tRewindableConversationSemantics,\n\tRunningTask,\n\tScanOrder,\n\tSeq,\n\tSession,\n\tSessionDocFamilyToken,\n\tSessionDocToken,\n\tSessionEnd,\n\tStorage,\n\tStorageWrite,\n\tStoredDocument,\n\tSubmissionCreate,\n\tSubmissionId,\n\tSubmissionQuery,\n\tSubmissionRecord,\n\tSubmissionSettlement,\n\tTableCommitChange,\n\tTask,\n\tTaskDefinition,\n\tTaskDocFamilyToken,\n\tTaskDocToken,\n\tTaskId,\n\tTaskOptions,\n\tTaskOutcome,\n\tTaskOutcomeError,\n\tTaskOwnership,\n\tTaskQuery,\n\tTaskRecord,\n\tTaskRuntime,\n\tTaskState,\n\tTx,\n\tTypedEntry,\n\tTypedEntryDraft,\n\tWatchEnd,\n\tWatchHandle,\n} from \"./types.ts\";\nexport { ROOT_CONVERSATION_ID } from \"./types.ts\";\n"]}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * BM25 tool search for code mode's `searchTools()` and the `tool_search` tool, a copy of the coding agent's tool search
3
+ * ranking: durable keeps its own copy of what it needs from the coding agent.
4
+ */
5
+ export type SearchDocument = {
6
+ readonly name: string;
7
+ readonly text: string;
8
+ };
9
+ /** Lowercase terms, split at camelCase boundaries and non-alphanumerics, without stop words. */
10
+ export declare function tokenize(text: string): string[];
11
+ /** Okapi BM25 (k1 1.2, b 0.75): the names of the best matches, best first; ties keep document order. */
12
+ export declare function rankDocuments(query: string, documents: readonly SearchDocument[], limit: number): string[];
13
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,cAAc,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAkC9E,gGAAgG;AAChG,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ/C;AAED,wGAAwG;AACxG,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,cAAc,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAiC1G"}