@far-world-labs/verblets 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (330) hide show
  1. package/README.md +98 -213
  2. package/dist/index.browser.js +221 -0
  3. package/dist/index.js +696 -0
  4. package/dist/shared-CMgpfDG4.js +10714 -0
  5. package/package.json +38 -15
  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 -12
  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/clear-redis.js +0 -74
  21. package/scripts/generate-chain/index.js +0 -111
  22. package/scripts/generate-lib/index.js +0 -68
  23. package/scripts/generate-test/index.js +0 -137
  24. package/scripts/generate-verblet/README.md +0 -17
  25. package/scripts/generate-verblet/index.js +0 -110
  26. package/scripts/run.sh +0 -15
  27. package/scripts/runner/index.js +0 -56
  28. package/scripts/simple-editor/README.md +0 -34
  29. package/scripts/simple-editor/index.js +0 -79
  30. package/scripts/summarize-files/index.js +0 -70
  31. package/src/chains/README.md +0 -30
  32. package/src/chains/anonymize/README.md +0 -21
  33. package/src/chains/anonymize/index.examples.js +0 -75
  34. package/src/chains/anonymize/index.js +0 -121
  35. package/src/chains/anonymize/index.spec.js +0 -78
  36. package/src/chains/bulk-central-tendency/index.examples.js +0 -138
  37. package/src/chains/bulk-central-tendency/index.js +0 -91
  38. package/src/chains/bulk-filter/README.md +0 -21
  39. package/src/chains/bulk-filter/index.examples.js +0 -22
  40. package/src/chains/bulk-filter/index.js +0 -58
  41. package/src/chains/bulk-filter/index.spec.js +0 -38
  42. package/src/chains/bulk-find/README.md +0 -16
  43. package/src/chains/bulk-find/index.examples.js +0 -20
  44. package/src/chains/bulk-find/index.js +0 -30
  45. package/src/chains/bulk-find/index.spec.js +0 -26
  46. package/src/chains/bulk-group/README.md +0 -23
  47. package/src/chains/bulk-group/index.examples.js +0 -18
  48. package/src/chains/bulk-group/index.js +0 -34
  49. package/src/chains/bulk-group/index.spec.js +0 -41
  50. package/src/chains/bulk-map/README.md +0 -43
  51. package/src/chains/bulk-map/index.examples.js +0 -17
  52. package/src/chains/bulk-map/index.js +0 -86
  53. package/src/chains/bulk-map/index.spec.js +0 -44
  54. package/src/chains/bulk-reduce/README.md +0 -12
  55. package/src/chains/bulk-reduce/index.examples.js +0 -15
  56. package/src/chains/bulk-reduce/index.js +0 -13
  57. package/src/chains/bulk-reduce/index.spec.js +0 -25
  58. package/src/chains/bulk-score/README.md +0 -16
  59. package/src/chains/bulk-score/bulk-score-result.json +0 -18
  60. package/src/chains/bulk-score/index.examples.js +0 -22
  61. package/src/chains/bulk-score/index.js +0 -133
  62. package/src/chains/bulk-score/index.spec.js +0 -30
  63. package/src/chains/category-samples/README.md +0 -61
  64. package/src/chains/category-samples/index.examples.js +0 -103
  65. package/src/chains/category-samples/index.js +0 -134
  66. package/src/chains/collect-terms/README.md +0 -12
  67. package/src/chains/collect-terms/index.examples.js +0 -16
  68. package/src/chains/collect-terms/index.js +0 -44
  69. package/src/chains/collect-terms/index.spec.js +0 -25
  70. package/src/chains/conversation/README.md +0 -26
  71. package/src/chains/conversation/index.examples.js +0 -398
  72. package/src/chains/conversation/index.js +0 -126
  73. package/src/chains/conversation/index.spec.js +0 -148
  74. package/src/chains/conversation/turn-policies.js +0 -93
  75. package/src/chains/conversation/turn-policies.md +0 -123
  76. package/src/chains/conversation/turn-policies.spec.js +0 -135
  77. package/src/chains/date/README.md +0 -12
  78. package/src/chains/date/index.examples.js +0 -47
  79. package/src/chains/date/index.js +0 -74
  80. package/src/chains/date/index.spec.js +0 -62
  81. package/src/chains/disambiguate/README.md +0 -22
  82. package/src/chains/disambiguate/disambiguate-meanings-result.json +0 -16
  83. package/src/chains/disambiguate/index.examples.js +0 -18
  84. package/src/chains/disambiguate/index.js +0 -92
  85. package/src/chains/disambiguate/index.spec.js +0 -25
  86. package/src/chains/dismantle/README.md +0 -67
  87. package/src/chains/dismantle/dismantle.examples.js +0 -27
  88. package/src/chains/dismantle/index.examples.js +0 -30
  89. package/src/chains/dismantle/index.js +0 -303
  90. package/src/chains/dismantle/index.spec.js +0 -32
  91. package/src/chains/expect/README.md +0 -171
  92. package/src/chains/expect/index.examples.js +0 -146
  93. package/src/chains/expect/index.js +0 -207
  94. package/src/chains/expect/index.spec.js +0 -324
  95. package/src/chains/filter-ambiguous/README.md +0 -11
  96. package/src/chains/filter-ambiguous/index.examples.js +0 -20
  97. package/src/chains/filter-ambiguous/index.js +0 -49
  98. package/src/chains/filter-ambiguous/index.spec.js +0 -31
  99. package/src/chains/glossary/README.md +0 -19
  100. package/src/chains/glossary/index.examples.js +0 -386
  101. package/src/chains/glossary/index.js +0 -75
  102. package/src/chains/glossary/index.spec.js +0 -19
  103. package/src/chains/intersections/README.md +0 -166
  104. package/src/chains/intersections/index.examples.js +0 -280
  105. package/src/chains/intersections/index.js +0 -218
  106. package/src/chains/intersections/intersection-result.json +0 -38
  107. package/src/chains/list/index.examples.js +0 -68
  108. package/src/chains/list/index.js +0 -214
  109. package/src/chains/list/index.spec.js +0 -67
  110. package/src/chains/list/list-result.json +0 -16
  111. package/src/chains/list/schema.json +0 -24
  112. package/src/chains/llm-logger/README.md +0 -366
  113. package/src/chains/llm-logger/index.js +0 -591
  114. package/src/chains/llm-logger/index.spec.js +0 -391
  115. package/src/chains/llm-logger/schema.json +0 -105
  116. package/src/chains/questions/index.examples.js +0 -69
  117. package/src/chains/questions/index.js +0 -135
  118. package/src/chains/questions/index.spec.js +0 -29
  119. package/src/chains/scan-js/index.js +0 -116
  120. package/src/chains/set-interval/README.md +0 -81
  121. package/src/chains/set-interval/index.examples.js +0 -64
  122. package/src/chains/set-interval/index.js +0 -152
  123. package/src/chains/set-interval/index.spec.js +0 -70
  124. package/src/chains/socratic/README.md +0 -17
  125. package/src/chains/socratic/index.js +0 -64
  126. package/src/chains/socratic/index.spec.js +0 -24
  127. package/src/chains/sort/index.examples.js +0 -36
  128. package/src/chains/sort/index.js +0 -163
  129. package/src/chains/sort/index.spec.js +0 -112
  130. package/src/chains/sort/sort-result.json +0 -16
  131. package/src/chains/summary-map/README.md +0 -41
  132. package/src/chains/summary-map/index.examples.js +0 -64
  133. package/src/chains/summary-map/index.js +0 -226
  134. package/src/chains/summary-map/index.spec.js +0 -153
  135. package/src/chains/test/index.js +0 -114
  136. package/src/chains/test-advice/index.js +0 -35
  137. package/src/chains/themes/README.md +0 -20
  138. package/src/chains/themes/index.examples.js +0 -17
  139. package/src/chains/themes/index.js +0 -28
  140. package/src/chains/themes/index.spec.js +0 -19
  141. package/src/chains/veiled-variants/index.examples.js +0 -18
  142. package/src/chains/veiled-variants/index.js +0 -107
  143. package/src/chains/veiled-variants/index.spec.js +0 -40
  144. package/src/constants/common.js +0 -13
  145. package/src/constants/messages.js +0 -3
  146. package/src/constants/models.js +0 -184
  147. package/src/index.js +0 -203
  148. package/src/json-schemas/README.md +0 -13
  149. package/src/json-schemas/cars-test.json +0 -11
  150. package/src/json-schemas/index.js +0 -12
  151. package/src/json-schemas/intent.json +0 -38
  152. package/src/json-schemas/schema-dot-org-photograph.json +0 -133
  153. package/src/json-schemas/schema-dot-org-place.json +0 -129
  154. package/src/lib/README.md +0 -26
  155. package/src/lib/any-signal/index.js +0 -28
  156. package/src/lib/assert/README.md +0 -84
  157. package/src/lib/assert/index.js +0 -50
  158. package/src/lib/bulk-filter/README.md +0 -22
  159. package/src/lib/bulk-filter/index.examples.js +0 -27
  160. package/src/lib/bulk-filter/index.js +0 -63
  161. package/src/lib/bulk-filter/index.spec.js +0 -38
  162. package/src/lib/bulk-find/README.md +0 -18
  163. package/src/lib/bulk-find/index.examples.js +0 -19
  164. package/src/lib/bulk-find/index.js +0 -30
  165. package/src/lib/bulk-find/index.spec.js +0 -41
  166. package/src/lib/chatgpt/index.js +0 -163
  167. package/src/lib/combinations/index.js +0 -30
  168. package/src/lib/combinations/index.spec.js +0 -23
  169. package/src/lib/editor/index.js +0 -31
  170. package/src/lib/functional/index.js +0 -28
  171. package/src/lib/logger-service/index.js +0 -32
  172. package/src/lib/parse-js-parts/index.js +0 -321
  173. package/src/lib/parse-js-parts/index.spec.js +0 -156
  174. package/src/lib/parse-llm-list/README.md +0 -39
  175. package/src/lib/parse-llm-list/index.js +0 -54
  176. package/src/lib/parse-llm-list/index.spec.js +0 -59
  177. package/src/lib/path-aliases/index.js +0 -37
  178. package/src/lib/path-aliases/index.spec.js +0 -64
  179. package/src/lib/pave/index.js +0 -34
  180. package/src/lib/pave/index.spec.js +0 -76
  181. package/src/lib/prompt-cache/index.js +0 -50
  182. package/src/lib/retry/index.js +0 -66
  183. package/src/lib/retry/index.spec.js +0 -86
  184. package/src/lib/ring-buffer/README.md +0 -82
  185. package/src/lib/ring-buffer/index.js +0 -235
  186. package/src/lib/ring-buffer/index.spec.js +0 -388
  187. package/src/lib/search-best-first/city-walk.spec.js +0 -37
  188. package/src/lib/search-best-first/index.js +0 -97
  189. package/src/lib/search-best-first/index.spec.js +0 -35
  190. package/src/lib/search-js-files/code-features-property-definitions.json +0 -123
  191. package/src/lib/search-js-files/index.examples.js +0 -22
  192. package/src/lib/search-js-files/index.js +0 -155
  193. package/src/lib/search-js-files/index.spec.js +0 -34
  194. package/src/lib/search-js-files/scan-file.js +0 -242
  195. package/src/lib/shorten-text/index.js +0 -25
  196. package/src/lib/shorten-text/index.spec.js +0 -68
  197. package/src/lib/strip-numeric/index.js +0 -5
  198. package/src/lib/strip-response/index.js +0 -30
  199. package/src/lib/template-replace/index.js +0 -23
  200. package/src/lib/template-replace/index.spec.js +0 -60
  201. package/src/lib/timed-abort-controller/index.js +0 -41
  202. package/src/lib/to-bool/index.js +0 -8
  203. package/src/lib/to-date/index.js +0 -11
  204. package/src/lib/to-enum/index.js +0 -14
  205. package/src/lib/to-number/index.js +0 -12
  206. package/src/lib/to-number-with-units/index.js +0 -51
  207. package/src/lib/transcribe/index.js +0 -78
  208. package/src/prompts/README.md +0 -17
  209. package/src/prompts/as-enum.js +0 -5
  210. package/src/prompts/as-json-schema.js +0 -9
  211. package/src/prompts/as-object-with-schema.js +0 -26
  212. package/src/prompts/as-schema-org-text.js +0 -25
  213. package/src/prompts/as-schema-org-type.js +0 -1
  214. package/src/prompts/blog-post.js +0 -7
  215. package/src/prompts/code-features.js +0 -24
  216. package/src/prompts/constants.js +0 -101
  217. package/src/prompts/features-json-schema.js +0 -27
  218. package/src/prompts/generate-collection.js +0 -26
  219. package/src/prompts/generate-list.js +0 -48
  220. package/src/prompts/generate-questions.js +0 -19
  221. package/src/prompts/index.js +0 -20
  222. package/src/prompts/intent.js +0 -60
  223. package/src/prompts/output-succinct-names.js +0 -3
  224. package/src/prompts/select-from-threshold.js +0 -17
  225. package/src/prompts/sort.js +0 -31
  226. package/src/prompts/style.js +0 -38
  227. package/src/prompts/summarize.js +0 -13
  228. package/src/prompts/token-budget.js +0 -3
  229. package/src/prompts/wrap-list.js +0 -11
  230. package/src/prompts/wrap-variable.js +0 -36
  231. package/src/services/llm-model/global-overrides.spec.js +0 -432
  232. package/src/services/llm-model/index.js +0 -308
  233. package/src/services/llm-model/model.js +0 -21
  234. package/src/services/llm-model/negotiate.spec.js +0 -447
  235. package/src/services/redis/index.js +0 -147
  236. package/src/test/setup.js +0 -20
  237. package/src/verblets/README.md +0 -26
  238. package/src/verblets/auto/index.examples.js +0 -31
  239. package/src/verblets/auto/index.js +0 -28
  240. package/src/verblets/auto/index.spec.js +0 -32
  241. package/src/verblets/bool/README.md +0 -36
  242. package/src/verblets/bool/index.examples.js +0 -80
  243. package/src/verblets/bool/index.js +0 -25
  244. package/src/verblets/bool/index.schema.json +0 -14
  245. package/src/verblets/bool/index.spec.js +0 -33
  246. package/src/verblets/central-tendency/README.md +0 -166
  247. package/src/verblets/central-tendency/central-tendency-result.json +0 -24
  248. package/src/verblets/central-tendency/index.examples.js +0 -196
  249. package/src/verblets/central-tendency/index.js +0 -171
  250. package/src/verblets/central-tendency/index.spec.js +0 -148
  251. package/src/verblets/conversation-turn/README.md +0 -33
  252. package/src/verblets/conversation-turn/index.examples.js +0 -218
  253. package/src/verblets/conversation-turn/index.js +0 -68
  254. package/src/verblets/conversation-turn/index.spec.js +0 -77
  255. package/src/verblets/conversation-turn-multi/README.md +0 -31
  256. package/src/verblets/conversation-turn-multi/index.examples.js +0 -160
  257. package/src/verblets/conversation-turn-multi/index.js +0 -104
  258. package/src/verblets/conversation-turn-multi/index.spec.js +0 -63
  259. package/src/verblets/enum/index.examples.js +0 -30
  260. package/src/verblets/enum/index.js +0 -18
  261. package/src/verblets/enum/index.spec.js +0 -35
  262. package/src/verblets/expect/README.md +0 -64
  263. package/src/verblets/expect/index.examples.js +0 -109
  264. package/src/verblets/expect/index.js +0 -75
  265. package/src/verblets/expect/index.spec.js +0 -127
  266. package/src/verblets/intent/index.examples.js +0 -139
  267. package/src/verblets/intent/index.js +0 -60
  268. package/src/verblets/intent/index.spec.js +0 -31
  269. package/src/verblets/intersection/README.md +0 -16
  270. package/src/verblets/intersection/index.examples.js +0 -89
  271. package/src/verblets/intersection/index.js +0 -125
  272. package/src/verblets/intersection/index.spec.js +0 -60
  273. package/src/verblets/intersection/intersection-result.json +0 -16
  274. package/src/verblets/list-expand/README.md +0 -10
  275. package/src/verblets/list-expand/index.examples.js +0 -14
  276. package/src/verblets/list-expand/index.js +0 -104
  277. package/src/verblets/list-expand/index.spec.js +0 -18
  278. package/src/verblets/list-expand/list-expand-result.json +0 -16
  279. package/src/verblets/list-filter/README.md +0 -22
  280. package/src/verblets/list-filter/index.examples.js +0 -26
  281. package/src/verblets/list-filter/index.js +0 -18
  282. package/src/verblets/list-filter/index.spec.js +0 -19
  283. package/src/verblets/list-find/README.md +0 -11
  284. package/src/verblets/list-find/index.examples.js +0 -15
  285. package/src/verblets/list-find/index.js +0 -17
  286. package/src/verblets/list-find/index.spec.js +0 -19
  287. package/src/verblets/list-group/README.md +0 -16
  288. package/src/verblets/list-group/index.examples.js +0 -16
  289. package/src/verblets/list-group/index.js +0 -112
  290. package/src/verblets/list-group/index.spec.js +0 -35
  291. package/src/verblets/list-group/list-group-result.json +0 -16
  292. package/src/verblets/list-map/README.md +0 -11
  293. package/src/verblets/list-map/index.examples.js +0 -15
  294. package/src/verblets/list-map/index.js +0 -26
  295. package/src/verblets/list-map/index.spec.js +0 -17
  296. package/src/verblets/list-reduce/README.md +0 -10
  297. package/src/verblets/list-reduce/index.examples.js +0 -14
  298. package/src/verblets/list-reduce/index.js +0 -21
  299. package/src/verblets/list-reduce/index.spec.js +0 -27
  300. package/src/verblets/list-reduce/index.spec.jsx +0 -27
  301. package/src/verblets/name/README.md +0 -15
  302. package/src/verblets/name/index.examples.js +0 -28
  303. package/src/verblets/name/index.js +0 -19
  304. package/src/verblets/name/index.spec.js +0 -33
  305. package/src/verblets/name-similar-to/README.md +0 -26
  306. package/src/verblets/name-similar-to/index.examples.js +0 -18
  307. package/src/verblets/name-similar-to/index.js +0 -20
  308. package/src/verblets/name-similar-to/index.spec.js +0 -13
  309. package/src/verblets/number/index.examples.js +0 -199
  310. package/src/verblets/number/index.js +0 -25
  311. package/src/verblets/number/index.spec.js +0 -33
  312. package/src/verblets/number-with-units/index.examples.js +0 -38
  313. package/src/verblets/number-with-units/index.js +0 -84
  314. package/src/verblets/number-with-units/index.spec.js +0 -46
  315. package/src/verblets/number-with-units/number-with-units-result.json +0 -23
  316. package/src/verblets/people-list/README.md +0 -28
  317. package/src/verblets/people-list/index.examples.js +0 -184
  318. package/src/verblets/people-list/index.js +0 -44
  319. package/src/verblets/people-list/index.spec.js +0 -49
  320. package/src/verblets/schema-org/index.examples.js +0 -51
  321. package/src/verblets/schema-org/index.js +0 -37
  322. package/src/verblets/schema-org/index.spec.js +0 -39
  323. package/src/verblets/sentiment/README.md +0 -10
  324. package/src/verblets/sentiment/index.examples.js +0 -20
  325. package/src/verblets/sentiment/index.js +0 -9
  326. package/src/verblets/sentiment/index.spec.js +0 -20
  327. package/src/verblets/to-object/README.md +0 -38
  328. package/src/verblets/to-object/index.examples.js +0 -29
  329. package/src/verblets/to-object/index.js +0 -131
  330. package/src/verblets/to-object/index.spec.js +0 -71
