@far-world-labs/verblets 0.1.1 → 0.1.3

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 (300) hide show
  1. package/.cursor/launch.json +30 -0
  2. package/.cursor/settings.json +20 -0
  3. package/.github/workflows/branch-protection.yml +22 -0
  4. package/.github/workflows/ci.yml +120 -0
  5. package/.prettierrc +6 -0
  6. package/.release-it.json +4 -1
  7. package/.vscode/launch.json +31 -0
  8. package/AGENTS.md +220 -0
  9. package/DEVELOPING.md +105 -0
  10. package/README.md +254 -0
  11. package/eslint.config.js +80 -0
  12. package/package.json +29 -17
  13. package/scripts/generate-test/index.js +29 -3
  14. package/scripts/runner/index.js +26 -0
  15. package/scripts/simple-editor/index.js +29 -18
  16. package/scripts/summarize-files/index.js +28 -4
  17. package/src/chains/README.md +30 -0
  18. package/src/chains/anonymize/README.md +21 -0
  19. package/src/chains/anonymize/index.examples.js +75 -0
  20. package/src/chains/anonymize/index.js +121 -0
  21. package/src/chains/anonymize/index.spec.js +78 -0
  22. package/src/chains/bulk-central-tendency/index.examples.js +138 -0
  23. package/src/chains/bulk-central-tendency/index.js +91 -0
  24. package/src/chains/bulk-filter/README.md +21 -0
  25. package/src/chains/bulk-filter/index.examples.js +22 -0
  26. package/src/chains/bulk-filter/index.js +58 -0
  27. package/src/chains/bulk-filter/index.spec.js +38 -0
  28. package/src/chains/bulk-find/README.md +16 -0
  29. package/src/chains/bulk-find/index.examples.js +20 -0
  30. package/src/chains/bulk-find/index.js +30 -0
  31. package/src/chains/bulk-find/index.spec.js +26 -0
  32. package/src/chains/bulk-group/README.md +23 -0
  33. package/src/chains/bulk-group/index.examples.js +18 -0
  34. package/src/chains/bulk-group/index.js +34 -0
  35. package/src/chains/bulk-group/index.spec.js +41 -0
  36. package/src/chains/bulk-map/README.md +43 -0
  37. package/src/chains/bulk-map/index.examples.js +17 -0
  38. package/src/chains/bulk-map/index.js +86 -0
  39. package/src/chains/bulk-map/index.spec.js +44 -0
  40. package/src/chains/bulk-reduce/README.md +12 -0
  41. package/src/chains/bulk-reduce/index.examples.js +15 -0
  42. package/src/chains/bulk-reduce/index.js +13 -0
  43. package/src/chains/bulk-reduce/index.spec.js +25 -0
  44. package/src/chains/bulk-score/README.md +16 -0
  45. package/src/chains/bulk-score/bulk-score-result.json +18 -0
  46. package/src/chains/bulk-score/index.examples.js +22 -0
  47. package/src/chains/bulk-score/index.js +133 -0
  48. package/src/chains/bulk-score/index.spec.js +30 -0
  49. package/src/chains/category-samples/README.md +61 -0
  50. package/src/chains/category-samples/index.examples.js +103 -0
  51. package/src/chains/category-samples/index.js +134 -0
  52. package/src/chains/collect-terms/README.md +12 -0
  53. package/src/chains/collect-terms/index.examples.js +16 -0
  54. package/src/chains/collect-terms/index.js +44 -0
  55. package/src/chains/collect-terms/index.spec.js +25 -0
  56. package/src/chains/date/README.md +12 -0
  57. package/src/chains/date/index.examples.js +47 -0
  58. package/src/chains/date/index.js +74 -0
  59. package/src/chains/date/index.spec.js +62 -0
  60. package/src/chains/disambiguate/README.md +22 -0
  61. package/src/chains/disambiguate/disambiguate-meanings-result.json +16 -0
  62. package/src/chains/disambiguate/index.examples.js +18 -0
  63. package/src/chains/disambiguate/index.js +92 -0
  64. package/src/chains/disambiguate/index.spec.js +25 -0
  65. package/src/chains/dismantle/README.md +67 -0
  66. package/src/chains/dismantle/dismantle.examples.js +27 -0
  67. package/src/chains/dismantle/index.js +6 -17
  68. package/src/chains/dismantle/index.spec.js +1 -2
  69. package/src/chains/expect/README.md +171 -0
  70. package/src/chains/expect/index.examples.js +146 -0
  71. package/src/chains/expect/index.js +173 -0
  72. package/src/chains/expect/index.spec.js +324 -0
  73. package/src/chains/filter-ambiguous/README.md +11 -0
  74. package/src/chains/filter-ambiguous/index.examples.js +20 -0
  75. package/src/chains/filter-ambiguous/index.js +49 -0
  76. package/src/chains/filter-ambiguous/index.spec.js +31 -0
  77. package/src/chains/glossary/README.md +19 -0
  78. package/src/chains/glossary/index.examples.js +386 -0
  79. package/src/chains/glossary/index.js +75 -0
  80. package/src/chains/glossary/index.spec.js +19 -0
  81. package/src/chains/intersections/README.md +152 -0
  82. package/src/chains/intersections/index.examples.js +279 -0
  83. package/src/chains/intersections/index.js +366 -0
  84. package/src/chains/intersections/intersection-result.json +38 -0
  85. package/src/chains/list/index.examples.js +12 -16
  86. package/src/chains/list/index.js +106 -53
  87. package/src/chains/list/index.spec.js +8 -9
  88. package/src/chains/list/list-result.json +16 -0
  89. package/src/chains/llm-logger/README.md +208 -0
  90. package/src/chains/llm-logger/index.js +205 -0
  91. package/src/chains/llm-logger/index.spec.js +330 -0
  92. package/src/chains/questions/index.examples.js +2 -1
  93. package/src/chains/questions/index.js +14 -15
  94. package/src/chains/scan-js/index.js +6 -9
  95. package/src/chains/set-interval/README.md +81 -0
  96. package/src/chains/set-interval/index.examples.js +36 -0
  97. package/src/chains/set-interval/index.js +131 -0
  98. package/src/chains/set-interval/index.spec.js +70 -0
  99. package/src/chains/socratic/README.md +17 -0
  100. package/src/chains/socratic/index.js +64 -0
  101. package/src/chains/socratic/index.spec.js +24 -0
  102. package/src/chains/sort/index.examples.js +3 -7
  103. package/src/chains/sort/index.js +65 -15
  104. package/src/chains/sort/index.spec.js +5 -8
  105. package/src/chains/sort/sort-result.json +16 -0
  106. package/src/chains/summary-map/README.md +9 -1
  107. package/src/chains/summary-map/index.examples.js +9 -2
  108. package/src/chains/summary-map/index.js +43 -25
  109. package/src/chains/summary-map/index.spec.js +78 -3
  110. package/src/chains/test/index.js +9 -13
  111. package/src/chains/test-advice/index.js +4 -5
  112. package/src/chains/themes/README.md +20 -0
  113. package/src/chains/themes/index.examples.js +17 -0
  114. package/src/chains/themes/index.js +28 -0
  115. package/src/chains/themes/index.spec.js +19 -0
  116. package/src/chains/veiled-variants/index.examples.js +18 -0
  117. package/src/chains/veiled-variants/index.js +107 -0
  118. package/src/chains/veiled-variants/index.spec.js +40 -0
  119. package/src/constants/common.js +0 -2
  120. package/src/constants/models.js +172 -0
  121. package/src/index.js +178 -18
  122. package/src/json-schemas/README.md +13 -0
  123. package/src/json-schemas/index.js +8 -14
  124. package/src/json-schemas/schema-dot-org-photograph.json +11 -5
  125. package/src/json-schemas/schema-dot-org-place.json +78 -5
  126. package/src/lib/README.md +26 -0
  127. package/src/lib/bulk-filter/README.md +22 -0
  128. package/src/lib/bulk-filter/index.examples.js +27 -0
  129. package/src/lib/bulk-filter/index.js +63 -0
  130. package/src/lib/bulk-filter/index.spec.js +38 -0
  131. package/src/lib/bulk-find/README.md +18 -0
  132. package/src/lib/bulk-find/index.examples.js +19 -0
  133. package/src/lib/bulk-find/index.js +30 -0
  134. package/src/lib/bulk-find/index.spec.js +41 -0
  135. package/src/lib/chatgpt/index.js +63 -43
  136. package/src/lib/combinations/index.js +30 -0
  137. package/src/lib/combinations/index.spec.js +23 -0
  138. package/src/lib/functional/index.js +28 -0
  139. package/src/lib/logger-service/index.js +32 -0
  140. package/src/lib/parse-js-parts/index.js +9 -21
  141. package/src/lib/parse-llm-list/README.md +39 -0
  142. package/src/lib/parse-llm-list/index.js +54 -0
  143. package/src/lib/parse-llm-list/index.spec.js +59 -0
  144. package/src/lib/path-aliases/index.js +1 -3
  145. package/src/lib/path-aliases/index.spec.js +2 -8
  146. package/src/lib/pave/index.js +4 -4
  147. package/src/lib/pave/index.spec.js +6 -3
  148. package/src/lib/prompt-cache/index.js +14 -10
  149. package/src/lib/retry/index.js +11 -8
  150. package/src/lib/ring-buffer/README.md +460 -0
  151. package/src/lib/ring-buffer/index.js +1074 -0
  152. package/src/lib/search-best-first/city-walk.spec.js +37 -0
  153. package/src/lib/search-best-first/index.js +42 -11
  154. package/src/lib/search-best-first/index.spec.js +35 -0
  155. package/src/lib/search-js-files/index.js +44 -47
  156. package/src/lib/search-js-files/scan-file.js +10 -21
  157. package/src/lib/shorten-text/index.js +2 -7
  158. package/src/lib/shorten-text/index.spec.js +3 -3
  159. package/src/lib/strip-response/index.js +2 -7
  160. package/src/lib/template-replace/index.js +23 -0
  161. package/src/lib/template-replace/index.spec.js +60 -0
  162. package/src/lib/to-date/index.js +11 -0
  163. package/src/lib/to-number/index.js +1 -1
  164. package/src/lib/transcribe/index.js +26 -9
  165. package/src/prompts/README.md +3 -1
  166. package/src/prompts/as-object-with-schema.js +3 -8
  167. package/src/prompts/as-schema-org-text.js +10 -2
  168. package/src/prompts/code-features.js +1 -5
  169. package/src/prompts/constants.js +27 -27
  170. package/src/prompts/generate-collection.js +1 -1
  171. package/src/prompts/intent.js +16 -22
  172. package/src/prompts/select-from-threshold.js +1 -2
  173. package/src/prompts/sort.js +4 -8
  174. package/src/prompts/style.js +4 -7
  175. package/src/prompts/wrap-list.js +1 -4
  176. package/src/services/llm-model/global-overrides.spec.js +432 -0
  177. package/src/services/llm-model/index.js +234 -40
  178. package/src/services/llm-model/model.js +2 -2
  179. package/src/services/llm-model/negotiate.spec.js +447 -0
  180. package/src/services/redis/index.js +70 -7
  181. package/src/test/setup.js +20 -0
  182. package/src/verblets/README.md +26 -0
  183. package/src/verblets/auto/index.examples.js +12 -9
  184. package/src/verblets/auto/index.js +10 -10
  185. package/src/verblets/auto/index.spec.js +4 -6
  186. package/src/verblets/bool/README.md +36 -0
  187. package/src/verblets/bool/index.examples.js +53 -1
  188. package/src/verblets/bool/index.js +6 -9
  189. package/src/verblets/bool/index.spec.js +1 -3
  190. package/src/verblets/central-tendency/README.md +166 -0
  191. package/src/verblets/central-tendency/central-tendency-result.json +24 -0
  192. package/src/verblets/central-tendency/index.examples.js +196 -0
  193. package/src/verblets/central-tendency/index.js +171 -0
  194. package/src/verblets/central-tendency/index.spec.js +148 -0
  195. package/src/verblets/enum/index.examples.js +1 -4
  196. package/src/verblets/enum/index.js +7 -4
  197. package/src/verblets/expect/README.md +64 -0
  198. package/src/verblets/expect/index.examples.js +109 -0
  199. package/src/verblets/expect/index.js +75 -0
  200. package/src/verblets/expect/index.spec.js +127 -0
  201. package/src/verblets/intent/index.examples.js +95 -7
  202. package/src/verblets/intent/index.js +56 -68
  203. package/src/verblets/intersection/README.md +16 -0
  204. package/src/verblets/intersection/index.examples.js +89 -0
  205. package/src/verblets/intersection/index.js +84 -0
  206. package/src/verblets/intersection/index.spec.js +60 -0
  207. package/src/verblets/intersection/intersection-result.json +16 -0
  208. package/src/verblets/list-expand/README.md +10 -0
  209. package/src/verblets/list-expand/index.examples.js +14 -0
  210. package/src/verblets/list-expand/index.js +104 -0
  211. package/src/verblets/list-expand/index.spec.js +18 -0
  212. package/src/verblets/list-expand/list-expand-result.json +16 -0
  213. package/src/verblets/list-filter/README.md +22 -0
  214. package/src/verblets/list-filter/index.examples.js +26 -0
  215. package/src/verblets/list-filter/index.js +18 -0
  216. package/src/verblets/list-filter/index.spec.js +19 -0
  217. package/src/verblets/list-find/README.md +11 -0
  218. package/src/verblets/list-find/index.examples.js +15 -0
  219. package/src/verblets/list-find/index.js +17 -0
  220. package/src/verblets/list-find/index.spec.js +19 -0
  221. package/src/verblets/list-group/README.md +16 -0
  222. package/src/verblets/list-group/index.examples.js +16 -0
  223. package/src/verblets/list-group/index.js +112 -0
  224. package/src/verblets/list-group/index.spec.js +35 -0
  225. package/src/verblets/list-group/list-group-result.json +16 -0
  226. package/src/verblets/list-map/README.md +11 -0
  227. package/src/verblets/list-map/index.examples.js +15 -0
  228. package/src/verblets/list-map/index.js +26 -0
  229. package/src/verblets/list-map/index.spec.js +17 -0
  230. package/src/verblets/list-reduce/README.md +10 -0
  231. package/src/verblets/list-reduce/index.examples.js +14 -0
  232. package/src/verblets/list-reduce/index.js +21 -0
  233. package/src/verblets/list-reduce/index.spec.js +27 -0
  234. package/src/verblets/list-reduce/index.spec.jsx +27 -0
  235. package/src/verblets/name/README.md +15 -0
  236. package/src/verblets/name/index.examples.js +28 -0
  237. package/src/verblets/name/index.js +19 -0
  238. package/src/verblets/name/index.spec.js +33 -0
  239. package/src/verblets/name-similar-to/README.md +26 -0
  240. package/src/verblets/name-similar-to/index.examples.js +18 -0
  241. package/src/verblets/name-similar-to/index.js +20 -0
  242. package/src/verblets/name-similar-to/index.spec.js +13 -0
  243. package/src/verblets/number/index.examples.js +173 -7
  244. package/src/verblets/number/index.js +5 -2
  245. package/src/verblets/number/index.spec.js +1 -3
  246. package/src/verblets/number-with-units/index.examples.js +5 -1
  247. package/src/verblets/number-with-units/index.js +74 -9
  248. package/src/verblets/number-with-units/number-with-units-result.json +23 -0
  249. package/src/verblets/schema-org/index.examples.js +2 -7
  250. package/src/verblets/schema-org/index.js +32 -3
  251. package/src/verblets/sentiment/README.md +10 -0
  252. package/src/verblets/sentiment/index.examples.js +20 -0
  253. package/src/verblets/sentiment/index.js +9 -0
  254. package/src/verblets/sentiment/index.spec.js +20 -0
  255. package/src/verblets/to-object/index.js +10 -15
  256. package/src/verblets/to-object/index.spec.js +1 -4
  257. package/.eslintrc.json +0 -42
  258. package/docs/README.md +0 -41
  259. package/docs/babel.config.js +0 -3
  260. package/docs/blog/2019-05-28-first-blog-post.md +0 -12
  261. package/docs/blog/2019-05-29-long-blog-post.md +0 -44
  262. package/docs/blog/2021-08-01-mdx-blog-post.mdx +0 -20
  263. package/docs/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg +0 -0
  264. package/docs/blog/2021-08-26-welcome/index.md +0 -25
  265. package/docs/blog/authors.yml +0 -17
  266. package/docs/docs/api/bool.md +0 -74
  267. package/docs/docs/api/search.md +0 -51
  268. package/docs/docs/intro.md +0 -47
  269. package/docs/docs/tutorial-basics/_category_.json +0 -8
  270. package/docs/docs/tutorial-basics/congratulations.md +0 -23
  271. package/docs/docs/tutorial-basics/create-a-blog-post.md +0 -34
  272. package/docs/docs/tutorial-basics/create-a-document.md +0 -57
  273. package/docs/docs/tutorial-basics/create-a-page.md +0 -43
  274. package/docs/docs/tutorial-basics/deploy-your-site.md +0 -31
  275. package/docs/docs/tutorial-basics/markdown-features.mdx +0 -152
  276. package/docs/docs/tutorial-extras/_category_.json +0 -7
  277. package/docs/docs/tutorial-extras/img/docsVersionDropdown.png +0 -0
  278. package/docs/docs/tutorial-extras/img/localeDropdown.png +0 -0
  279. package/docs/docs/tutorial-extras/manage-docs-versions.md +0 -55
  280. package/docs/docs/tutorial-extras/translate-your-site.md +0 -88
  281. package/docs/docusaurus.config.js +0 -120
  282. package/docs/package.json +0 -44
  283. package/docs/sidebars.js +0 -31
  284. package/docs/src/components/HomepageFeatures/index.js +0 -61
  285. package/docs/src/components/HomepageFeatures/styles.module.css +0 -11
  286. package/docs/src/css/custom.css +0 -30
  287. package/docs/src/pages/index.js +0 -43
  288. package/docs/src/pages/index.module.css +0 -23
  289. package/docs/src/pages/markdown-page.md +0 -7
  290. package/docs/static/.nojekyll +0 -0
  291. package/docs/static/img/docusaurus-social-card.jpg +0 -0
  292. package/docs/static/img/docusaurus.png +0 -0
  293. package/docs/static/img/favicon.ico +0 -0
  294. package/docs/static/img/logo.svg +0 -1
  295. package/docs/static/img/undraw_docusaurus_mountain.svg +0 -171
  296. package/docs/static/img/undraw_docusaurus_react.svg +0 -170
  297. package/docs/static/img/undraw_docusaurus_tree.svg +0 -40
  298. package/src/constants/openai.js +0 -65
  299. /package/{.vite.config.examples.js → .vitest.config.examples.js} +0 -0
  300. /package/{.vite.config.js → .vitest.config.js} +0 -0
