@far-world-labs/verblets 0.1.7 → 0.3.2

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 (306) hide show
  1. package/README.md +86 -213
  2. package/dist/index.browser.js +74 -0
  3. package/dist/index.js +548 -0
  4. package/dist/shared-C6kPWghF.js +7806 -0
  5. package/package.json +32 -8
  6. package/.cursor/launch.json +0 -30
  7. package/.cursor/settings.json +0 -20
  8. package/.github/workflows/branch-protection.yml +0 -22
  9. package/.github/workflows/ci.yml +0 -165
  10. package/.husky/pre-commit +0 -4
  11. package/.prettierrc +0 -6
  12. package/.release-it.json +0 -12
  13. package/.vitest.config.examples.js +0 -8
  14. package/.vitest.config.js +0 -8
  15. package/.vscode/launch.json +0 -31
  16. package/AGENTS.md +0 -220
  17. package/DEVELOPING.md +0 -105
  18. package/docker-compose.yml +0 -7
  19. package/eslint.config.js +0 -80
  20. package/scripts/generate-chain/index.js +0 -111
  21. package/scripts/generate-lib/index.js +0 -68
  22. package/scripts/generate-test/index.js +0 -137
  23. package/scripts/generate-verblet/README.md +0 -17
  24. package/scripts/generate-verblet/index.js +0 -110
  25. package/scripts/run.sh +0 -15
  26. package/scripts/runner/index.js +0 -56
  27. package/scripts/simple-editor/README.md +0 -34
  28. package/scripts/simple-editor/index.js +0 -79
  29. package/scripts/summarize-files/index.js +0 -70
  30. package/src/chains/README.md +0 -30
  31. package/src/chains/anonymize/README.md +0 -21
  32. package/src/chains/anonymize/index.examples.js +0 -75
  33. package/src/chains/anonymize/index.js +0 -121
  34. package/src/chains/anonymize/index.spec.js +0 -78
  35. package/src/chains/bulk-central-tendency/index.examples.js +0 -138
  36. package/src/chains/bulk-central-tendency/index.js +0 -91
  37. package/src/chains/bulk-filter/README.md +0 -21
  38. package/src/chains/bulk-filter/index.examples.js +0 -22
  39. package/src/chains/bulk-filter/index.js +0 -58
  40. package/src/chains/bulk-filter/index.spec.js +0 -38
  41. package/src/chains/bulk-find/README.md +0 -16
  42. package/src/chains/bulk-find/index.examples.js +0 -20
  43. package/src/chains/bulk-find/index.js +0 -30
  44. package/src/chains/bulk-find/index.spec.js +0 -26
  45. package/src/chains/bulk-group/README.md +0 -23
  46. package/src/chains/bulk-group/index.examples.js +0 -18
  47. package/src/chains/bulk-group/index.js +0 -34
  48. package/src/chains/bulk-group/index.spec.js +0 -41
  49. package/src/chains/bulk-map/README.md +0 -43
  50. package/src/chains/bulk-map/index.examples.js +0 -17
  51. package/src/chains/bulk-map/index.js +0 -86
  52. package/src/chains/bulk-map/index.spec.js +0 -44
  53. package/src/chains/bulk-reduce/README.md +0 -12
  54. package/src/chains/bulk-reduce/index.examples.js +0 -15
  55. package/src/chains/bulk-reduce/index.js +0 -13
  56. package/src/chains/bulk-reduce/index.spec.js +0 -25
  57. package/src/chains/bulk-score/README.md +0 -16
  58. package/src/chains/bulk-score/bulk-score-result.json +0 -18
  59. package/src/chains/bulk-score/index.examples.js +0 -22
  60. package/src/chains/bulk-score/index.js +0 -133
  61. package/src/chains/bulk-score/index.spec.js +0 -30
  62. package/src/chains/category-samples/README.md +0 -61
  63. package/src/chains/category-samples/index.examples.js +0 -103
  64. package/src/chains/category-samples/index.js +0 -134
  65. package/src/chains/collect-terms/README.md +0 -12
  66. package/src/chains/collect-terms/index.examples.js +0 -16
  67. package/src/chains/collect-terms/index.js +0 -44
  68. package/src/chains/collect-terms/index.spec.js +0 -25
  69. package/src/chains/date/README.md +0 -12
  70. package/src/chains/date/index.examples.js +0 -47
  71. package/src/chains/date/index.js +0 -74
  72. package/src/chains/date/index.spec.js +0 -62
  73. package/src/chains/disambiguate/README.md +0 -22
  74. package/src/chains/disambiguate/disambiguate-meanings-result.json +0 -16
  75. package/src/chains/disambiguate/index.examples.js +0 -18
  76. package/src/chains/disambiguate/index.js +0 -92
  77. package/src/chains/disambiguate/index.spec.js +0 -25
  78. package/src/chains/dismantle/README.md +0 -67
  79. package/src/chains/dismantle/dismantle.examples.js +0 -27
  80. package/src/chains/dismantle/index.examples.js +0 -30
  81. package/src/chains/dismantle/index.js +0 -303
  82. package/src/chains/dismantle/index.spec.js +0 -32
  83. package/src/chains/expect/README.md +0 -171
  84. package/src/chains/expect/index.examples.js +0 -146
  85. package/src/chains/expect/index.js +0 -173
  86. package/src/chains/expect/index.spec.js +0 -324
  87. package/src/chains/filter-ambiguous/README.md +0 -11
  88. package/src/chains/filter-ambiguous/index.examples.js +0 -20
  89. package/src/chains/filter-ambiguous/index.js +0 -49
  90. package/src/chains/filter-ambiguous/index.spec.js +0 -31
  91. package/src/chains/glossary/README.md +0 -19
  92. package/src/chains/glossary/index.examples.js +0 -386
  93. package/src/chains/glossary/index.js +0 -75
  94. package/src/chains/glossary/index.spec.js +0 -19
  95. package/src/chains/intersections/README.md +0 -152
  96. package/src/chains/intersections/index.examples.js +0 -279
  97. package/src/chains/intersections/index.js +0 -366
  98. package/src/chains/intersections/intersection-result.json +0 -38
  99. package/src/chains/list/index.examples.js +0 -68
  100. package/src/chains/list/index.js +0 -214
  101. package/src/chains/list/index.spec.js +0 -67
  102. package/src/chains/list/list-result.json +0 -16
  103. package/src/chains/list/schema.json +0 -24
  104. package/src/chains/llm-logger/README.md +0 -208
  105. package/src/chains/llm-logger/index.js +0 -205
  106. package/src/chains/llm-logger/index.spec.js +0 -330
  107. package/src/chains/questions/index.examples.js +0 -69
  108. package/src/chains/questions/index.js +0 -135
  109. package/src/chains/questions/index.spec.js +0 -29
  110. package/src/chains/scan-js/index.js +0 -116
  111. package/src/chains/set-interval/README.md +0 -81
  112. package/src/chains/set-interval/index.examples.js +0 -36
  113. package/src/chains/set-interval/index.js +0 -131
  114. package/src/chains/set-interval/index.spec.js +0 -70
  115. package/src/chains/socratic/README.md +0 -17
  116. package/src/chains/socratic/index.js +0 -64
  117. package/src/chains/socratic/index.spec.js +0 -24
  118. package/src/chains/sort/index.examples.js +0 -36
  119. package/src/chains/sort/index.js +0 -163
  120. package/src/chains/sort/index.spec.js +0 -112
  121. package/src/chains/sort/sort-result.json +0 -16
  122. package/src/chains/summary-map/README.md +0 -41
  123. package/src/chains/summary-map/index.examples.js +0 -64
  124. package/src/chains/summary-map/index.js +0 -226
  125. package/src/chains/summary-map/index.spec.js +0 -153
  126. package/src/chains/test/index.js +0 -114
  127. package/src/chains/test-advice/index.js +0 -35
  128. package/src/chains/themes/README.md +0 -20
  129. package/src/chains/themes/index.examples.js +0 -17
  130. package/src/chains/themes/index.js +0 -28
  131. package/src/chains/themes/index.spec.js +0 -19
  132. package/src/chains/veiled-variants/index.examples.js +0 -18
  133. package/src/chains/veiled-variants/index.js +0 -107
  134. package/src/chains/veiled-variants/index.spec.js +0 -40
  135. package/src/constants/common.js +0 -7
  136. package/src/constants/messages.js +0 -3
  137. package/src/constants/models.js +0 -183
  138. package/src/index.js +0 -193
  139. package/src/json-schemas/README.md +0 -13
  140. package/src/json-schemas/cars-test.json +0 -11
  141. package/src/json-schemas/index.js +0 -12
  142. package/src/json-schemas/intent.json +0 -38
  143. package/src/json-schemas/schema-dot-org-photograph.json +0 -133
  144. package/src/json-schemas/schema-dot-org-place.json +0 -129
  145. package/src/lib/README.md +0 -26
  146. package/src/lib/any-signal/index.js +0 -28
  147. package/src/lib/bulk-filter/README.md +0 -22
  148. package/src/lib/bulk-filter/index.examples.js +0 -27
  149. package/src/lib/bulk-filter/index.js +0 -63
  150. package/src/lib/bulk-filter/index.spec.js +0 -38
  151. package/src/lib/bulk-find/README.md +0 -18
  152. package/src/lib/bulk-find/index.examples.js +0 -19
  153. package/src/lib/bulk-find/index.js +0 -30
  154. package/src/lib/bulk-find/index.spec.js +0 -41
  155. package/src/lib/chatgpt/index.js +0 -163
  156. package/src/lib/combinations/index.js +0 -30
  157. package/src/lib/combinations/index.spec.js +0 -23
  158. package/src/lib/editor/index.js +0 -31
  159. package/src/lib/functional/index.js +0 -28
  160. package/src/lib/logger-service/index.js +0 -32
  161. package/src/lib/parse-js-parts/index.js +0 -321
  162. package/src/lib/parse-js-parts/index.spec.js +0 -156
  163. package/src/lib/parse-llm-list/README.md +0 -39
  164. package/src/lib/parse-llm-list/index.js +0 -54
  165. package/src/lib/parse-llm-list/index.spec.js +0 -59
  166. package/src/lib/path-aliases/index.js +0 -37
  167. package/src/lib/path-aliases/index.spec.js +0 -64
  168. package/src/lib/pave/index.js +0 -34
  169. package/src/lib/pave/index.spec.js +0 -76
  170. package/src/lib/prompt-cache/index.js +0 -50
  171. package/src/lib/retry/index.js +0 -66
  172. package/src/lib/retry/index.spec.js +0 -86
  173. package/src/lib/ring-buffer/README.md +0 -460
  174. package/src/lib/ring-buffer/index.js +0 -1074
  175. package/src/lib/search-best-first/city-walk.spec.js +0 -37
  176. package/src/lib/search-best-first/index.js +0 -97
  177. package/src/lib/search-best-first/index.spec.js +0 -35
  178. package/src/lib/search-js-files/code-features-property-definitions.json +0 -123
  179. package/src/lib/search-js-files/index.examples.js +0 -22
  180. package/src/lib/search-js-files/index.js +0 -155
  181. package/src/lib/search-js-files/index.spec.js +0 -34
  182. package/src/lib/search-js-files/scan-file.js +0 -242
  183. package/src/lib/shorten-text/index.js +0 -25
  184. package/src/lib/shorten-text/index.spec.js +0 -68
  185. package/src/lib/strip-numeric/index.js +0 -5
  186. package/src/lib/strip-response/index.js +0 -30
  187. package/src/lib/template-replace/index.js +0 -23
  188. package/src/lib/template-replace/index.spec.js +0 -60
  189. package/src/lib/timed-abort-controller/index.js +0 -41
  190. package/src/lib/to-bool/index.js +0 -8
  191. package/src/lib/to-date/index.js +0 -11
  192. package/src/lib/to-enum/index.js +0 -14
  193. package/src/lib/to-number/index.js +0 -12
  194. package/src/lib/to-number-with-units/index.js +0 -51
  195. package/src/lib/transcribe/index.js +0 -78
  196. package/src/prompts/README.md +0 -17
  197. package/src/prompts/as-enum.js +0 -5
  198. package/src/prompts/as-json-schema.js +0 -9
  199. package/src/prompts/as-object-with-schema.js +0 -26
  200. package/src/prompts/as-schema-org-text.js +0 -25
  201. package/src/prompts/as-schema-org-type.js +0 -1
  202. package/src/prompts/blog-post.js +0 -7
  203. package/src/prompts/code-features.js +0 -24
  204. package/src/prompts/constants.js +0 -101
  205. package/src/prompts/features-json-schema.js +0 -27
  206. package/src/prompts/generate-collection.js +0 -26
  207. package/src/prompts/generate-list.js +0 -48
  208. package/src/prompts/generate-questions.js +0 -19
  209. package/src/prompts/index.js +0 -20
  210. package/src/prompts/intent.js +0 -60
  211. package/src/prompts/output-succinct-names.js +0 -3
  212. package/src/prompts/select-from-threshold.js +0 -17
  213. package/src/prompts/sort.js +0 -31
  214. package/src/prompts/style.js +0 -38
  215. package/src/prompts/summarize.js +0 -13
  216. package/src/prompts/token-budget.js +0 -3
  217. package/src/prompts/wrap-list.js +0 -11
  218. package/src/prompts/wrap-variable.js +0 -36
  219. package/src/services/llm-model/global-overrides.spec.js +0 -432
  220. package/src/services/llm-model/index.js +0 -308
  221. package/src/services/llm-model/model.js +0 -21
  222. package/src/services/llm-model/negotiate.spec.js +0 -447
  223. package/src/services/redis/index.js +0 -147
  224. package/src/test/setup.js +0 -20
  225. package/src/verblets/README.md +0 -26
  226. package/src/verblets/auto/index.examples.js +0 -31
  227. package/src/verblets/auto/index.js +0 -28
  228. package/src/verblets/auto/index.spec.js +0 -32
  229. package/src/verblets/bool/README.md +0 -36
  230. package/src/verblets/bool/index.examples.js +0 -80
  231. package/src/verblets/bool/index.js +0 -25
  232. package/src/verblets/bool/index.schema.json +0 -14
  233. package/src/verblets/bool/index.spec.js +0 -33
  234. package/src/verblets/central-tendency/README.md +0 -166
  235. package/src/verblets/central-tendency/central-tendency-result.json +0 -24
  236. package/src/verblets/central-tendency/index.examples.js +0 -196
  237. package/src/verblets/central-tendency/index.js +0 -171
  238. package/src/verblets/central-tendency/index.spec.js +0 -148
  239. package/src/verblets/enum/index.examples.js +0 -30
  240. package/src/verblets/enum/index.js +0 -18
  241. package/src/verblets/enum/index.spec.js +0 -35
  242. package/src/verblets/expect/README.md +0 -64
  243. package/src/verblets/expect/index.examples.js +0 -109
  244. package/src/verblets/expect/index.js +0 -75
  245. package/src/verblets/expect/index.spec.js +0 -127
  246. package/src/verblets/intent/index.examples.js +0 -139
  247. package/src/verblets/intent/index.js +0 -60
  248. package/src/verblets/intent/index.spec.js +0 -31
  249. package/src/verblets/intersection/README.md +0 -16
  250. package/src/verblets/intersection/index.examples.js +0 -89
  251. package/src/verblets/intersection/index.js +0 -84
  252. package/src/verblets/intersection/index.spec.js +0 -60
  253. package/src/verblets/intersection/intersection-result.json +0 -16
  254. package/src/verblets/list-expand/README.md +0 -10
  255. package/src/verblets/list-expand/index.examples.js +0 -14
  256. package/src/verblets/list-expand/index.js +0 -104
  257. package/src/verblets/list-expand/index.spec.js +0 -18
  258. package/src/verblets/list-expand/list-expand-result.json +0 -16
  259. package/src/verblets/list-filter/README.md +0 -22
  260. package/src/verblets/list-filter/index.examples.js +0 -26
  261. package/src/verblets/list-filter/index.js +0 -18
  262. package/src/verblets/list-filter/index.spec.js +0 -19
  263. package/src/verblets/list-find/README.md +0 -11
  264. package/src/verblets/list-find/index.examples.js +0 -15
  265. package/src/verblets/list-find/index.js +0 -17
  266. package/src/verblets/list-find/index.spec.js +0 -19
  267. package/src/verblets/list-group/README.md +0 -16
  268. package/src/verblets/list-group/index.examples.js +0 -16
  269. package/src/verblets/list-group/index.js +0 -112
  270. package/src/verblets/list-group/index.spec.js +0 -35
  271. package/src/verblets/list-group/list-group-result.json +0 -16
  272. package/src/verblets/list-map/README.md +0 -11
  273. package/src/verblets/list-map/index.examples.js +0 -15
  274. package/src/verblets/list-map/index.js +0 -26
  275. package/src/verblets/list-map/index.spec.js +0 -17
  276. package/src/verblets/list-reduce/README.md +0 -10
  277. package/src/verblets/list-reduce/index.examples.js +0 -14
  278. package/src/verblets/list-reduce/index.js +0 -21
  279. package/src/verblets/list-reduce/index.spec.js +0 -27
  280. package/src/verblets/list-reduce/index.spec.jsx +0 -27
  281. package/src/verblets/name/README.md +0 -15
  282. package/src/verblets/name/index.examples.js +0 -28
  283. package/src/verblets/name/index.js +0 -19
  284. package/src/verblets/name/index.spec.js +0 -33
  285. package/src/verblets/name-similar-to/README.md +0 -26
  286. package/src/verblets/name-similar-to/index.examples.js +0 -18
  287. package/src/verblets/name-similar-to/index.js +0 -20
  288. package/src/verblets/name-similar-to/index.spec.js +0 -13
  289. package/src/verblets/number/index.examples.js +0 -199
  290. package/src/verblets/number/index.js +0 -25
  291. package/src/verblets/number/index.spec.js +0 -33
  292. package/src/verblets/number-with-units/index.examples.js +0 -38
  293. package/src/verblets/number-with-units/index.js +0 -84
  294. package/src/verblets/number-with-units/index.spec.js +0 -46
  295. package/src/verblets/number-with-units/number-with-units-result.json +0 -23
  296. package/src/verblets/schema-org/index.examples.js +0 -51
  297. package/src/verblets/schema-org/index.js +0 -37
  298. package/src/verblets/schema-org/index.spec.js +0 -39
  299. package/src/verblets/sentiment/README.md +0 -10
  300. package/src/verblets/sentiment/index.examples.js +0 -20
  301. package/src/verblets/sentiment/index.js +0 -9
  302. package/src/verblets/sentiment/index.spec.js +0 -20
  303. package/src/verblets/to-object/README.md +0 -38
  304. package/src/verblets/to-object/index.examples.js +0 -29
  305. package/src/verblets/to-object/index.js +0 -131
  306. package/src/verblets/to-object/index.spec.js +0 -71
