@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,303 +0,0 @@
1
- import { v4 as uuid } from 'uuid';
2
-
3
- import chatGPT from '../../lib/chatgpt/index.js';
4
- import { outputSuccinctNames, constants as promptConstants } from '../../prompts/index.js';
5
- import modelService from '../../services/llm-model/index.js';
6
- import toObject from '../../verblets/to-object/index.js';
7
-
8
- const { onlyJSONStringArray } = promptConstants;
9
-
10
- const subComponentsPrompt = (component, thing, fixes = '') => {
11
- let focus = '';
12
- if (component !== thing) {
13
- focus = `"${component}" within "${thing}"`;
14
- } else {
15
- focus = thing;
16
- }
17
-
18
- return `
19
- ${onlyJSONStringArray}
20
-
21
- Exhaustively enumerate all physical and logical subcomponents of ${focus}, including containers or abstract components.
22
-
23
- Apply the specifics listed here when dealing with component or entity:
24
- - ${outputSuccinctNames()}
25
- - If some components are subcomponents of others in the list, don't include them.
26
- - The output must not include "${thing}" or "${component}" in the list.
27
- - Only subcomponents, no accessories.
28
- ${fixes}
29
-
30
- ${onlyJSONStringArray}
31
- `;
32
- };
33
-
34
- const componentOptionsPrompt = (component, thing, fixes = '') => {
35
- let focus = '';
36
- if (component !== thing) {
37
- focus = `Considering "${component}" as a separate component within "${thing}" entity`;
38
- } else {
39
- focus = `Considering "${component}"`;
40
- }
41
- return `
42
- ${onlyJSONStringArray}
43
-
44
- ${focus}, list specific variants for this component. Only provide known variants, don't speculate. Output an empty list if you must.
45
-
46
- Apply the specifics listed here when dealing with component or entity:
47
- - ${outputSuccinctNames()}
48
- - Do not list subcomponents, that's not what this is about.
49
- ${fixes}
50
-
51
- ${onlyJSONStringArray}
52
- `;
53
- };
54
-
55
- const defaultMatch = () => false;
56
-
57
- const deepClone = (obj) => JSON.parse(JSON.stringify(obj));
58
-
59
- const search = (node, { match = defaultMatch, matches = [] } = {}) => {
60
- if (match(node)) {
61
- matches.push(node);
62
- }
63
-
64
- if (!node.children) {
65
- return matches.length > 0 ? matches : undefined;
66
- }
67
-
68
- for (const child of node.children) {
69
- search(child, { match, matches });
70
- }
71
-
72
- return matches.length > 0 ? matches : undefined;
73
- };
74
-
75
- const defaultDecompose = async ({
76
- name,
77
- focus,
78
- rootName,
79
- fixes,
80
- model = modelService.getBestPublicModel(),
81
- } = {}) => {
82
- const focusFormatted = focus ? `: ${focus}` : '';
83
-
84
- const promptCreated = subComponentsPrompt(`${name}${focusFormatted}`, rootName, fixes);
85
- const budget = model.budgetTokens(promptCreated);
86
- return toObject(
87
- await chatGPT(promptCreated, {
88
- modelOptions: {
89
- maxTokens: budget.completion,
90
- frequencyPenalty: 0.7,
91
- temperature: 0.7,
92
- },
93
- })
94
- );
95
- };
96
-
97
- const defaultEnhance = async ({
98
- name,
99
- rootName,
100
- fixes,
101
- model = modelService.getBestPublicModel(),
102
- } = {}) => {
103
- const promptCreated = componentOptionsPrompt(name, rootName, fixes);
104
- const budget = model.budgetTokens(promptCreated);
105
- const options = toObject(
106
- await chatGPT(promptCreated, {
107
- maxTokens: budget.completion,
108
- frequencyPenalty: 0.5,
109
- temperature: 0.3,
110
- })
111
- );
112
-
113
- return {
114
- name,
115
- options,
116
- topOptionName: options?.[0],
117
- };
118
- };
119
-
120
- const makeNode = async ({
121
- node = {},
122
- name: nameInitial,
123
- rootName,
124
- decompose = defaultDecompose,
125
- enhance = defaultEnhance,
126
- makeId = uuid,
127
- enhanceFixes,
128
- decomposeFixes,
129
- } = {}) => {
130
- const name = nameInitial ?? rootName;
131
-
132
- let nodeNew = node;
133
-
134
- if (!node.isEnhanced) {
135
- nodeNew = await enhance({
136
- name,
137
- rootName,
138
- fixes: enhanceFixes,
139
- });
140
- nodeNew.isEnhanced = true;
141
-
142
- const focus = node.options?.[0];
143
-
144
- const childNames = await decompose({
145
- name,
146
- focus,
147
- rootName,
148
- fixes: decomposeFixes,
149
- });
150
- nodeNew.children = childNames.map((childName) => ({
151
- id: makeId(),
152
- name: childName,
153
- }));
154
- }
155
-
156
- if (!node.id) {
157
- nodeNew.id = makeId();
158
- }
159
-
160
- return {
161
- ...node,
162
- ...nodeNew,
163
- };
164
- };
165
-
166
- const makeSubtree = async ({
167
- name,
168
- rootName,
169
- tree: treeInitial,
170
- depth = 0,
171
- decompose,
172
- enhance,
173
- enhanceFixes,
174
- decomposeFixes,
175
- makeId,
176
- } = {}) => {
177
- let tree = { ...(treeInitial ?? {}) };
178
-
179
- const nodeNew = await makeNode({
180
- node: tree,
181
- name: name ?? tree.name,
182
- rootName,
183
- enhance,
184
- decompose,
185
- makeId,
186
- enhanceFixes,
187
- decomposeFixes,
188
- });
189
-
190
- tree = {
191
- ...tree,
192
- ...nodeNew,
193
- };
194
-
195
- if (depth <= 0) {
196
- return tree;
197
- }
198
-
199
- const children = [];
200
- for (const child of tree.children) {
201
- // eslint-disable-next-line no-await-in-loop
202
- const subtree = await makeSubtree({
203
- tree: child,
204
- rootName,
205
- decompose,
206
- enhance,
207
- depth: depth - 1,
208
- makeId,
209
- enhanceFixes,
210
- decomposeFixes,
211
- });
212
-
213
- children.push(subtree);
214
- }
215
-
216
- tree.children = children;
217
-
218
- return tree;
219
- };
220
-
221
- export const simplifyTree = (node) => {
222
- if (!node.children || node.children.length === 0) {
223
- const parts = (node.children ?? []).map((child) => child.name);
224
- return {
225
- id: node.id,
226
- name: `${node.name}${node.options?.[0] ? `: ${node.options?.[0]}` : ''}`,
227
- parts: parts.length ? parts : undefined,
228
- };
229
- }
230
-
231
- const parts = node.children.map((child) => simplifyTree(child));
232
- return {
233
- id: node.id,
234
- name: `${node.name}${node.options?.[0] ? `: ${node.options?.[0]}` : ''}`,
235
- parts: parts.length ? parts : undefined,
236
- };
237
- };
238
-
239
- class ChainTree {
240
- constructor(name, { decompose, enhance, makeId, enhanceFixes, decomposeFixes } = {}) {
241
- this.rootName = name;
242
- this.tree = {};
243
- this.decompose = decompose;
244
- this.enhance = enhance;
245
- this.makeId = makeId;
246
- this.enhanceFixes = enhanceFixes;
247
- this.decomposeFixes = decomposeFixes;
248
- }
249
-
250
- getTree() {
251
- return this.tree;
252
- }
253
-
254
- async attachSubtree({ find, depth }) {
255
- const clonedTree = deepClone(this.tree);
256
-
257
- // Find the node to attach the subtree to in the cloned tree
258
- const targetNodes = search(clonedTree, { match: find });
259
-
260
- if (!targetNodes || targetNodes.length !== 1) {
261
- return undefined;
262
- }
263
-
264
- const targetNode = targetNodes[0];
265
-
266
- const newNode = await makeSubtree({
267
- ...this,
268
- rootName: clonedTree.name,
269
- tree: targetNode,
270
- depth,
271
- });
272
-
273
- Object.assign(targetNode, newNode);
274
-
275
- const nodeStripped = {
276
- ...newNode,
277
- children: newNode.children.map((child) => ({
278
- ...child,
279
- children: [],
280
- })),
281
- };
282
-
283
- this.tree = clonedTree;
284
-
285
- return nodeStripped;
286
- }
287
-
288
- async makeSubtree(config = {}) {
289
- this.tree = await makeSubtree({
290
- ...this,
291
- rootName: this.tree.name || this.rootName,
292
- ...config,
293
- });
294
-
295
- return this.tree;
296
- }
297
- }
298
-
299
- export const dismantle = (text, options) => {
300
- return new ChainTree(text, options);
301
- };
302
-
303
- export default ChainTree;
@@ -1,32 +0,0 @@
1
- import { describe, expect, it, vi } from 'vitest';
2
-
3
- import { dismantle } from './index.js';
4
-
5
- vi.mock('../../lib/chatgpt/index.js', () => ({
6
- default: vi.fn().mockImplementation((text) => {
7
- if (/prompt text to match/.test(text)) {
8
- return 'True';
9
- }
10
- return 'undefined';
11
- }),
12
- }));
13
-
14
- const examples = [
15
- {
16
- name: 'Basic usage',
17
- inputs: { text: 'test' },
18
- want: { result: {} },
19
- },
20
- ];
21
-
22
- describe('Dismantle chain', () => {
23
- examples.forEach((example) => {
24
- it(example.name, async () => {
25
- const result = await dismantle(example.inputs.text);
26
-
27
- if (example.want.typeOfResult) {
28
- expect(JSON.stringify(result.tree)).toStrictEqual(JSON.stringify(example.want.result));
29
- }
30
- });
31
- });
32
- });
@@ -1,171 +0,0 @@
1
- # LLM Expect Chain
2
-
3
- Advanced intelligent assertions with debugging features, environment variable modes, and structured results. This chain provides enhanced functionality beyond the basic [expect verblet](../../verblets/expect/).
4
-
5
- ## Why Use the Chain?
6
-
7
- While the verblet provides simple pass/fail assertions, the chain offers:
8
-
9
- - **Advanced Debugging**: Automatic code context analysis and intelligent advice
10
- - **Environment Modes**: Different behaviors for development, testing, and CI
11
- - **Structured Results**: Detailed information about assertions and failures
12
- - **Stack Trace Integration**: Automatic detection of calling file and line
13
-
14
- ## Environment Variable Modes
15
-
16
- Control behavior with the `LLM_EXPECT_MODE` environment variable:
17
-
18
- ### `none` (default)
19
- Silent mode - returns structured results without throwing or logging
20
- ```bash
21
- export LLM_EXPECT_MODE=none
22
- ```
23
-
24
- ### `info`
25
- Development mode - logs failures with context and advice to console
26
- ```bash
27
- export LLM_EXPECT_MODE=info
28
- ```
29
-
30
- ### `error`
31
- CI/Testing mode - throws detailed errors on assertion failures
32
- ```bash
33
- export LLM_EXPECT_MODE=error
34
- ```
35
-
36
- ## API Reference
37
-
38
- ### Enhanced API: `expect(actual, expected?, constraint?)`
39
-
40
- Returns a tuple `[passed, details]` with structured results:
41
-
42
- ```javascript
43
- import { expect } from './index.js';
44
-
45
- const [passed, details] = await expect(
46
- actualValue,
47
- "Does this meet our quality standards?"
48
- );
49
-
50
- console.log(details);
51
- /* Returns:
52
- {
53
- passed: false,
54
- advice: "ISSUE: Content lacks specific examples...",
55
- file: "/path/to/test.js",
56
- line: 42
57
- }
58
- */
59
- ```
60
-
61
- ### Simple API: `expect(actual, expected?, constraint?)`
62
-
63
- Backward compatible with the verblet - returns boolean:
64
-
65
- ```javascript
66
- import expect from './index.js';
67
-
68
- const result = await expect("hello", "hello");
69
- // Returns: true
70
- ```
71
-
72
- ## Real-World Use Cases
73
-
74
- ### Content Quality Assurance with Debugging
75
-
76
- ```javascript
77
- import { expect } from './index.js';
78
-
79
- // Set development mode for detailed feedback
80
- process.env.LLM_EXPECT_MODE = 'info';
81
-
82
- const [passed, details] = await expect(
83
- generatedCopy,
84
- "Is this marketing copy professional, engaging, and free of grammatical errors?"
85
- );
86
-
87
- if (!passed) {
88
- console.log(`Failed at ${details.file}:${details.line}`);
89
- console.log(details.advice);
90
- // ISSUE: Copy contains informal language and lacks call-to-action
91
- // FIX: Replace casual phrases with professional alternatives and add clear CTA
92
- // CONTEXT: Marketing copy should maintain professional tone while being engaging
93
- }
94
- ```
95
-
96
- ## Advanced Features
97
-
98
- ### Automatic Code Context Analysis
99
-
100
- The chain automatically:
101
- - Detects the calling file and line number
102
- - Reads 400 lines before and 100 lines after the assertion
103
- - Provides this context to the LLM for better debugging advice
104
-
105
- ### Intelligent Advice Generation
106
-
107
- Failed assertions generate structured advice:
108
- - **ISSUE**: Brief description of why the assertion failed
109
- - **FIX**: Specific actionable steps to resolve the issue
110
- - **CONTEXT**: Additional context about the problem and root causes
111
-
112
- ### Environment-Aware Behavior
113
-
114
- Different modes for different environments:
115
- - **Development**: Rich console output with advice
116
- - **Testing**: Detailed error throwing for CI/CD
117
- - **Production**: Silent operation with structured results
118
-
119
- ## Best Practices
120
-
121
- ### **Write Specific Constraints**
122
- ```javascript
123
- // ❌ Vague
124
- await expect(text, "Is this good?");
125
-
126
- // ✅ Specific
127
- await expect(text, "Is this text grammatically correct, under 100 words, and written in a professional tone?");
128
- ```
129
-
130
- ### **Use Structured Results**
131
- ```javascript
132
- const [passed, details] = await expect(content, constraint);
133
-
134
- // Access rich debugging information
135
- console.log('File:', details.file);
136
- console.log('Line:', details.line);
137
- console.log('Advice:', details.advice);
138
- ```
139
-
140
- ### **Combine with Traditional Tests**
141
- ```javascript
142
- // Traditional assertion for structure
143
- expect(response).toHaveProperty('status');
144
- expect(response.status).toBe(200);
145
-
146
- // LLM assertion for content quality
147
- const [passed] = await expect(
148
- response.message,
149
- "Is this error message helpful and user-friendly?"
150
- );
151
- ```
152
-
153
- ### Environment Modes
154
-
155
- ```bash
156
- # Silent operation (default)
157
- export LLM_EXPECT_MODE=none
158
-
159
- # Log debugging advice on failures
160
- export LLM_EXPECT_MODE=info
161
-
162
- # Throw with detailed debugging advice
163
- export LLM_EXPECT_MODE=error
164
- ```
165
-
166
- ## Best Practices
167
-
168
- - **Be specific**: Use clear, detailed constraints
169
- - **Test qualitatively**: Verify qualitative details with a clear yes/no answer
170
- - **Use robust constraints**: Write criteria to pass under a wide range of input hallucinations. Assert cases that classical software can't. Tune the level of rigorousness to the model performing the eval.
171
- - **Performance**: Remember this makes an LLM call - use judiciously
@@ -1,146 +0,0 @@
1
- import { describe, expect, it, beforeAll, afterAll } from 'vitest';
2
-
3
- import { expect as aiExpect } from './index.js';
4
- import { longTestTimeout } from '../../constants/common.js';
5
-
6
- const examples = [
7
- {
8
- inputs: {
9
- actual: 'Hello world!',
10
- constraint: 'Is this a greeting?',
11
- },
12
- want: { result: true },
13
- },
14
- {
15
- inputs: {
16
- actual: 'Goodbye cruel world',
17
- constraint: 'Is this a greeting?',
18
- },
19
- want: { result: false },
20
- },
21
- {
22
- inputs: {
23
- actual: 'hello',
24
- expected: 'hello',
25
- },
26
- want: { result: true },
27
- },
28
- {
29
- inputs: {
30
- actual: 'hello',
31
- expected: 'goodbye',
32
- },
33
- want: { result: false },
34
- },
35
- {
36
- inputs: {
37
- actual: 'This is a well-written, professional email with proper grammar and clear intent.',
38
- constraint: 'Is this text professional and grammatically correct?',
39
- },
40
- want: { result: true },
41
- },
42
- {
43
- inputs: {
44
- actual: { name: 'John Doe', age: 30, city: 'New York' },
45
- constraint: 'Does this person data look realistic?',
46
- },
47
- want: { result: true },
48
- },
49
- ];
50
-
51
- describe('LLM Expect Chain', () => {
52
- // Set environment mode to 'none' for all tests to avoid throwing
53
- const originalMode = process.env.LLM_EXPECT_MODE;
54
-
55
- beforeAll(() => {
56
- process.env.LLM_EXPECT_MODE = 'none';
57
- });
58
-
59
- afterAll(() => {
60
- if (originalMode !== undefined) {
61
- process.env.LLM_EXPECT_MODE = originalMode;
62
- } else {
63
- delete process.env.LLM_EXPECT_MODE;
64
- }
65
- });
66
-
67
- examples.forEach((example) => {
68
- const description = example.inputs.constraint
69
- ? `${JSON.stringify(example.inputs.actual).slice(0, 30)}... - ${example.inputs.constraint}`
70
- : `${JSON.stringify(example.inputs.actual)} === ${JSON.stringify(example.inputs.expected)}`;
71
-
72
- it(
73
- description,
74
- async () => {
75
- const [result, details] = await aiExpect(
76
- example.inputs.actual,
77
- example.inputs.expected,
78
- example.inputs.constraint
79
- );
80
-
81
- expect(result).toBe(example.want.result);
82
- expect(details).toHaveProperty('passed', example.want.result);
83
- expect(details).toHaveProperty('file');
84
- expect(details).toHaveProperty('line');
85
- expect(typeof details.line).toBe('number');
86
- },
87
- longTestTimeout
88
- );
89
- });
90
-
91
- it(
92
- 'should provide detailed debugging information on failure',
93
- async () => {
94
- const [result, details] = await aiExpect(
95
- 'This is clearly wrong content',
96
- undefined,
97
- 'Is this a professional business email?'
98
- );
99
-
100
- expect(result).toBe(false);
101
- expect(details.passed).toBe(false);
102
- expect(details.file).toBeDefined();
103
- expect(details.line).toBeGreaterThan(0);
104
-
105
- // In none mode, advice should be null for failures
106
- expect(details.advice).toBeNull();
107
- },
108
- longTestTimeout
109
- );
110
-
111
- it(
112
- 'should handle complex business logic validation',
113
- async () => {
114
- const businessRecommendation =
115
- 'Increase marketing budget by 20% for Q4 to boost holiday sales and target demographics aged 25-45 through social media campaigns';
116
-
117
- const [result, details] = await aiExpect(
118
- businessRecommendation,
119
- undefined,
120
- 'Is this recommendation specific, actionable, and includes measurable targets?'
121
- );
122
-
123
- expect(result).toBe(true);
124
- expect(details.passed).toBe(true);
125
- expect(details.file).toBeDefined();
126
- },
127
- longTestTimeout
128
- );
129
-
130
- it(
131
- 'should validate creative content quality',
132
- async () => {
133
- const storyOpening =
134
- 'Once upon a time, in a land far away, there lived a brave knight who embarked on a quest to save the kingdom from an ancient curse that had plagued the realm for centuries.';
135
-
136
- const [result] = await aiExpect(
137
- storyOpening,
138
- undefined,
139
- 'Is this story opening engaging, sets up clear conflict, and follows good narrative structure?'
140
- );
141
-
142
- expect(result).toBe(true);
143
- },
144
- longTestTimeout
145
- );
146
- });