package/README.md ADDED
@@ -0,0 +1,254 @@
1
+ # Verblets
2
+
3
+ Verblets is a library of AI-powered utilities that transform natural language and structured data into reliable, structured outputs. Each function uses language model intelligence while constraining outputs to limit hallucination and ensure software reliability.
4
+
5
+ ## Repository Guide
6
+
7
+ ### Quick Links
8
+
9
+ - [Chains](./src/chains/) - AI-powered workflows and operations
10
+ - [Verblets](./src/verblets/) - Core AI utility functions
11
+ - [Library Helpers](./src/lib/) - Utility functions and wrappers
12
+ - [Prompts](./src/prompts/) - Reusable prompt templates
13
+ - [JSON Schemas](./src/json-schemas/) - Data validation schemas
14
+
15
+ ## Verblets
16
+
17
+ ### Primitives
18
+
19
+ Primitive verblets extract basic data types from natural language with high reliability. They constrain LLM outputs to prevent hallucination while handling the complexity of human expression.
20
+
21
+ - [bool](./src/verblets/bool) - interpret text as true/false decisions
22
+ - [enum](./src/verblets/enum) - map text to predefined options
23
+ - [number](./src/verblets/number) - extract numeric values from text
24
+ - [number-with-units](./src/verblets/number-with-units) - parse numbers with units and conversions
25
+ - [date](./src/chains/date) - return Date objects from natural language prompts
26
+
27
+ ### Lists
28
+
29
+ List operations transform, filter, and organize collections using natural language criteria. They handle both small lists with individual verblets and large datasets with batch processing chains.
30
+
31
+ - [bulk-map](./src/chains/bulk-map) - process long lists in retryable batches
32
+ - [bulk-reduce](./src/chains/bulk-reduce) - reduce long lists in manageable chunks
33
+ - [bulk-find](./src/chains/bulk-find) - locate the best match in large datasets
34
+ - [bulk-group](./src/chains/bulk-group) - group large datasets efficiently
35
+ - [bulk-filter](./src/chains/bulk-filter) - filter huge lists in batches
36
+ - [intersections](./src/chains/intersections) - find comprehensive intersections for all combinations
37
+ - [list](./src/chains/list) - generate contextual lists from prompts
38
+ - [list-map](./src/verblets/list-map) - transform each item in a list
39
+ - [list-reduce](./src/verblets/list-reduce) - combine list items using custom logic
40
+ - [list-find](./src/verblets/list-find) - pick the single best item from a list
41
+ - [list-filter](./src/verblets/list-filter) - filter lists with natural language criteria
42
+ - [list-group](./src/verblets/list-group) - categorize list items into groups
43
+ - [list-expand](./src/verblets/list-expand) - generate additional similar items
44
+ - [intersection](./src/verblets/intersection) - describe common traits between items
45
+ - [sort](./src/chains/sort) - order lists by any describable criteria
46
+ - [bulk-score](./src/chains/bulk-score) - score lists with calibrated examples
47
+
48
+ ### Content
49
+
50
+ Content utilities generate, transform, and analyze text while maintaining structure and meaning. They excel at creative tasks, system analysis, and privacy-aware text processing.
51
+
52
+ - [anonymize](./src/chains/anonymize) - scrub personal details from text
53
+ - [collect-terms](./src/chains/collect-terms) - extract difficult vocabulary
54
+ - [dismantle](./src/chains/dismantle) - break systems into components
55
+ - [disambiguate](./src/chains/disambiguate) - resolve ambiguous word meanings using context
56
+ - [filter-ambiguous](./src/chains/filter-ambiguous) - find and rank unclear terms for disambiguation
57
+ - [name](./src/verblets/name) - name something from a definition or description
58
+ - [name-similar-to](./src/verblets/name-similar-to) - suggest short names that match a style
59
+ - [questions](./src/chains/questions) - produce clarifying questions
60
+ - [schema-org](./src/verblets/schema-org) - create schema.org objects
61
+ - [socratic](./src/chains/socratic) - explore assumptions using a Socratic dialogue
62
+ - [summary-map](./src/chains/summary-map) - summarize a collection
63
+ - [themes](./src/chains/themes) - identify themes in text
64
+ - [category-samples](./src/chains/category-samples) - generate diverse examples for any category
65
+ - [to-object](./src/verblets/to-object) - convert descriptions to structured objects
66
+ - [veiled-variants](./src/chains/veiled-variants) - rephrase sensitive queries safely
67
+
68
+ ### Utility Operations
69
+
70
+ Utility operations provide meta-functionality like automatic tool selection, intent parsing, and context compression. They're essential for building intelligent systems that can adapt and scale.
71
+
72
+ - [auto](./src/verblets/auto) - automatically select the best verblet for a task
73
+ - [expect](./src/verblets/expect) - simple LLM assertions
74
+ - [expect chain](./src/chains/expect) - assert things about data with LLM reasoning
75
+ - [intent](./src/verblets/intent) - extract user intent and structured parameters
76
+ - [sentiment](./src/verblets/sentiment) - detect emotional tone of text
77
+ - [summary-map](./src/chains/summary-map) - store self-resizing hash table values. Useful for fixed-sized contexts.
78
+ - [set-interval](./src/chains/set-interval) - Conversational scheduler
79
+
80
+ ### Codebase
81
+
82
+ Codebase utilities analyze, test, and improve code quality using AI reasoning. They provide insights that traditional static analysis tools miss by understanding context and intent.
83
+
84
+ - [scan-js](./src/chains/scan-js) - analyze JavaScript code quality
85
+ - [test](./src/chains/test) - run AI-driven software tests
86
+ - [test-advice](./src/chains/test-advice) - get feedback on test coverage
87
+
88
+ ## Library Helpers
89
+
90
+ - [chatgpt](./src/lib/chatgpt) - OpenAI ChatGPT wrapper
91
+ - [prompt-cache](./src/lib/prompt-cache) - cache prompts and responses
92
+ - [retry](./src/lib/retry) - retry asynchronous calls
93
+ - [search-best-first](./src/lib/search-best-first) - best-first search algorithm
94
+ - [search-js-files](./src/lib/search-js-files) - scan JavaScript sources
95
+ - [combinations](./src/lib/combinations) - generate array combinations
96
+ - [shorten-text](./src/lib/shorten-text) - shorten text using a model
97
+ - [strip-numeric](./src/lib/strip-numeric) - remove non-digit characters
98
+ - [strip-response](./src/lib/strip-response) - clean up model responses
99
+ - [to-bool](./src/lib/to-bool) - parse text to boolean
100
+ - [to-enum](./src/lib/to-enum) - parse text to enum values
101
+ - [to-number](./src/lib/to-number) - parse text to numbers
102
+ - [to-number-with-units](./src/lib/to-number-with-units) - parse numbers with units
103
+ - [to-date](./src/lib/to-date) - parse text to JavaScript Date objects
104
+ - [transcribe](./src/lib/transcribe) - microphone transcription via Whisper
105
+
106
+ ## Example: Intelligent Customer Support System
107
+
108
+ This example shows how verblets enable building systems that understand context, make nuanced decisions, and adapt to complex real-world scenarios - capabilities that would be nearly impossible with traditional programming approaches.
109
+
110
+ ```javascript
111
+ import bulkMap from './src/chains/bulk-map/index.js';
112
+ import list from './src/chains/list/index.js';
113
+ import {
114
+ anonymize,
115
+ bool,
116
+ enum,
117
+ intent,
118
+ listFilter,
119
+ questions,
120
+ sort,
121
+ toObject,
122
+ sentiment,
123
+ bulkScore
124
+ } from 'verblets';
125
+
126
+ // Intelligent customer support system that handles complex, contextual requests
127
+ async function handleCustomerRequest(message, history, catalog) {
128
+ const customerIntent = await intent({
129
+ text: message,
130
+ operations: [
131
+ { name: 'refund-request', parameters: { reason: 'string', orderNumber: 'string?' } },
132
+ { name: 'product-inquiry', parameters: { productType: 'string', feature: 'string?' } },
133
+ { name: 'technical-support', parameters: { issue: 'string', urgency: 'string' } },
134
+ { name: 'complaint', parameters: { category: 'string', severity: 'string' } }
135
+ ]
136
+ });
137
+
138
+ const emotion = await sentiment(message);
139
+ const urgent = await bool(`Is this urgent? ${message}`);
140
+
141
+ const strategy = await enum(message, {
142
+ immediate_escalation: 'Customer is very upset, escalate to human agent',
143
+ detailed_help: 'Customer needs comprehensive assistance',
144
+ quick_resolution: 'Simple issue that can be resolved quickly',
145
+ educational: 'Customer needs to understand how something works'
146
+ });
147
+
148
+ const followUpQuestions = await questions(
149
+ `Customer says: "${message}". What should we ask to help them better?`
150
+ );
151
+
152
+ const candidates = await listFilter(
153
+ catalog,
154
+ `Products that might solve: ${
155
+ customerIntent.parameters.issue || customerIntent.parameters.productType
156
+ }`
157
+ );
158
+
159
+ const scores = await bulkScore(candidates, 'resolution likelihood');
160
+ const prioritized = await sort(candidates, `by likelihood score ${scores.join(', ')}`);
161
+
162
+ const bulletPoints = await bulkMap(
163
+ prioritized.map(p => p.name),
164
+ 'Write a friendly one-line apology referencing <list>.'
165
+ );
166
+
167
+ const sampleReplies = await list('3 reassuring follow-up messages for this customer');
168
+
169
+ const caseSummary = await anonymize(
170
+ `Customer ${customerIntent.intent.operation}: ${message}.
171
+ History: ${history}. Resolution: ${prioritized[0]}`
172
+ );
173
+
174
+ const response = await toObject(
175
+ `
176
+ Customer needs ${customerIntent.intent.operation} help.
177
+ They are ${emotion} and ${urgent ? 'urgent' : 'not urgent'}.
178
+ Best approach: ${strategy}.
179
+ Top solution: ${prioritized[0]?.name}
180
+ `,
181
+ {
182
+ type: 'object',
183
+ properties: {
184
+ intent: { type: 'string' },
185
+ urgency: { type: 'string' },
186
+ emotion: { type: 'string' },
187
+ strategy: { type: 'string' },
188
+ recommendedSolution: { type: 'string' },
189
+ followUpQuestions: { type: 'array' }
190
+ }
191
+ }
192
+ );
193
+
194
+
195
+ return {
196
+ ...response,
197
+ followUpQuestions: followUpQuestions.slice(0, 3),
198
+ anonymizedCase: caseSummary,
199
+ bulletPoints,
200
+ sampleReplies
201
+ };
202
+ }
203
+
204
+ // Usage: Handle a complex customer scenario
205
+ const result = await handleCustomerRequest(
206
+ "I'm really frustrated! I ordered your premium headphones 2 weeks ago for my daughter's birthday tomorrow and they still haven't arrived. The tracking says 'processing' but I paid for 2-day shipping. This is completely unacceptable and I want my money back immediately!",
207
+ 'Previous orders: 3 successful deliveries, 1 late delivery complaint resolved',
208
+ [
209
+ {
210
+ name: 'Premium Wireless Headphones',
211
+ category: 'audio',
212
+ features: ['noise-canceling', 'wireless']
213
+ },
214
+ { name: 'Express Shipping Upgrade', category: 'service', features: ['priority', 'tracking'] },
215
+ { name: 'Gift Card', category: 'compensation', features: ['flexible', 'immediate'] }
216
+ ]
217
+ );
218
+
219
+ /* Returns something like:
220
+ {
221
+ intent: "refund-request",
222
+ urgency: "high",
223
+ emotion: "frustrated",
224
+ strategy: "immediate_escalation",
225
+ recommendedSolution: "Express Shipping Upgrade",
226
+ followUpQuestions: [
227
+ "What's your order number so I can track this immediately?",
228
+ "Would you like us to expedite a replacement for tomorrow delivery?",
229
+ "How can we make this right for your daughter's birthday?"
230
+ ],
231
+ anonymizedCase: "Customer refund-request: Customer frustrated about delayed premium headphones order for child's birthday..."
232
+ bulletPoints: ["Apologies for the delay on Premium Wireless Headphones", ...],
233
+ sampleReplies: ["We're monitoring shipping updates...", ...]
234
+ }
235
+ */
236
+ ```
237
+
238
+ This system demonstrates capabilities that would require thousands of lines of traditional code and extensive machine learning expertise:
239
+
240
+ - **Contextual understanding** of customer emotions and intent
241
+ - **Dynamic decision making** based on multiple factors
242
+ - **Adaptive questioning** that changes based on the situation
243
+ - **Intelligent prioritization** of solutions
244
+ - **Privacy-aware data handling** for compliance
245
+ - **Structured output** that integrates with existing systems
246
+
247
+
248
+ ## Contributing
249
+
250
+ Help us explore what's possible when we rebuild software primitives with intelligence at their core.
251
+
252
+ ## License
253
+
254
+ All Rights Reserved - Far World Labs
@@ -0,0 +1,80 @@
1
+ import js from '@eslint/js';
2
+ import prettierConfig from 'eslint-config-prettier';
3
+ import prettierPlugin from 'eslint-plugin-prettier';
4
+
5
+ export default [
6
+ js.configs.recommended,
7
+ {
8
+ files: ['src/**/*.js'],
9
+ languageOptions: {
10
+ ecmaVersion: 2022,
11
+ sourceType: 'module',
12
+ globals: {
13
+ console: 'readonly',
14
+ process: 'readonly',
15
+ Buffer: 'readonly',
16
+ __dirname: 'readonly',
17
+ __filename: 'readonly',
18
+ URL: 'readonly',
19
+ AbortController: 'readonly',
20
+ fetch: 'readonly',
21
+ setTimeout: 'readonly',
22
+ clearTimeout: 'readonly',
23
+ setInterval: 'readonly',
24
+ clearInterval: 'readonly',
25
+ // Vitest
26
+ beforeEach: 'readonly',
27
+ afterEach: 'readonly',
28
+ describe: 'readonly',
29
+ it: 'readonly',
30
+ expect: 'readonly',
31
+ vi: 'readonly',
32
+ },
33
+ },
34
+ linterOptions: {
35
+ reportUnusedDisableDirectives: false,
36
+ },
37
+ plugins: {
38
+ prettier: prettierPlugin,
39
+ },
40
+ rules: {
41
+ 'prettier/prettier': 'error',
42
+
43
+ // TODO: Remove console statements and replace with proper logging
44
+ 'no-console': 'off',
45
+
46
+ // TODO: Refactor await-in-loop patterns to use Promise.all()
47
+ 'no-await-in-loop': 'off',
48
+
49
+ // Customize recommended rules
50
+ 'no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
51
+
52
+ // Additional quality rules not in recommended
53
+ 'require-await': 'error',
54
+ 'prefer-arrow-callback': 'error',
55
+ 'prefer-template': 'error',
56
+ 'object-shorthand': 'error',
57
+ 'array-callback-return': 'error',
58
+
59
+ // Syntax restrictions
60
+ 'no-restricted-syntax': [
61
+ 'error',
62
+ {
63
+ selector: 'ForInStatement',
64
+ message: 'Use Object.{keys,values,entries} instead of for..in',
65
+ },
66
+ {
67
+ selector: 'WithStatement',
68
+ message: '`with` is not allowed',
69
+ },
70
+ ],
71
+ },
72
+ },
73
+ {
74
+ files: ['**/*.spec.js', '**/*.test.js'],
75
+ rules: {
76
+ 'require-await': 'off', // Test functions often don't need await
77
+ },
78
+ },
79
+ prettierConfig,
80
+ ];
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@far-world-labs/verblets",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "OpenAI Client",
5
- "main": "index.js",
5
+ "main": "src/index.js",
6
6
  "type": "module",