@@ -1,460 +0,0 @@
1
- # Ring Buffer
2
-
3
- A memory-efficient circular buffer designed for high-throughput logging, batch processing, and LLM operations. Automatically evicts oldest entries when full, making it ideal for streaming data scenarios where memory efficiency is critical.
4
-
5
- ## Features
6
-
7
- - **Automatic Memory Management**: Configurable size limits with automatic eviction of oldest entries
8
- - **Multiple Cursor Support**: Track multiple processing positions concurrently
9
- - **Batch Operations**: Optimized for LLM workflows with parallel and sequential processing
10
- - **Flexible Access Patterns**: ID-based, index-based, and time-based slicing
11
- - **Rich Query Interface**: Filter, find, map, and reduce operations
12
- - **Iterator Support**: Works with for...of loops and spread operator
13
- - **Statistics Tracking**: Monitor buffer usage and performance metrics
14
-
15
- ## Basic Usage
16
-
17
- ```javascript
18
- import RingBuffer from '../lib/ring-buffer/index.js';
19
-
20
- // Create buffer with capacity of 1000 entries
21
- const buffer = new RingBuffer(1000);
22
-
23
- // Add entries
24
- const entry1 = buffer.push('Hello world');
25
- const entry2 = buffer.push({ user: 'alice', action: 'login' });
26
-
27
- // Get all entries
28
- const allEntries = buffer.all();
29
- console.log(`Buffer contains ${allEntries.length} entries`);
30
-
31
- // Add metadata
32
- const meta = new Map([['source', 'api'], ['priority', 'high']]);
33
- buffer.push('Important message', meta);
34
- ```
35
-
36
- ## Batch Operations
37
-
38
- Perfect for processing large datasets in manageable chunks:
39
-
40
- ```javascript
41
- // Add multiple entries at once
42
- const logData = ['error 1', 'error 2', 'error 3'];
43
- const entries = buffer.pushBatch(logData);
44
-
45
- // Process in batches
46
- await buffer.processBatches(50, async (batch, batchIndex) => {
47
- console.log(`Processing batch ${batchIndex} with ${batch.length} entries`);
48
-
49
- // Your processing logic here
50
- const results = await processLogBatch(batch);
51
- return results;
52
- });
53
-
54
- // Parallel processing for better performance
55
- await buffer.processBatches(25, processBatch, { parallel: true });
56
- ```
57
-
58
- ## Cursor Operations
59
-
60
- Track multiple processing positions for concurrent operations:
61
-
62
- ```javascript
63
- // Create cursors for different processors
64
- buffer.setCursor('error-processor', 0);
65
- buffer.setCursor('audit-processor', 0);
66
- buffer.setCursor('analytics-processor', 0);
67
-
68
- // Process new entries since last cursor position
69
- const newErrors = buffer.getSinceCursor('error-processor');
70
- console.log(`Found ${newErrors.length} new entries to process`);
71
-
72
- // Cursor automatically moves to latest processed position
73
- // Or control cursor movement manually
74
- const entries = buffer.getSinceCursor('audit-processor', false); // Don't move cursor
75
- ```
76
-
77
- ## Flexible Querying
78
-
79
- Rich query interface for finding and analyzing data:
80
-
81
- ```javascript
82
- // Find entries matching criteria
83
- const errors = buffer.filter(entry =>
84
- typeof entry.data === 'string' && entry.data.includes('ERROR')
85
- );
86
-
87
- // Find first match
88
- const criticalError = buffer.find(entry =>
89
- entry.meta.get('priority') === 'critical'
90
- );
91
-
92
- // Transform data
93
- const timestamps = buffer.map(entry => entry.timestamp);
94
-
95
- // Aggregate data
96
- const totalSize = buffer.reduce((sum, entry) =>
97
- sum + JSON.stringify(entry.data).length, 0
98
- );
99
- ```
100
-
101
- ## Slicing Operations
102
-
103
- Access data using different strategies:
104
-
105
- ```javascript
106
- // Get entries by ID range
107
- const recentEntries = buffer.slice(1000, 1100);
108
-
109
- // Get entries by index (like Array.slice)
110
- const firstTen = buffer.sliceByIndex(0, 10);
111
- const lastTen = buffer.tail(10);
112
-
113
- // Get entries by time range
114
- const lastHour = new Date(Date.now() - 3600000);
115
- const recentLogs = buffer.sliceByTime(lastHour);
116
- ```
117
-
118
- ## Memory Management
119
-
120
- Automatic memory management with detailed statistics:
121
-
122
- ```javascript
123
- // Check buffer status
124
- console.log(`Buffer is ${buffer.isFull() ? 'full' : 'not full'}`);
125
- console.log(`Current size: ${buffer.size()}/${buffer.capacity()}`);
126
-
127
- // Get detailed statistics
128
- const stats = buffer.getStats();
129
- console.log(`Total added: ${stats.totalAdded}`);
130
- console.log(`Total evicted: ${stats.totalEvicted}`);
131
- console.log(`Active cursors: ${stats.cursors}`);
132
-
133
- // Clear buffer when needed
134
- buffer.clear(); // Removes all entries and cursors
135
- buffer.clear(true); // Keeps cursors, removes entries
136
- ```
137
-
138
- ## LLM Chain Integration
139
-
140
- Designed specifically for LLM workflows:
141
-
142
- ```javascript
143
- // Log processing pipeline
144
- const logBuffer = new RingBuffer(5000);
145
-
146
- // Add logs from various sources
147
- logBuffer.push('User query: "What is the weather?"');
148
- logBuffer.push({ type: 'llm-request', model: 'gpt-4', tokens: 150 });
149
- logBuffer.push('LLM response: "The weather is sunny..."');
150
-
151
- // Process logs in batches for LLM analysis
152
- await logBuffer.processBatches(100, async (batch) => {
153
- // Send batch to LLM for analysis
154
- const analysis = await analyzeLogs(batch);
155
- return analysis;
156
- });
157
-
158
- // Track different processing stages
159
- logBuffer.setCursor('preprocessing', 0);
160
- logBuffer.setCursor('llm-analysis', 0);
161
- logBuffer.setCursor('postprocessing', 0);
162
-
163
- // Each stage processes from its cursor position
164
- const toPreprocess = logBuffer.getSinceCursor('preprocessing');
165
- const toAnalyze = logBuffer.getSinceCursor('llm-analysis');
166
- ```
167
-
168
- ## Advanced Features
169
-
170
- ### Iterator Support
171
-
172
- ```javascript
173
- // Use with for...of loops
174
- for (const entry of buffer) {
175
- console.log(`Entry ${entry.id}: ${entry.data}`);
176
- }
177
-
178
- // Use with spread operator
179
- const allEntries = [...buffer];
180
- ```
181
-
182
- ### Filtered Buffers
183
-
184
- ```javascript
185
- // Create new buffer with filtered data
186
- const errorBuffer = buffer.createFiltered(
187
- entry => entry.data.includes('ERROR'),
188
- 500 // New buffer capacity
189
- );
190
- ```
191
-
192
- ### Cursor Metadata
193
-
194
- ```javascript
195
- const cursor = buffer.setCursor('processor-1');
196
- cursor.meta.set('owner', 'error-handler');
197
- cursor.meta.set('last-processed', new Date());
198
- ```
199
-
200
- ## Performance Characteristics
201
-
202
- - **Memory**: O(n) where n is buffer capacity (not total entries added)
203
- - **Push**: O(1) amortized
204
- - **Slice by ID**: O(n) where n is buffer size
205
- - **Slice by Index**: O(k) where k is slice size
206
- - **Cursor Operations**: O(1) for cursor management, O(n) for getSinceCursor
207
-
208
- ## Use Cases
209
-
210
- - **High-throughput Logging**: Capture logs without memory leaks
211
- - **LLM Chain Processing**: Batch operations on conversation history
212
- - **Stream Processing**: Process data streams with multiple consumers
213
- - **Audit Trails**: Maintain recent activity with automatic cleanup
214
- - **Performance Monitoring**: Track metrics with bounded memory usage
215
- - **Event Sourcing**: Store recent events with cursor-based replay
216
-
217
- The ring buffer is particularly valuable in LLM applications where you need to maintain context windows, process conversation history in batches, or implement streaming responses with memory constraints.
218
-
219
- ## Stable Batch Processing
220
-
221
- The ring buffer provides advanced stable batch processing capabilities that maintain consistent batch boundaries even when the buffer window changes due to eviction. This is essential for reliable retry scenarios and parallel processing.
222
-
223
- ### Key Features
224
-
225
- - **Globally Stable Batches**: Batch definitions based on entry IDs (not indices) remain consistent
226
- - **Cursor-Based Iteration**: Multiple cursors can iterate over identical batch boundaries
227
- - **Built-in Retry Logic**: Configurable retry with exponential backoff
228
- - **Parallel Processing**: Process batches concurrently while maintaining stability
229
- - **Resume Capability**: Resume processing from exact batch boundaries after interruption
230
-
231
- ### Basic Stable Batch Processing
232
-
233
- ```javascript
234
- const buffer = new RingBuffer(1000);
235
-
236
- // Add data
237
- for (let i = 1; i <= 100; i++) {
238
- buffer.push({ id: i, data: `item-${i}` });
239
- }
240
-
241
- // Process in stable batches with retry
242
- const results = await buffer.processStableBatches(10, async (entries, batchDef, context) => {
243
- console.log(`Processing ${batchDef.batchId}: ${entries.length} entries`);
244
-
245
- // Your processing logic here
246
- return entries.map(entry => entry.data.toUpperCase());
247
- }, {
248
- maxRetries: 3,
249
- retryDelay: (attempt) => 1000 * Math.pow(2, attempt), // Exponential backoff
250
- parallel: false, // Sequential processing
251
- onBatchStart: (batchDef) => console.log(`Starting ${batchDef.batchId}`),
252
- onBatchComplete: (batchDef, result) => console.log(`Completed ${batchDef.batchId}`),
253
- onBatchError: (batchDef, error, attempt) => console.log(`Error in ${batchDef.batchId}: ${error.message}`)
254
- });
255
- ```
256
-
257
- ### Resumable Processing with Cursors
258
-
259
- ```javascript
260
- // First processing run
261
- try {
262
- await buffer.processStableBatches(5, processor, {
263
- cursorName: 'main-processor',
264
- maxRetries: 2
265
- });
266
- } catch (error) {
267
- console.log('Processing interrupted:', error.message);
268
- }
269
-
270
- // Resume from where we left off
271
- const resumeResults = await buffer.processStableBatches(5, processor, {
272
- cursorName: 'main-processor' // Automatically resumes from cursor position
273
- });
274
- ```
275
-
276
- ### Parallel Processing with Synchronized Cursors
277
-
278
- ```javascript
279
- // Create synchronized cursors for multiple workers
280
- const workers = buffer.createSynchronizedBatchCursors(
281
- ['worker-1', 'worker-2', 'worker-3'],
282
- 20 // batch size
283
- );
284
-
285
- // Each worker processes different batches but with identical boundaries
286
- const results = await Promise.all([
287
- processWorkerBatches(workers['worker-1']),
288
- processWorkerBatches(workers['worker-2']),
289
- processWorkerBatches(workers['worker-3'])
290
- ]);
291
-
292
- async function processWorkerBatches(worker) {
293
- const results = [];
294
- while (true) {
295
- const batch = worker.next();
296
- if (batch.done) break;
297
-
298
- // Process this batch
299
- const result = await processBatch(batch.entries);
300
- results.push({ batchId: batch.batchDef.batchId, result });
301
- }
302
- return results;
303
- }
304
- ```
305
-
306
- ### Batch Cursor Iteration
307
-
308
- ```javascript
309
- // Create a batch cursor for manual iteration
310
- const cursor = buffer.createBatchCursor('manual-cursor', 15);
311
-
312
- while (true) {
313
- const batch = cursor.next();
314
- if (batch.done) break;
315
-
316
- console.log(`Processing batch ${batch.batchDef.batchId}`);
317
- console.log(` Entries: ${batch.entries.length}`);
318
- console.log(` ID range: ${batch.batchDef.startId}-${batch.batchDef.endId - 1}`);
319
-
320
- // Process entries
321
- await processEntries(batch.entries);
322
- }
323
-
324
- // Check cursor status
325
- const status = cursor.getStatus();
326
- console.log(`Processed batches, ${status.remainingEntries} entries remaining`);
327
- ```
328
-
329
- ### Integration with External Retry Libraries
330
-
331
- ```javascript
332
- import retry from 'your-retry-library';
333
-
334
- // Wrap your processor with external retry logic
335
- const retryProcessor = async (entries, batchDef, context) => {
336
- return await retry(async () => {
337
- // Your processing logic that might fail
338
- return await processEntries(entries);
339
- }, {
340
- retries: 3,
341
- factor: 2
342
- });
343
- };
344
-
345
- // Use with stable batch processing (no built-in retry needed)
346
- const results = await buffer.processStableBatches(10, retryProcessor, {
347
- maxRetries: 0 // Disable built-in retry since we're using external
348
- });
349
- ```
350
-
351
- ### Handling Missing Entries (Eviction)
352
-
353
- ```javascript
354
- // Small buffer that will evict entries
355
- const smallBuffer = new RingBuffer(50);
356
-
357
- // Add lots of data to force eviction
358
- for (let i = 1; i <= 100; i++) {
359
- smallBuffer.push(`item-${i}`);
360
- }
361
-
362
- // Process with missing entry handling
363
- const results = await smallBuffer.processStableBatches(10, processor, {
364
- startId: 1, // Some of these entries may be evicted
365
- skipMissingEntries: true // Skip batches with no available entries
366
- });
367
-
368
- // Check which batches were skipped
369
- results.forEach(result => {
370
- if (result.skipped) {
371
- console.log(`Batch ${result.batchId} was skipped (entries evicted)`);
372
- }
373
- });
374
- ```
375
-
376
- ### Advanced Configuration
377
-
378
- ```javascript
379
- const results = await buffer.processStableBatches(batchSize, processor, {
380
- // Cursor tracking
381
- cursorName: 'my-processor', // Track progress with named cursor
382
-
383
- // Range control
384
- startId: 100, // Start from specific entry ID
385
- endId: 500, // End at specific entry ID
386
-
387
- // Processing mode
388
- parallel: true, // Process batches in parallel
389
-
390
- // Retry configuration
391
- maxRetries: 5, // Maximum retry attempts per batch
392
- retryDelay: (attempt) => 1000 * attempt, // Custom delay function
393
-
394
- // Missing entry handling
395
- skipMissingEntries: true, // Skip batches with evicted entries
396
-
397
- // Event callbacks
398
- onBatchStart: (batchDef) => {
399
- console.log(`Starting ${batchDef.batchId}`);
400
- },
401
- onBatchComplete: (batchDef, result) => {
402
- console.log(`Completed ${batchDef.batchId}`);
403
- },
404
- onBatchError: (batchDef, error, attempt) => {
405
- console.log(`Error in ${batchDef.batchId} (attempt ${attempt}): ${error.message}`);
406
- }
407
- });
408
- ```
409
-
410
- ### Stable Batch Definitions
411
-
412
- ```javascript
413
- // Create stable batch definitions without processing
414
- const batchDefs = buffer.createStableBatches(10, {
415
- startId: 50,
416
- endId: 150,
417
- batchIdPrefix: 'custom'
418
- });
419
-
420
- console.log(`Created ${batchDefs.length} stable batches`);
421
-
422
- // Later, get entries for a specific batch
423
- const entries = buffer.getBatchEntries(batchDefs[0]);
424
- console.log(`Batch ${batchDefs[0].batchId} has ${entries.length} available entries`);
425
- ```
426
-
427
- ### Use Cases
428
-
429
- **Data Pipeline Processing**: Process large datasets in reliable, resumable batches
430
- ```javascript
431
- await buffer.processStableBatches(100, async (entries) => {
432
- return await sendToAPI(entries);
433
- }, { cursorName: 'pipeline', maxRetries: 3 });
434
- ```
435
-
436
- **Parallel Worker Processing**: Multiple workers processing different batches
437
- ```javascript
438
- const workers = buffer.createSynchronizedBatchCursors(['w1', 'w2', 'w3'], 50);
439
- // Each worker gets identical batch boundaries for consistent processing
440
- ```
441
-
442
- **Fault-Tolerant Batch Jobs**: Resume exactly where processing was interrupted
443
- ```javascript
444
- // Job can be interrupted and resumed with identical batch boundaries
445
- await buffer.processStableBatches(25, processor, {
446
- cursorName: 'batch-job',
447
- maxRetries: 5
448
- });
449
- ```
450
-
451
- **Memory-Efficient Stream Processing**: Process continuous data streams in batches
452
- ```javascript
453
- const cursor = buffer.createBatchCursor('stream', 20);
454
- setInterval(async () => {
455
- const batch = cursor.next();
456
- if (!batch.done) {
457
- await processStreamBatch(batch.entries);
458
- }
459
- }, 1000);
460
- ```