@far-world-labs/verblets 0.1.1 → 0.1.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 (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 +117 -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 +671 -0
  11. package/eslint.config.js +80 -0
  12. package/package.json +28 -16
  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 +3 -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 +21 -41
  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 +4 -4
  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 +11 -16
  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 +84 -1
  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
@@ -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,6 +1,6 @@
1
1
  {
2
2
  "name": "@far-world-labs/verblets",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "OpenAI Client",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -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
+
@@ -0,0 +1,75 @@
1
+ import { describe, it } from 'vitest';
2
+ import { expect } from 'chai';
3
+ import { anonymize, anonymizeMethod } from './index.js';
4
+
5
+ const sampleText = `As a seasoned engineer from Silicon Valley, I've found that React's
6
+ component lifecycle is like a well-oiled machine - understanding the mounting
7
+ phase is crucial, especially with those pesky useEffect hooks. Trust me, after
8
+ 10 years of experience, proper cleanup is key to avoiding memory leaks!`;
9
+
10
+ describe('anonymize examples', () => {
11
+ it.only('should anonymize text using strict method', { timeout: 60_000 }, async () => {
12
+ const input = {
13
+ text: sampleText,
14
+ method: anonymizeMethod.STRICT,
15
+ };
16
+
17
+ const result = await anonymize(input);
18
+
19
+ expect(result).to.have.property('text');
20
+ expect(result).to.have.property('stages');
21
+ expect(result.stages).to.have.property('distinctiveContentRemoved');
22
+ expect(result.stages).to.have.property('structureNormalized');
23
+ expect(result.stages).to.have.property('patternsSuppressed');
24
+
25
+ // Verify anonymization removed personal markers
26
+ expect(result.text).to.not.include('Silicon Valley');
27
+ expect(result.text).to.not.include('10 years of experience');
28
+ expect(result.text).to.not.include('Trust me');
29
+
30
+ // Verify metaphors and idioms are removed
31
+ expect(result.text).to.not.include('well-oiled machine');
32
+ expect(result.text).to.not.include('pesky');
33
+
34
+ // Verify the text has been transformed
35
+ expect(result.text).to.not.equal(sampleText);
36
+ expect(result.text.length).to.be.lessThan(sampleText.length);
37
+ });
38
+
39
+ it('should preserve more content with balanced method', { timeout: 60_000 }, async () => {
40
+ const input = {
41
+ text: sampleText,
42
+ method: anonymizeMethod.BALANCED,
43
+ };
44
+
45
+ const result = await anonymize(input);
46
+
47
+ // Verify some personal markers are still removed
48
+ expect(result.text).to.not.include('Silicon Valley');
49
+ expect(result.text).to.not.include('Trust me');
50
+
51
+ // But technical content is more preserved
52
+ expect(result.text.length).to.be.greaterThan(
53
+ (await anonymize({ text: sampleText, method: anonymizeMethod.STRICT })).text.length
54
+ );
55
+ });
56
+
57
+ it('should minimally transform text with light method', { timeout: 60_000 }, async () => {
58
+ const input = {
59
+ text: sampleText,
60
+ method: anonymizeMethod.LIGHT,
61
+ };
62
+
63
+ const result = await anonymize(input);
64
+
65
+ // Verify minimal transformation
66
+ expect(result.text.length).to.be.greaterThan(
67
+ (await anonymize({ text: sampleText, method: anonymizeMethod.BALANCED })).text.length
68
+ );
69
+
70
+ // Only the most obvious personal markers should be removed
71
+ expect(result.text).to.not.include('Trust me');
72
+
73
+ expect(result.text).to.not.include("I've found");
74
+ });
75
+ });
@@ -0,0 +1,121 @@
1
+ import { run } from '../../lib/chatgpt/index.js';
2
+
3
+ export const anonymizeMethod = {
4
+ STRICT: 'strict',
5
+ BALANCED: 'balanced',
6
+ LIGHT: 'light',
7
+ };
8
+
9
+ const METHODS = Object.values(anonymizeMethod);
10
+
11
+ const validateInput = (input) => {
12
+ if (!input || typeof input !== 'object') {
13
+ throw new Error('Input must be an object');
14
+ }
15
+
16
+ const { text, method, context } = input;
17
+
18
+ if (!text || typeof text !== 'string') {
19
+ throw new Error('Input must include a text string');
20
+ }
21
+
22
+ if (!method || !METHODS.includes(method)) {
23
+ throw new Error(`Method must be one of: ${METHODS.join(', ')}`);
24
+ }
25
+
26
+ if (context !== undefined && typeof context !== 'string') {
27
+ throw new Error('Context must be a string if provided');
28
+ }
29
+
30
+ return { text, method, context };
31
+ };
32
+
33
+ const stage1Prompt = (text, context) => `
34
+ Remove Distinctive Content and Markers
35
+ - Identify and replace every distinctive or uncommon word, phrase, or sentence structure with the most widely used, nondescript alternative.
36
+ - Remove all idioms, metaphors, analogies, cultural references, personal perspectives, and subjective tones.
37
+ - Eliminate any explicit or implicit references to the author's identity, background, education, expertise, region, or intent.
38
+
39
+ ${context ? `Context: ${context}\n` : ''}
40
+ Text to process:
41
+ ${text}
42
+
43
+ Return ONLY the processed text, with no explanations or additional content.`;
44
+
45
+ const stage2Prompt = (text, context) => `
46
+ Normalize Structure, Formatting, and Tone
47
+ - Restructure sentences and paragraphs to strictly follow standard, average patterns in length, order, and construction. Avoid any distinctive rhythm, complexity, or flow.
48
+ - Uniformly normalize punctuation, formatting, and paragraphing; avoid any variation or emphasis that could signal style.
49
+ - Strip out all emotional, evaluative, or expressive language, enforcing a neutral, impersonal, and objective tone.
50
+
51
+ ${context ? `Context: ${context}\n` : ''}
52
+ Text to process:
53
+ ${text}
54
+
55
+ Return ONLY the normalized text, with no explanations or additional content.`;
56
+
57
+ const stage3Prompt = (text, context) => `
58
+ Stage 3: Suppress Latent Stylistic Patterns
59
+ - Review for and suppress any recurring linguistic patterns, syntactic habits, or structural quirks—even if they appear common.
60
+ - For all possible ways to phrase content, always select the plainest, most generic, and least distinctive form.
61
+ - Ensure the final text reads as if generated by an automated system, with no evidence of personality, emotion, region, or any unique authorial traits.
62
+
63
+ ${context ? `Context: ${context}\n` : ''}
64
+ Text to process:
65
+ ${text}
66
+
67
+ Return ONLY the final anonymized text, with no explanations or additional content.`;
68
+
69
+ const anonymize = async (input, config = {}) => {
70
+ const { text, method, context } = validateInput(input);
71
+ const { llm, ...options } = config;
72
+
73
+ // Stage 1: Remove distinctive content
74
+ const stage1Result = await run(stage1Prompt(text, method, context), {
75
+ modelOptions: { modelName: 'privacy', ...llm },
76
+ ...options,
77
+ });
78
+
79
+ if (method === anonymizeMethod.LIGHT) {
80
+ return {
81
+ text: stage1Result,
82
+ stages: {
83
+ distinctiveContentRemoved: stage1Result,
84
+ },
85
+ };
86
+ }
87
+
88
+ // Stage 2: Normalize structure and tone
89
+ const stage2Result = await run(stage2Prompt(stage1Result, method), {
90
+ modelOptions: { modelName: 'privacy', ...llm },
91
+ ...options,
92
+ });
93
+
94
+ if (method === anonymizeMethod.BALANCED) {
95
+ return {
96
+ text: stage2Result,
97
+ stages: {
98
+ distinctiveContentRemoved: stage1Result,
99
+ structureNormalized: stage2Result,
100
+ },
101
+ };
102
+ }
103
+
104
+ // Stage 3: Suppress stylistic patterns
105
+ const stage3Result = await run(stage3Prompt(stage2Result, method), {
106
+ modelOptions: { modelName: 'privacy', ...llm },
107
+ ...options,
108
+ });
109
+
110
+ return {
111
+ text: stage3Result,
112
+ stages: {
113
+ distinctiveContentRemoved: stage1Result,
114
+ structureNormalized: stage2Result,
115
+ patternsSuppressed: stage3Result,
116
+ },
117
+ };
118
+ };
119
+
120
+ export { anonymize };
121
+ export default anonymize;