7
7
  "repository": {
8
8
  "type": "git",
@@ -15,56 +15,68 @@
15
15
  "--": "npm run script -- generate-verblet foo",
16
16
  "script": "./scripts/run.sh",
17
17
  "test": "vitest",
18
- "examples": "EXAMPLES=true vitest --config .vite.config.examples.js",
18
+ "examples:warn": "source .env && LLM_EXPECT_MODE=info EXAMPLES=true vitest --config .vitest.config.examples.js",
19
+ "examples": "source .env && LLM_EXPECT_MODE=error EXAMPLES=true vitest --config .vitest.config.examples.js",
19
20
  "lint": "eslint 'src/**/*.{js,jsx}'",
20
21
  "lint:fix": "eslint 'src/**/*.{js,jsx}' --fix",
22
+ "check:deps": "npx npm-deprecated-check current",
21
23
  "husky:install": "husky install",
22
24
  "husky:uninstall": "husky uninstall",
23
- "prepare": "npx husky install"
25
+ "prepare": "npx husky install",
26
+ "version:patch": "npm version patch",
27
+ "version:minor": "npm version minor",
28
+ "version:major": "npm version major"
24
29
  },
25
30
  "config": {
26
31
  "gen-script": "./scripts/run.sh gen-$1"
27
32
  },