@@ -1,153 +0,0 @@
1
- import { describe, expect, it, vi } from 'vitest';
2
- import pave from '../../lib/pave/index.js';
3
- import SummaryMap from './index.js';
4
- import chatGPT from '../../lib/chatgpt/index.js';
5
-
6
- vi.mock('../../services/llm-model/index.js', () => ({
7
- default: {
8
- negotiateModel: vi.fn().mockReturnValue('fastGood'),
9
- getBestPublicModel: vi.fn().mockReturnValue({
10
- name: 'fastGood',
11
- tokenizer: (text) => text.split(' '),
12
- maxContextWindow: 128000,
13
- maxOutputTokens: 16384,
14
- toTokens(text) {
15
- return this.tokenizer(text);
16
- },
17
- budgetTokens(text, { completionMax = Infinity } = {}) {
18
- const prompt = this.toTokens(text).length;
19
- const total = this.maxContextWindow;
20
- const completion = Math.min(Math.min(total - prompt, this.maxOutputTokens), completionMax);
21
- return {
22
- completion,
23
- prompt,
24
- total,
25
- };
26
- },
27
- }),
28
- getModel: vi.fn().mockReturnValue({
29
- name: 'fastGood',
30
- tokenizer: (text) => text.split(' '),
31
- maxContextWindow: 128000,
32
- maxOutputTokens: 16384,
33
- toTokens(text) {
34
- return this.tokenizer(text);
35
- },
36
- budgetTokens(text, { completionMax = Infinity } = {}) {
37
- const prompt = this.toTokens(text).length;
38
- const total = this.maxContextWindow;
39
- const completion = Math.min(Math.min(total - prompt, this.maxOutputTokens), completionMax);
40
- return {
41
- completion,
42
- prompt,
43
- total,
44
- };
45
- },
46
- }),
47
- },
48
- }));
49
-
50
- vi.mock('../../lib/chatgpt/index.js', () => ({
51
- default: vi.fn().mockImplementation((text) => {
52
- if (/Pursuant to the adjudication/.test(text)) {
53
- return '01234567890123456789012345678901234567890123456789';
54
- }
55
- if (/rabin_karp_search/.test(text)) {
56
- return '0123456789012345678901234';
57
- }
58
- return 'undefined';
59
- }),
60
- }));
61
-
62
- const legalText =
63
- 'Pursuant to the adjudication of a force majeure clause within the context of contractual';
64
-
65
- const codeText = `import numpy as np
66
-
67
- def rabin_karp_search(pattern, text, prime=101):
68
- `;
69
-
70
- const examples = [
71
- {
72
- name: 'Basic usage',
73
- inputs: {
74
- targetTokens: 100,
75
- keys: [
76
- { key: 'example.text', value: legalText, weight: 1, type: 'text' },
77
- { key: 'example.code', value: codeText, weight: 0.5, type: 'code' },
78
- ],
79
- },
80
- wants: [
81
- { key: 'example.text', resultLength: 50, budget: [60, 80] },
82
- { key: 'example.code', resultLength: 25, budget: [20, 40] },
83
- ],
84
- },
85
- {
86
- name: 'Model options and privacy',
87
- inputs: {
88
- targetTokens: 50,
89
- modelOptions: { modelName: 'fastGood' },
90
- keys: [
91
- {
92
- key: 'example.text',
93
- value: legalText,
94
- weight: 1,
95
- type: 'text',
96
- privacy: { blacklist: 'names' },
97
- },
98
- { key: 'example.code', value: codeText, weight: 0.5, type: 'code' },
99
- ],
100
- },
101
- wants: [
102
- { key: 'example.text', resultLength: 50 },
103
- { key: 'example.code', resultLength: 25 },
104
- ],
105
- },
106
- ];
107
-
108
- describe('Summary map', () => {
109
- examples.forEach((example) => {
110
- it(example.name, async () => {
111
- vi.clearAllMocks();
112
- const map = new SummaryMap({
113
- targetTokens: example.inputs.targetTokens,
114
- ...(example.inputs.modelOptions && { modelOptions: example.inputs.modelOptions }),
115
- });
116
-
117
- for (const input of example.inputs.keys) {
118
- map.set(input.key, input);
119
- }
120
-
121
- const entries = Array.from(await map.entries());
122
- const result = entries.reduce((acc, [k, v]) => pave(acc, k, v), {});
123
-
124
- for (const want of example.wants) {
125
- let value = result;
126
-
127
- // Navigate the result object using the key segments
128
- for (const keySegment of want.key.split('.')) {
129
- value = value[keySegment];
130
- }
131
-
132
- expect(typeof value).toBe('string');
133
-
134
- // Check if the length of the value is within the expected range
135
- expect(value.length).toBeLessThanOrEqual(want.resultLength);
136
-
137
- if (want.budget) {
138
- const { budgets } = map.calculateBudgets();
139
- const found = budgets.find((b) => b.key === want.key);
140
- expect(found.budget).gt(want.budget[0]);
141
- expect(found.budget).lt(want.budget[1]);
142
- }
143
- }
144
-
145
- if (example.name === 'Model options and privacy') {
146
- const callWithPrivacy = chatGPT.mock.calls.find(
147
- (c) => c[1]?.modelOptions?.modelName === 'privacy'
148
- );
149
- expect(callWithPrivacy).toBeTruthy();
150
- }
151
- });
152
- });
153
- });
@@ -1,114 +0,0 @@
1
- import fs from 'node:fs/promises';
2
- import path from 'node:path';
3
-
4
- import { errorRunningTests } from '../../constants/messages.js';
5
- import chatGPT from '../../lib/chatgpt/index.js';
6
- import { constants as promptConstants, wrapVariable } from '../../prompts/index.js';
7
- import modelService from '../../services/llm-model/index.js';
8
- import toObject from '../../verblets/to-object/index.js';
9
-
10
- const {
11
- contentIsExample,
12
- contentIsInstructions,
13
- noFalseInformation,
14
- onlyJSONArray,
15
- onlyJSONStringArray,
16
- useLineNumber,
17
- } = promptConstants;
18
-
19
- const contentIsChecksExamined = 'These items were checked in an examination of the text:';
20
- const contentIsExamined = 'The text examined:';
21
- const findCodeImprovements = 'Find specific improvements in the following code, not nitpicks.';
22
- const gatherAsTestJSON =
23
- 'Gather these discovered issues into a JSON format my tests module can consume.';
24
-
25
- const testExamplesJSON = `[
26
- {
27
- name: '<copied from the supplied checks>',
28
- expected: '<what you expected to see, your rationale for the change, give suggestions here, abbreviate to < 100 characters>',
29
- saw: '<what you saw, being specific about where you see it, abbreviate to < 100 characters>',
30
- isSuccess: false,
31
- },
32
- {
33
- name: '<copied from the supplied checks>',
34
- expected: '<what you expected to see, your rationale for the change, give suggestions here, abbreviate to < 100 characters>',
35
- saw: '<what you saw, being specific about where you see it, abbreviate to < 100 characters>',
36
- isSuccess: true,
37
- },
38
- <many more>
39
- ]`;
40
-
41
- const checksPrompt = (text, instructions) => `
42
- ${contentIsInstructions} ${wrapVariable(instructions)}
43
-
44
- ${wrapVariable(text, { tag: 'main-content' })}
45
-
46
- ${useLineNumber}
47
- ${noFalseInformation}
48
-
49
- ${onlyJSONStringArray}
50
- `;
51
-
52
- const testsPrompt = (text, instructions, checks) => `${onlyJSONArray}
53
-
54
- ${gatherAsTestJSON}
55
-
56
- ${contentIsChecksExamined} ${wrapVariable(checks)}
57
-
58
- ${contentIsExamined} ${wrapVariable(text, { tag: 'text-examined' })}
59
-
60
- ${contentIsExample} ${wrapVariable(testExamplesJSON, { tag: 'example' })}
61
-
62
- ${onlyJSONArray}
63
- `;
64
-
65
- export default async (filePath, instructions = findCodeImprovements, config = {}) => {
66
- const { model = modelService.getBestPublicModel(), llm, ...options } = config;
67
- const enableRegex = new RegExp(process.env.ENABLE_AI_TESTS ?? '^$');
68
- if (!enableRegex.test(filePath)) {
69
- return [];
70
- }
71
-
72
- try {
73
- const filePathAbsolute = path.resolve(filePath);
74
- const text = await fs.readFile(filePathAbsolute, 'utf-8');
75
-
76
- const checksPromptCreated = checksPrompt(text, instructions);
77
- const checksBudget = model.budgetTokens(checksPromptCreated);
78
-
79
- const checksResult = await chatGPT(checksPromptCreated, {
80
- modelOptions: {
81
- maxTokens: checksBudget.completion,
82
- ...llm,
83
- },
84
- ...options,
85
- });
86
-
87
- const testsPromptCreated = testsPrompt(text, instructions, checksResult);
88
- const testsBudget = model.budgetTokens(testsPromptCreated);
89
-
90
- const results = await toObject(
91
- await chatGPT(testsPromptCreated, {
92
- modelOptions: {
93
- maxTokens: testsBudget.completion,
94
- ...llm,
95
- },
96
- ...options,
97
- })
98
- );
99
-
100
- if (!results.length) {
101
- return [];
102
- }
103
-
104
- return results;
105
- } catch (error) {
106
- return [
107
- {
108
- name: errorRunningTests,
109
- expected: 'tests generated',
110
- saw: error.message,
111
- },
112
- ];
113
- }
114
- };
@@ -1,35 +0,0 @@
1
- import test from '../test/index.js';
2
-
3
- const boundaryIssues = 'Run the code with 5 boundary value test cases and report any that fail';
4
-
5
- const successIssues =
6
- 'Identify 5 passing scenarios and significant boundary conditions in this code. Provide minimal input examples for each scenario to demonstrate correctness.';
7
-
8
- const failureIssues =
9
- "Identify 5 failing scenarios and significant boundary conditions in this code. Provide minimal input examples for each scenario to demonstrate the failure. Assume DBC, and don't complain when types are specified in jsDoc.";
10
-
11
- const defectIssues =
12
- 'Identify 5 defects in this code. Provide minimal input examples to demonstrate each defect.';
13
-
14
- const bestPracticesIssues = 'Suggest 5 best practices improvements for this code.';
15
-
16
- const cleanCodeIssues = 'Suggest 5 "clean code" improvements for this code.';
17
-
18
- const qualityIssues =
19
- 'Identify 5 specific issues related to code quality, readability, and maintainability.';
20
-
21
- const refactorIssues =
22
- 'Suggest 5 refactors that would most improve the composibility of this code.';
23
-
24
- export default async (path) => {
25
- return [
26
- ...(await test(path, boundaryIssues)),
27
- ...(await test(path, successIssues)),
28
- ...(await test(path, failureIssues)),
29
- ...(await test(path, defectIssues)),
30
- ...(await test(path, bestPracticesIssues)),
31
- ...(await test(path, cleanCodeIssues)),
32
- ...(await test(path, qualityIssues)),
33
- ...(await test(path, refactorIssues)),
34
- ];
35
- };
@@ -1,20 +0,0 @@
1
- # themes
2
-
3
- Reveal a text's key themes and map them back to the sentences where they appear. The chain first scans fragments in batches to collect possible themes, then runs a consolidation step to normalize and deduplicate them. Optionally it returns a per-sentence map showing which themes surface in each line.
4
-
5
- ```javascript
6
- import themes from './index.js';
7
-
8
- const news = `The storm toppled trees and damaged homes. Volunteers quickly arrived with food and tools. Their kindness inspired hope throughout the town.`;
9
-
10
- const result = await themes(news, { sentenceMap: true });
11
- /* {
12
- * themes: ['disaster recovery', 'community', 'hope'],
13
- * sentenceThemes: [
14
- * [0, ['disaster recovery']],
15
- * [44, ['community']],
16
- * [114, ['hope']]
17
- * ]
18
- */
19
- ```
20
-
@@ -1,17 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import themes from './index.js';
3
- import { longTestTimeout } from '../../constants/common.js';
4
-
5
- describe('themes chain', () => {
6
- it(
7
- 'extracts key themes',
8
- async () => {
9
- const text = `Coffee shops are opening all over town. People love the
10
- new flavors but complain about long lines. Local farmers provide beans while
11
- young entrepreneurs drive innovation.`;
12
- const result = await themes(text, { topN: 2 });
13
- expect(Array.isArray(result)).toBe(true);
14
- },
15
- longTestTimeout
16
- );
17
- });
@@ -1,28 +0,0 @@
1
- import bulkReduce from '../bulk-reduce/index.js';
2
- import shuffle from 'lodash/shuffle.js';
3
-
4
- const splitText = (text) =>
5
- text
6
- .split(/\n{2,}/)
7
- .map((p) => p.trim())
8
- .filter(Boolean);
9
-
10
- export default async function themes(text, config = {}) {
11
- const { chunkSize = 5, topN, llm, ...options } = config;
12
- const pieces = splitText(text);
13
- const reducePrompt =
14
- 'Update the accumulator with short themes from this text. Avoid duplicates. Return ONLY a comma-separated list of themes with no explanation or additional text.';
15
- const firstPass = await bulkReduce(shuffle(pieces), reducePrompt, { chunkSize, llm, ...options });
16
- const rawThemes = firstPass
17
- .split(',')
18
- .map((t) => t.trim())
19
- .filter(Boolean);
20
-
21
- const limitText = topN ? `Limit to the top ${topN} themes.` : 'Return all meaningful themes.';
22
- const refinePrompt = `Refine the accumulator by merging similar themes. ${limitText} Return ONLY a comma-separated list with no explanation or additional text.`;
23
- const final = await bulkReduce(rawThemes, refinePrompt, { chunkSize, llm, ...options });
24
- return final
25
- .split(',')
26
- .map((t) => t.trim())
27
- .filter(Boolean);
28
- }
@@ -1,19 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- import themes from './index.js';
3
- import bulkReduce from '../bulk-reduce/index.js';
4
-
5
- vi.mock('../bulk-reduce/index.js');
6
-
7
- beforeEach(() => {
8
- vi.clearAllMocks();
9
- });
10
-
11
- describe('themes chain', () => {
12
- it('reduces in two passes', async () => {
13
- bulkReduce.mockResolvedValueOnce('a, b, c').mockResolvedValueOnce('a, c');
14
- const text = 'x\n\ny';
15
- const result = await themes(text, { chunkSize: 1, topN: 2 });
16
- expect(result).toStrictEqual(['a', 'c']);
17
- expect(bulkReduce).toHaveBeenCalledTimes(2);
18
- });
19
- });
@@ -1,18 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import veiledVariants from './index.js';
3
- import { longTestTimeout } from '../../constants/common.js';
4
-
5
- describe('veiledVariants example', () => {
6
- it(
7
- 'obscures a sensitive query',
8
- async () => {
9
- const result = await veiledVariants({
10
- prompt:
11
- 'If pigeons are government spies, how do I ask for counter-surveillance tips without sounding paranoid?',
12
- });
13
- expect(Array.isArray(result)).toBe(true);
14
- expect(result.length, `Saw: "${result.join('", "')}"`).toBe(15);
15
- },
16
- longTestTimeout
17
- );
18
- });
@@ -1,107 +0,0 @@
1
- import { run } from '../../lib/chatgpt/index.js';
2
- import { constants as promptConstants, wrapVariable } from '../../prompts/index.js';
3
-
4
- const { onlyJSONStringArray } = promptConstants;
5
-
6
- export const scientificFramingPrompt = (prompt) => `${onlyJSONStringArray}
7
-
8
- Recast the intent as if asked by a scientific researcher. Generate exactly 5 masked alternatives.
9
-
10
- Apply these requirements:
11
- - Replace casual terms with academic phrasing
12
- - Invoke terminology from biology, epidemiology, diagnostics, or public health
13
- - Never use slang, simplifications, or direct synonyms of the original prompt
14
- - Frame each as a legitimate research query
15
- - You MUST generate exactly 5 alternatives. No more, no less.
16
- - Output must be a JSON array of exactly 5 strings
17
-
18
- ${wrapVariable(prompt, { tag: 'intent' })}
19
-
20
- ${onlyJSONStringArray}`;
21
-
22
- export const causalFramePrompt = (prompt) => `${onlyJSONStringArray}
23
-
24
- Generate queries that explore causes, co-conditions, or plausible consequences of the prompt topic. Generate exactly 5 masked alternatives.
25
-
26
- Apply these requirements:
27
- - Focus on surrounding or adjacent issues rather than the central sensitive term
28
- - Frame each as a legitimate research query
29
- - Explore what leads to, accompanies, or results from the topic
30
- - You MUST generate exactly 5 alternatives. No more, no less.
31
- - Output must be a JSON array of exactly 5 strings
32
-
33
- ${wrapVariable(prompt, { tag: 'intent' })}
34
-
35
- ${onlyJSONStringArray}`;
36
-
37
- export const softCoverPrompt = (prompt) => `${onlyJSONStringArray}
38
-
39
- Reframe the prompt as general wellness or diagnostic concerns. Generate exactly 5 masked alternatives.
40
-
41
- Apply these requirements:
42
- - Avoid direct synonyms or sensitive key terms
43
- - Use a clinical and approachable tone that is safe for open searches
44
- - Frame as health, wellness, or general diagnostic queries
45
- - You MUST generate exactly 5 alternatives. No more, no less.
46
- - Output must be a JSON array of exactly 5 strings
47
-
48
- ${wrapVariable(prompt, { tag: 'intent' })}
49
-
50
- ${onlyJSONStringArray}`;
51
-
52
- const veiledVariants = async ({ prompt, modelName = 'privacy' }) => {
53
- const prompts = [
54
- scientificFramingPrompt(prompt),
55
- causalFramePrompt(prompt),
56
- softCoverPrompt(prompt),
57
- ];
58
- const options = { modelOptions: { modelName } };
59
- const results = await Promise.all(prompts.map((p) => run(p, options)));
60
- return results
61
- .map((r) => {
62
- try {
63
- // First try to extract JSON array from response
64
- const jsonMatch = r.match(/\[[\s\S]*?\]/);
65
- if (jsonMatch) {
66
- const parsed = JSON.parse(jsonMatch[0]);
67
- if (Array.isArray(parsed) && parsed.length > 0) {
68
- return parsed;
69
- }
70
- }
71
-
72
- // If no valid JSON array found, try to parse the entire response
73
- const parsed = JSON.parse(r);
74
- if (Array.isArray(parsed)) {
75
- return parsed;
76
- }
77
-
78
- // If response is not an array, wrap it in an array
79
- return [parsed];
80
- } catch (error) {
81
- // If JSON parsing fails completely, try to extract meaningful content
82
- const trimmed = r.trim();
83
-
84
- // If it's a long prose response, try to extract sentences or phrases
85
- if (trimmed.length > 200) {
86
- // Split by sentences and take meaningful ones
87
- const sentences = trimmed.split(/[.!?]+/).filter((s) => s.trim().length > 20);
88
- if (sentences.length >= 3) {
89
- return sentences.slice(0, 5).map((s) => s.trim());
90
- }
91
- }
92
-
93
- // If it contains quoted strings, extract them
94
- const quotes = trimmed.match(/"([^"]+)"/g);
95
- if (quotes && quotes.length > 0) {
96
- return quotes.map((q) => q.replace(/"/g, ''));
97
- }
98
-
99
- // Fallback: return the raw response as a single item
100
- console.warn('Failed to parse JSON response, using raw text:', error.message);
101
- return [trimmed];
102
- }
103
- })
104
- .flat();
105
- };
106
-
107
- export default veiledVariants;
@@ -1,40 +0,0 @@
1
- import { describe, expect, it, vi } from 'vitest';
2
- import veiledVariants from './index.js';
3
-
4
- let call = 0;
5
-
6
- const runMock = vi.fn().mockImplementation(() => {
7
- call += 1;
8
- if (call === 1) {
9
- return '["s1","s2","s3","s4","s5"]';
10
- }
11
- if (call === 2) {
12
- return '["c1","c2","c3","c4","c5"]';
13
- }
14
- return '["w1","w2","w3","w4","w5"]';
15
- });
16
-
17
- vi.mock('../../lib/chatgpt/index.js', () => ({
18
- run: (...args) => runMock(...args),
19
- }));
20
-
21
- describe('veiledVariants', () => {
22
- it('returns 15 masked queries', async () => {
23
- const result = await veiledVariants({ prompt: 'secret' });
24
- expect(Array.isArray(result)).toBe(true);
25
- expect(result.length).toBe(15);
26
- expect(runMock).toHaveBeenCalledTimes(3);
27
- runMock.mock.calls.forEach((callArgs) => {
28
- expect(callArgs[1]).toStrictEqual({ modelOptions: { modelName: 'privacy' } });
29
- });
30
- });
31
-
32
- it('allows overriding model name', async () => {
33
- runMock.mockClear();
34
- call = 0;
35
- await veiledVariants({ prompt: 'secret', modelName: 'fastGood' });
36
- runMock.mock.calls.forEach((callArgs) => {
37
- expect(callArgs[1]).toStrictEqual({ modelOptions: { modelName: 'fastGood' } });
38
- });
39
- });
40
- });
@@ -1,13 +0,0 @@
1
- export const longTestTimeout = 10 * 60 * 1000; // 10 minutes
2
-
3
- export const maxRetries = 3;
4
-
5
- export const retryDelay = 1000;
6
-
7
- export const debugToObject = process.env.DEBUG_TO_OBJECT ?? false;
8
-
9
- // Utility to conditionally skip long-running examples
10
- // Set ENABLE_LONG_EXAMPLES=true to run all examples
11
- // Set ENABLE_LONG_EXAMPLES=false or leave unset to skip long examples
12
- export const shouldRunLongExamples =
13
- process.env.ENABLE_LONG_EXAMPLES === 'true' || process.env.ENABLE_LONG_EXAMPLES === '1';
@@ -1,3 +0,0 @@
1
- export const retryJSONParse =
2
- 'The JSON parsing module will attempt recovery via internal retry. This message only appears in dev.';
3
- export const errorRunningTests = 'Error running AI tests';