28
33
  "author": "Far World Labs",
29
34
  "license": "All Rights Reserved",
35
+ "publishConfig": {
36
+ "access": "public"
37
+ },
30
38
  "dependencies": {
31
39
  "acorn": "^8.8.2",
32
40
  "acorn-walk": "^8.2.0",
33
41
  "ajv": "^8.12.0",
34
42
  "chai": "^4.3.7",
35
43
  "change-case": "^4.1.2",
44
+ "commander": "^11.0.0",
45
+ "compromise": "^14.14.4",
36
46
  "dependency-tree": "^10.0.1",
37
47
  "dotenv": "^16.0.3",
38
48
  "gpt-tokenizer": "^2.1.2",
39
49
  "gpt4-tokenizer": "^1.3.0",
50
+ "lodash": "^4.17.21",
40
51
  "mocha": "^10.2.0",
41
52
  "node-fetch": "^3.3.0",
42
- "nodemon": "^2.0.22",
53
+ "node-record-lpcm16": "^1.0.1",
43
54
  "ramda": "^0.29.0",
44
55
  "redis": "^4.6.5",
45
56
  "uuid": "^9.0.0",
46
- "vitest": "^0.30.1",
57
+ "vitest": "^3.1.3",
58
+ "whisper-node": "^1.1.1",
47
59
  "yargs": "^17.7.1"
48
60
  },
49
61
  "devDependencies": {
62
+ "@eslint/js": "^9.28.0",
63
+ "@stylistic/eslint-plugin": "^4.4.0",
50
64
  "@types/node": "^18.16.3",
51
- "eslint": "^8.39.0",
52
- "eslint-config-airbnb": "^19.0.4",
65
+ "@vitest/ui": "^3.1.3",
66
+ "eslint": "^9.28.0",
53
67
  "eslint-config-prettier": "^8.8.0",
54
- "eslint-plugin-import": "^2.27.5",
55
- "eslint-plugin-jest": "^27.2.1",
56
- "eslint-plugin-jsx-a11y": "^6.7.1",
68
+ "eslint-plugin-import": "^2.31.0",
69
+ "eslint-plugin-jest": "^28.12.0",
57
70
  "eslint-plugin-prettier": "^4.2.1",
58
- "eslint-plugin-react": "^7.32.2",
59
- "eslint-plugin-react-hooks": "^4.6.0",
71
+ "eslint-plugin-unicorn": "^59.0.1",
72
+ "eslint-plugin-vitest": "^0.5.4",
60
73
  "husky": "^8.0.3",
61
74
  "install-peerdeps": "^3.0.3",
62
75
  "lint-staged": "^13.2.2",
63
- "node-record-lpcm16": "^1.0.1",
64
- "npm-check": "^6.0.1",
76
+ "nodemon": "^3.1.10",
77
+ "npm-deprecated-check": "^1.5.0",
65
78
  "prettier": "^2.8.8",
66
- "release-it": "^15.10.1",
67
- "whisper-node": "^1.1.1",
79
+ "release-it": "^19.0.3",
68
80
  "why-is-node-running": "^2.2.2"
69
81
  },
70
82
  "lint-staged": {
@@ -8,9 +8,35 @@ chatGPT,
8
8
  getRedis,
9
9
  SummaryMap
10
10
  } from '../../src/index.js';
11
-
12
- const modulePath = process.argv[2];
13
- const functionName = process.argv[3];
11
+ import modelService from '../../src/services/llm-model/index.js';
12
+ import { Command } from 'commander';
13
+
14
+ const program = new Command();
15
+ program
16
+ .argument('<modulePath>', 'Module to test')
17
+ .argument('[functionName]', 'Specific function to test')
18
+ .option('-p, --privacy', 'Use privacy model if configured')
19
+ .option('-m, --model <modelName>', 'Specify model name to use');
20
+
21
+ program.parse(process.argv);
22
+
23
+ const options = program.opts();
24
+ const [modulePath, functionName] = program.args;
25
+
26
+ if (options.privacy) {
27
+ try {
28
+ modelService.setGlobalOverride('modelName', 'privacy');
29
+ } catch (err) {
30
+ console.error(`Privacy model error: ${err.message}`);
31
+ }
32
+ }
33
+ if (options.model) {
34
+ try {
35
+ modelService.setGlobalOverride('modelName', options.model);
36
+ } catch (err) {
37
+ console.error(`Model override error: ${err.message}`);
38
+ }
39
+ }
14
40
 
15
41
  if (!modulePath) {
16
42
  console.error('Please specify a module to test.');
@@ -5,6 +5,32 @@ import chatGPT, {
5
5
  retry as run,
6
6
  schemas,
7
7
  } from '../../src/index.js';
8
+ import modelService from '../../src/services/llm-model/index.js';
9
+ import { Command } from 'commander';
10
+
11
+ const program = new Command();
12
+ program
13
+ .option('-p, --privacy', 'Use privacy model if configured')
14
+ .option('-m, --model <modelName>', 'Specify model name to use');
15
+
16
+ program.parse(process.argv);
17
+
18
+ const options = program.opts();
19
+
20
+ if (options.privacy) {
21
+ try {
22
+ modelService.setGlobalOverride('modelName', 'privacy');
23
+ } catch (err) {
24
+ console.error(`Privacy model error: ${err.message}`);
25
+ }
26
+ }
27
+ if (options.model) {
28
+ try {
29
+ modelService.setGlobalOverride('modelName', options.model);
30
+ } catch (err) {
31
+ console.error(`Model override error: ${err.message}`);
32
+ }
33
+ }
8
34
 
9
35
  await run(async () => {
10
36
  const results = await chatGPT('make a list of nintendo games with a schema that includes a title, year, and maybe a couple others of your choice', {
@@ -1,25 +1,36 @@
1
1
  import dotenv from 'dotenv/config';
2
- import yargs from 'yargs';
3
- import { hideBin } from 'yargs/helpers';
2
+ import { Command } from 'commander';
4
3
 
5
4
  import chatGPT, { getRedis, auto, bool } from '../../src/index.js';
5
+ import modelService from '../../src/services/llm-model/index.js';
6
6
  import edit from '../../src/lib/editor/index.js';
7
7
  import Transcriber from '../../src/lib/transcribe/index.js';
8
8
 
9
- const argv = yargs(hideBin(process.argv))
10
- .option('use-intent', {
11
- alias: 'i',
12
- default: 'true',
13
- type: 'string',
14
- description: '"false" to disable intent parsing and just use chatGPT',
15
- })
16
- .option('transcribe', {
17
- alias: 't',
18
- default: 'false',
19
- type: 'string',
20
- description: '"true" to enable audio transcription',
21
- })
22
- .argv;
9
+ const program = new Command();
10
+ program
11
+ .option('-t, --transcribe', 'Enable audio transcription')
12
+ .option('--no-use-intent', 'Disable intent parsing')
13
+ .option('-p, --privacy', 'Use privacy model if configured')
14
+ .option('-m, --model <modelName>', 'Specify model name to use');
15
+
16
+ program.parse(process.argv);
17
+
18
+ const argv = program.opts();
19
+
20
+ if (argv.privacy) {
21
+ try {
22
+ modelService.setGlobalOverride('modelName', 'privacy');
23
+ } catch (err) {
24
+ console.error(`Privacy model error: ${err.message}`);
25
+ }
26
+ }
27
+ if (argv.model) {
28
+ try {
29
+ modelService.setGlobalOverride('modelName', argv.model);
30
+ } catch (err) {
31
+ console.error(`Model override error: ${err.message}`);
32
+ }
33
+ }
23
34
 
24
35
  const operations = [
25
36
  {
@@ -32,7 +43,7 @@ const operations = [
32
43
 
33
44
 
34
45
  let userInput;
35
- const useTranscribe = ['true', '1'].includes(argv.transcribe)
46
+ const useTranscribe = !!argv.transcribe;
36
47
  if (useTranscribe) {
37
48
  const transcriber = new Transcriber("stopword"); // Replace "stopword" with the word you want to trigger the stop
38
49
  userInput = await transcriber.startRecording()
@@ -40,7 +51,7 @@ if (useTranscribe) {
40
51
  userInput = await edit();
41
52
  }
42
53
 
43
- const useIntent = !!['true', '1'].includes(argv.useIntent.toLowerCase())
54
+ const useIntent = argv.useIntent !== false;
44
55
 
45
56
  const commandType = useIntent ? 'Tool selection' : 'Direct ChatGPT';
46
57
  console.error(`Command: ${commandType}`);
@@ -1,12 +1,36 @@
1
1
  import glob from 'glob';
2
2
  import { readFile } from 'fs/promises';
3
3
  import SummaryMap from '../../src/chains/summary-map/index.js';
4
+ import modelService from '../../src/services/llm-model/index.js';
5
+ import { Command } from 'commander';
4
6
 
5
- // Define your glob pattern here or pass it as a command line argument
6
- const globPattern = process.argv[2] || './src/**/*.js';
7
+ const program = new Command();
8
+ program
9
+ .argument('[globPattern]', 'Glob pattern to summarize', './src/**/*.js')
10
+ .argument('[targetTokens]', 'Target token count', '4097')
11
+ .option('-p, --privacy', 'Use privacy model if configured')
12
+ .option('-m, --model <modelName>', 'Specify model name to use');
7
13
 
8
- // Define your target tokens here or pass it as a command line argument
9
- const targetTokens = process.argv[3] || 4097;
14
+ program.parse(process.argv);
15
+
16
+ const options = program.opts();
17
+ const [globPattern, targetTokensInput] = program.args;
18
+ const targetTokens = Number(targetTokensInput);
19
+
20
+ if (options.privacy) {
21
+ try {
22
+ modelService.setGlobalOverride('modelName', 'privacy');
23
+ } catch (err) {
24
+ console.error(`Privacy model error: ${err.message}`);
25
+ }
26
+ }
27
+ if (options.model) {
28
+ try {
29
+ modelService.setGlobalOverride('modelName', options.model);
30
+ } catch (err) {
31
+ console.error(`Model override error: ${err.message}`);
32
+ }
33
+ }
10
34
 
11
35
  // Initialize the SummaryMap with the target tokens
12
36
  const map = new SummaryMap({
@@ -0,0 +1,30 @@
1
+ # Chains
2
+
3
+ Chains orchestrate multiple verblets or helper functions to perform more complex tasks. Each subdirectory exposes a specific workflow that can be imported as a single function.
4
+
5
+ Available chains:
6
+
7
+ - [anonymize](./anonymize)
8
+ - [bulk-map](./bulk-map)
9
+ - [bulk-reduce](./bulk-reduce)
10
+ - [bulk-filter](./bulk-filter)
11
+ - [bulk-group](./bulk-group)
12
+ - [dismantle](./dismantle)
13
+ - [disambiguate](./disambiguate)
14
+ - [intersections](./intersections)
15
+ - [list](./list)
16
+ - [questions](./questions)
17
+ - [socratic](./socratic)
18
+ - [glossary](./glossary)
19
+ - [scan-js](./scan-js)
20
+ - [sort](./sort)
21
+ - [summary-map](./summary-map)
22
+ - [themes](./themes)
23
+ - [set-interval](./set-interval)
24
+ - [test](./test)
25
+ - [test-advice](./test-advice)
26
+ - [veiled-variants](./veiled-variants)
27
+ - [collect-terms](./collect-terms) - gather complex vocabulary
28
+
29
+ Chains are free to use any utilities from [`../lib`](../lib/README.md) and often rely on one or more verblets from [`../verblets`](../verblets/README.md).
30
+
@@ -0,0 +1,21 @@
1
+ # anonymize
2
+
3
+ Remove personal style, references, and formatting from text to conceal the original author. The chain runs through your configured LLM models, so it works with fully private or self‑hosted LLMs.
4
+
5
+ Supported methods: `STRICT`, `BALANCED`, and `LIGHT` to control how aggressively style is removed.
6
+
7
+
8
+ ```javascript
9
+ import anonymize, { anonymizeMethod } from './index.js';
10
+
11
+ const message = `As a software lead in Chicago, I've found our new UI framework helps junior devs ramp up fast.`;
12
+
13
+ const { text } = await anonymize({
14
+ text: message,
15
+ method: anonymizeMethod.STRICT,
16
+ });
17
+
18
+ console.log(text);
19
+ // => "The new UI framework shortens the learning curve for new developers."
20
+ ```
21
+