@far-world-labs/verblets 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (300) hide show
  1. package/.cursor/launch.json +30 -0
  2. package/.cursor/settings.json +20 -0
  3. package/.github/workflows/branch-protection.yml +22 -0
  4. package/.github/workflows/ci.yml +120 -0
  5. package/.prettierrc +6 -0
  6. package/.release-it.json +4 -1
  7. package/.vscode/launch.json +31 -0
  8. package/AGENTS.md +220 -0
  9. package/DEVELOPING.md +105 -0
  10. package/README.md +254 -0
  11. package/eslint.config.js +80 -0
  12. package/package.json +29 -17
  13. package/scripts/generate-test/index.js +29 -3
  14. package/scripts/runner/index.js +26 -0
  15. package/scripts/simple-editor/index.js +29 -18
  16. package/scripts/summarize-files/index.js +28 -4
  17. package/src/chains/README.md +30 -0
  18. package/src/chains/anonymize/README.md +21 -0
  19. package/src/chains/anonymize/index.examples.js +75 -0
  20. package/src/chains/anonymize/index.js +121 -0
  21. package/src/chains/anonymize/index.spec.js +78 -0
  22. package/src/chains/bulk-central-tendency/index.examples.js +138 -0
  23. package/src/chains/bulk-central-tendency/index.js +91 -0
  24. package/src/chains/bulk-filter/README.md +21 -0
  25. package/src/chains/bulk-filter/index.examples.js +22 -0
  26. package/src/chains/bulk-filter/index.js +58 -0
  27. package/src/chains/bulk-filter/index.spec.js +38 -0
  28. package/src/chains/bulk-find/README.md +16 -0
  29. package/src/chains/bulk-find/index.examples.js +20 -0
  30. package/src/chains/bulk-find/index.js +30 -0
  31. package/src/chains/bulk-find/index.spec.js +26 -0
  32. package/src/chains/bulk-group/README.md +23 -0
  33. package/src/chains/bulk-group/index.examples.js +18 -0
  34. package/src/chains/bulk-group/index.js +34 -0
  35. package/src/chains/bulk-group/index.spec.js +41 -0
  36. package/src/chains/bulk-map/README.md +43 -0
  37. package/src/chains/bulk-map/index.examples.js +17 -0
  38. package/src/chains/bulk-map/index.js +86 -0
  39. package/src/chains/bulk-map/index.spec.js +44 -0
  40. package/src/chains/bulk-reduce/README.md +12 -0
  41. package/src/chains/bulk-reduce/index.examples.js +15 -0
  42. package/src/chains/bulk-reduce/index.js +13 -0
  43. package/src/chains/bulk-reduce/index.spec.js +25 -0
  44. package/src/chains/bulk-score/README.md +16 -0
  45. package/src/chains/bulk-score/bulk-score-result.json +18 -0
  46. package/src/chains/bulk-score/index.examples.js +22 -0
  47. package/src/chains/bulk-score/index.js +133 -0
  48. package/src/chains/bulk-score/index.spec.js +30 -0
  49. package/src/chains/category-samples/README.md +61 -0
  50. package/src/chains/category-samples/index.examples.js +103 -0
  51. package/src/chains/category-samples/index.js +134 -0
  52. package/src/chains/collect-terms/README.md +12 -0
  53. package/src/chains/collect-terms/index.examples.js +16 -0
  54. package/src/chains/collect-terms/index.js +44 -0
  55. package/src/chains/collect-terms/index.spec.js +25 -0
  56. package/src/chains/date/README.md +12 -0
  57. package/src/chains/date/index.examples.js +47 -0
  58. package/src/chains/date/index.js +74 -0
  59. package/src/chains/date/index.spec.js +62 -0
  60. package/src/chains/disambiguate/README.md +22 -0
  61. package/src/chains/disambiguate/disambiguate-meanings-result.json +16 -0
  62. package/src/chains/disambiguate/index.examples.js +18 -0
  63. package/src/chains/disambiguate/index.js +92 -0
  64. package/src/chains/disambiguate/index.spec.js +25 -0
  65. package/src/chains/dismantle/README.md +67 -0
  66. package/src/chains/dismantle/dismantle.examples.js +27 -0
  67. package/src/chains/dismantle/index.js +6 -17
  68. package/src/chains/dismantle/index.spec.js +1 -2
  69. package/src/chains/expect/README.md +171 -0
  70. package/src/chains/expect/index.examples.js +146 -0
  71. package/src/chains/expect/index.js +173 -0
  72. package/src/chains/expect/index.spec.js +324 -0
  73. package/src/chains/filter-ambiguous/README.md +11 -0
  74. package/src/chains/filter-ambiguous/index.examples.js +20 -0
  75. package/src/chains/filter-ambiguous/index.js +49 -0
  76. package/src/chains/filter-ambiguous/index.spec.js +31 -0
  77. package/src/chains/glossary/README.md +19 -0
  78. package/src/chains/glossary/index.examples.js +386 -0
  79. package/src/chains/glossary/index.js +75 -0
  80. package/src/chains/glossary/index.spec.js +19 -0
  81. package/src/chains/intersections/README.md +152 -0
  82. package/src/chains/intersections/index.examples.js +279 -0
  83. package/src/chains/intersections/index.js +366 -0
  84. package/src/chains/intersections/intersection-result.json +38 -0
  85. package/src/chains/list/index.examples.js +12 -16
  86. package/src/chains/list/index.js +106 -53
  87. package/src/chains/list/index.spec.js +8 -9
  88. package/src/chains/list/list-result.json +16 -0
  89. package/src/chains/llm-logger/README.md +208 -0
  90. package/src/chains/llm-logger/index.js +205 -0
  91. package/src/chains/llm-logger/index.spec.js +330 -0
  92. package/src/chains/questions/index.examples.js +2 -1
  93. package/src/chains/questions/index.js +14 -15
  94. package/src/chains/scan-js/index.js +6 -9
  95. package/src/chains/set-interval/README.md +81 -0
  96. package/src/chains/set-interval/index.examples.js +36 -0
  97. package/src/chains/set-interval/index.js +131 -0
  98. package/src/chains/set-interval/index.spec.js +70 -0
  99. package/src/chains/socratic/README.md +17 -0
  100. package/src/chains/socratic/index.js +64 -0
  101. package/src/chains/socratic/index.spec.js +24 -0
  102. package/src/chains/sort/index.examples.js +3 -7
  103. package/src/chains/sort/index.js +65 -15
  104. package/src/chains/sort/index.spec.js +5 -8
  105. package/src/chains/sort/sort-result.json +16 -0
  106. package/src/chains/summary-map/README.md +9 -1
  107. package/src/chains/summary-map/index.examples.js +9 -2
  108. package/src/chains/summary-map/index.js +43 -25
  109. package/src/chains/summary-map/index.spec.js +78 -3
  110. package/src/chains/test/index.js +9 -13
  111. package/src/chains/test-advice/index.js +4 -5
  112. package/src/chains/themes/README.md +20 -0
  113. package/src/chains/themes/index.examples.js +17 -0
  114. package/src/chains/themes/index.js +28 -0
  115. package/src/chains/themes/index.spec.js +19 -0
  116. package/src/chains/veiled-variants/index.examples.js +18 -0
  117. package/src/chains/veiled-variants/index.js +107 -0
  118. package/src/chains/veiled-variants/index.spec.js +40 -0
  119. package/src/constants/common.js +0 -2
  120. package/src/constants/models.js +172 -0
  121. package/src/index.js +178 -18
  122. package/src/json-schemas/README.md +13 -0
  123. package/src/json-schemas/index.js +8 -14
  124. package/src/json-schemas/schema-dot-org-photograph.json +11 -5
  125. package/src/json-schemas/schema-dot-org-place.json +78 -5
  126. package/src/lib/README.md +26 -0
  127. package/src/lib/bulk-filter/README.md +22 -0
  128. package/src/lib/bulk-filter/index.examples.js +27 -0
  129. package/src/lib/bulk-filter/index.js +63 -0
  130. package/src/lib/bulk-filter/index.spec.js +38 -0
  131. package/src/lib/bulk-find/README.md +18 -0
  132. package/src/lib/bulk-find/index.examples.js +19 -0
  133. package/src/lib/bulk-find/index.js +30 -0
  134. package/src/lib/bulk-find/index.spec.js +41 -0
  135. package/src/lib/chatgpt/index.js +63 -43
  136. package/src/lib/combinations/index.js +30 -0
  137. package/src/lib/combinations/index.spec.js +23 -0
  138. package/src/lib/functional/index.js +28 -0
  139. package/src/lib/logger-service/index.js +32 -0
  140. package/src/lib/parse-js-parts/index.js +9 -21
  141. package/src/lib/parse-llm-list/README.md +39 -0
  142. package/src/lib/parse-llm-list/index.js +54 -0
  143. package/src/lib/parse-llm-list/index.spec.js +59 -0
  144. package/src/lib/path-aliases/index.js +1 -3
  145. package/src/lib/path-aliases/index.spec.js +2 -8
  146. package/src/lib/pave/index.js +4 -4
  147. package/src/lib/pave/index.spec.js +6 -3
  148. package/src/lib/prompt-cache/index.js +14 -10
  149. package/src/lib/retry/index.js +11 -8
  150. package/src/lib/ring-buffer/README.md +460 -0
  151. package/src/lib/ring-buffer/index.js +1074 -0
  152. package/src/lib/search-best-first/city-walk.spec.js +37 -0
  153. package/src/lib/search-best-first/index.js +42 -11
  154. package/src/lib/search-best-first/index.spec.js +35 -0
  155. package/src/lib/search-js-files/index.js +44 -47
  156. package/src/lib/search-js-files/scan-file.js +10 -21
  157. package/src/lib/shorten-text/index.js +2 -7
  158. package/src/lib/shorten-text/index.spec.js +3 -3
  159. package/src/lib/strip-response/index.js +2 -7
  160. package/src/lib/template-replace/index.js +23 -0
  161. package/src/lib/template-replace/index.spec.js +60 -0
  162. package/src/lib/to-date/index.js +11 -0
  163. package/src/lib/to-number/index.js +1 -1
  164. package/src/lib/transcribe/index.js +26 -9
  165. package/src/prompts/README.md +3 -1
  166. package/src/prompts/as-object-with-schema.js +3 -8
  167. package/src/prompts/as-schema-org-text.js +10 -2
  168. package/src/prompts/code-features.js +1 -5
  169. package/src/prompts/constants.js +27 -27
  170. package/src/prompts/generate-collection.js +1 -1
  171. package/src/prompts/intent.js +16 -22
  172. package/src/prompts/select-from-threshold.js +1 -2
  173. package/src/prompts/sort.js +4 -8
  174. package/src/prompts/style.js +4 -7
  175. package/src/prompts/wrap-list.js +1 -4
  176. package/src/services/llm-model/global-overrides.spec.js +432 -0
  177. package/src/services/llm-model/index.js +234 -40
  178. package/src/services/llm-model/model.js +2 -2
  179. package/src/services/llm-model/negotiate.spec.js +447 -0
  180. package/src/services/redis/index.js +70 -7
  181. package/src/test/setup.js +20 -0
  182. package/src/verblets/README.md +26 -0
  183. package/src/verblets/auto/index.examples.js +12 -9
  184. package/src/verblets/auto/index.js +10 -10
  185. package/src/verblets/auto/index.spec.js +4 -6
  186. package/src/verblets/bool/README.md +36 -0
  187. package/src/verblets/bool/index.examples.js +53 -1
  188. package/src/verblets/bool/index.js +6 -9
  189. package/src/verblets/bool/index.spec.js +1 -3
  190. package/src/verblets/central-tendency/README.md +166 -0
  191. package/src/verblets/central-tendency/central-tendency-result.json +24 -0
  192. package/src/verblets/central-tendency/index.examples.js +196 -0
  193. package/src/verblets/central-tendency/index.js +171 -0
  194. package/src/verblets/central-tendency/index.spec.js +148 -0
  195. package/src/verblets/enum/index.examples.js +1 -4
  196. package/src/verblets/enum/index.js +7 -4
  197. package/src/verblets/expect/README.md +64 -0
  198. package/src/verblets/expect/index.examples.js +109 -0
  199. package/src/verblets/expect/index.js +75 -0
  200. package/src/verblets/expect/index.spec.js +127 -0
  201. package/src/verblets/intent/index.examples.js +95 -7
  202. package/src/verblets/intent/index.js +56 -68
  203. package/src/verblets/intersection/README.md +16 -0
  204. package/src/verblets/intersection/index.examples.js +89 -0
  205. package/src/verblets/intersection/index.js +84 -0
  206. package/src/verblets/intersection/index.spec.js +60 -0
  207. package/src/verblets/intersection/intersection-result.json +16 -0
  208. package/src/verblets/list-expand/README.md +10 -0
  209. package/src/verblets/list-expand/index.examples.js +14 -0
  210. package/src/verblets/list-expand/index.js +104 -0
  211. package/src/verblets/list-expand/index.spec.js +18 -0
  212. package/src/verblets/list-expand/list-expand-result.json +16 -0
  213. package/src/verblets/list-filter/README.md +22 -0
  214. package/src/verblets/list-filter/index.examples.js +26 -0
  215. package/src/verblets/list-filter/index.js +18 -0
  216. package/src/verblets/list-filter/index.spec.js +19 -0
  217. package/src/verblets/list-find/README.md +11 -0
  218. package/src/verblets/list-find/index.examples.js +15 -0
  219. package/src/verblets/list-find/index.js +17 -0
  220. package/src/verblets/list-find/index.spec.js +19 -0
  221. package/src/verblets/list-group/README.md +16 -0
  222. package/src/verblets/list-group/index.examples.js +16 -0
  223. package/src/verblets/list-group/index.js +112 -0
  224. package/src/verblets/list-group/index.spec.js +35 -0
  225. package/src/verblets/list-group/list-group-result.json +16 -0
  226. package/src/verblets/list-map/README.md +11 -0
  227. package/src/verblets/list-map/index.examples.js +15 -0
  228. package/src/verblets/list-map/index.js +26 -0
  229. package/src/verblets/list-map/index.spec.js +17 -0
  230. package/src/verblets/list-reduce/README.md +10 -0
  231. package/src/verblets/list-reduce/index.examples.js +14 -0
  232. package/src/verblets/list-reduce/index.js +21 -0
  233. package/src/verblets/list-reduce/index.spec.js +27 -0
  234. package/src/verblets/list-reduce/index.spec.jsx +27 -0
  235. package/src/verblets/name/README.md +15 -0
  236. package/src/verblets/name/index.examples.js +28 -0
  237. package/src/verblets/name/index.js +19 -0
  238. package/src/verblets/name/index.spec.js +33 -0
  239. package/src/verblets/name-similar-to/README.md +26 -0
  240. package/src/verblets/name-similar-to/index.examples.js +18 -0
  241. package/src/verblets/name-similar-to/index.js +20 -0
  242. package/src/verblets/name-similar-to/index.spec.js +13 -0
  243. package/src/verblets/number/index.examples.js +173 -7
  244. package/src/verblets/number/index.js +5 -2
  245. package/src/verblets/number/index.spec.js +1 -3
  246. package/src/verblets/number-with-units/index.examples.js +5 -1
  247. package/src/verblets/number-with-units/index.js +74 -9
  248. package/src/verblets/number-with-units/number-with-units-result.json +23 -0
  249. package/src/verblets/schema-org/index.examples.js +2 -7
  250. package/src/verblets/schema-org/index.js +32 -3
  251. package/src/verblets/sentiment/README.md +10 -0
  252. package/src/verblets/sentiment/index.examples.js +20 -0
  253. package/src/verblets/sentiment/index.js +9 -0
  254. package/src/verblets/sentiment/index.spec.js +20 -0
  255. package/src/verblets/to-object/index.js +10 -15
  256. package/src/verblets/to-object/index.spec.js +1 -4
  257. package/.eslintrc.json +0 -42
  258. package/docs/README.md +0 -41
  259. package/docs/babel.config.js +0 -3
  260. package/docs/blog/2019-05-28-first-blog-post.md +0 -12
  261. package/docs/blog/2019-05-29-long-blog-post.md +0 -44
  262. package/docs/blog/2021-08-01-mdx-blog-post.mdx +0 -20
  263. package/docs/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg +0 -0
  264. package/docs/blog/2021-08-26-welcome/index.md +0 -25
  265. package/docs/blog/authors.yml +0 -17
  266. package/docs/docs/api/bool.md +0 -74
  267. package/docs/docs/api/search.md +0 -51
  268. package/docs/docs/intro.md +0 -47
  269. package/docs/docs/tutorial-basics/_category_.json +0 -8
  270. package/docs/docs/tutorial-basics/congratulations.md +0 -23
  271. package/docs/docs/tutorial-basics/create-a-blog-post.md +0 -34
  272. package/docs/docs/tutorial-basics/create-a-document.md +0 -57
  273. package/docs/docs/tutorial-basics/create-a-page.md +0 -43
  274. package/docs/docs/tutorial-basics/deploy-your-site.md +0 -31
  275. package/docs/docs/tutorial-basics/markdown-features.mdx +0 -152
  276. package/docs/docs/tutorial-extras/_category_.json +0 -7
  277. package/docs/docs/tutorial-extras/img/docsVersionDropdown.png +0 -0
  278. package/docs/docs/tutorial-extras/img/localeDropdown.png +0 -0
  279. package/docs/docs/tutorial-extras/manage-docs-versions.md +0 -55
  280. package/docs/docs/tutorial-extras/translate-your-site.md +0 -88
  281. package/docs/docusaurus.config.js +0 -120
  282. package/docs/package.json +0 -44
  283. package/docs/sidebars.js +0 -31
  284. package/docs/src/components/HomepageFeatures/index.js +0 -61
  285. package/docs/src/components/HomepageFeatures/styles.module.css +0 -11
  286. package/docs/src/css/custom.css +0 -30
  287. package/docs/src/pages/index.js +0 -43
  288. package/docs/src/pages/index.module.css +0 -23
  289. package/docs/src/pages/markdown-page.md +0 -7
  290. package/docs/static/.nojekyll +0 -0
  291. package/docs/static/img/docusaurus-social-card.jpg +0 -0
  292. package/docs/static/img/docusaurus.png +0 -0
  293. package/docs/static/img/favicon.ico +0 -0
  294. package/docs/static/img/logo.svg +0 -1
  295. package/docs/static/img/undraw_docusaurus_mountain.svg +0 -171
  296. package/docs/static/img/undraw_docusaurus_react.svg +0 -170
  297. package/docs/static/img/undraw_docusaurus_tree.svg +0 -40
  298. package/src/constants/openai.js +0 -65
  299. /package/{.vite.config.examples.js → .vitest.config.examples.js} +0 -0
  300. /package/{.vite.config.js → .vitest.config.js} +0 -0
@@ -1,4 +1,3 @@
1
- import { camelCase, camelCaseTransformMerge } from 'change-case';
2
1
  import * as tokenizer from 'gpt-tokenizer';
3
2
 
4
3
  import Model from './model.js';
@@ -8,7 +7,34 @@ import {
8
7
  presencePenalty as presencePenaltyConfig,
9
8
  temperature as temperatureConfig,
10
9
  topP as topPConfig,
11
- } from '../../constants/openai.js';
10
+ } from '../../constants/models.js';
11
+
12
+ // Prioritized list of models (best to worst, excluding privacy/reasoning which are never auto-invoked)
13
+ const prioritizedModels = [
14
+ 'fastGoodCheap',
15
+ 'fastGoodCheapMulti',
16
+ 'fastGood',
17
+ 'fastGoodMulti',
18
+ 'goodCheap',
19
+ 'goodCheapMulti',
20
+ 'good',
21
+ 'goodMulti',
22
+ 'fastCheap',
23
+ 'fastCheapMulti',
24
+ 'fast',
25
+ 'fastMulti',
26
+ 'cheap',
27
+ 'cheapMulti',
28
+ 'multi',
29
+ 'fastCheapReasoning',
30
+ 'fastCheapReasoningMulti',
31
+ 'fastReasoning',
32
+ 'fastReasoningMulti',
33
+ 'cheapReasoning',
34
+ 'cheapReasoningMulti',
35
+ 'reasoning',
36
+ 'reasoningMulti',
37
+ ];
12
38
 
13
39
  class ModelService {
14
40
  constructor() {
@@ -16,41 +42,204 @@ class ModelService {
16
42
  this.models = Object.entries(models).reduce(
17
43
  (acc, [key, modelDef]) => ({
18
44
  ...acc,
19
- [key]:
20
- new Model({
21
- ...modelDef,
22
- tokenizer: tokenizer.encode,
23
- }),
45
+ [key]: new Model({
46
+ ...modelDef,
47
+ key,
48
+ tokenizer: tokenizer.encode,
49
+ }),
24
50
  }),
25
51
  {}
26
52
  );
27
53
 
28
- this.bestAvailableModel = this.models.gpt4 ?? this.models.gpt35Turbo;
29
- if (process.env.TEST === 'true') {
30
- // this.bestAvailableModel = this.models.textDavinci003;
31
- this.bestAvailableModel = this.models.gpt35Turbo;
54
+ // Always default to fastGood for public model
55
+ this.bestPublicModelKey = 'fastGood';
56
+
57
+ // Global overrides
58
+ this.globalOverrides = {
59
+ modelName: null, // Force specific model
60
+ negotiate: null, // Force specific negotiation options
61
+ temperature: null, // Force specific temperature
62
+ maxTokens: null, // Force specific max tokens
63
+ topP: null, // Force specific top_p
64
+ frequencyPenalty: null, // Force specific frequency penalty
65
+ presencePenalty: null, // Force specific presence penalty
66
+ };
67
+ }
68
+
69
+ // Global override management
70
+ setGlobalOverride(key, value) {
71
+ if (!(key in this.globalOverrides)) {
72
+ throw new Error(
73
+ `Invalid override key: ${key}. Valid keys are: ${Object.keys(this.globalOverrides).join(
74
+ ', '
75
+ )}`
76
+ );
32
77
  }
78
+ this.globalOverrides[key] = value;
33
79
  }
34
80
 
35
- getBestAvailableModel() {
36
- return this.bestAvailableModel;
81
+ clearGlobalOverride(key) {
82
+ if (key) {
83
+ if (!(key in this.globalOverrides)) {
84
+ throw new Error(
85
+ `Invalid override key: ${key}. Valid keys are: ${Object.keys(this.globalOverrides).join(
86
+ ', '
87
+ )}`
88
+ );
89
+ }
90
+ this.globalOverrides[key] = null;
91
+ } else {
92
+ // Clear all overrides
93
+ Object.keys(this.globalOverrides).forEach((k) => {
94
+ this.globalOverrides[k] = null;
95
+ });
96
+ }
37
97
  }
38
98
 
39
- updateBestAvailableModel(name) {
40
- this.bestAvailableModel = this.getModel(name);
99
+ getGlobalOverride(key) {
100
+ return this.globalOverrides[key];
41
101
  }
42
102
 
43
- getModel(name) {
44
- let modelFound = this.getBestAvailableModel();
45
- if (name && process.env.TEST !== 'true') {
46
- modelFound = this.models[name];
47
- if (!modelFound) {
48
- throw new Error(`Get model by name [error]: '${name}' not found.`);
103
+ getAllGlobalOverrides() {
104
+ return { ...this.globalOverrides };
105
+ }
106
+
107
+ // Apply global overrides to model options
108
+ applyGlobalOverrides(modelOptions) {
109
+ const result = { ...modelOptions };
110
+
111
+ // Apply each override if it's set (not null)
112
+ Object.entries(this.globalOverrides).forEach(([key, value]) => {
113
+ if (value !== null) {
114
+ result[key] = value;
49
115
  }
116
+ });
117
+
118
+ return result;
119
+ }
120
+
121
+ getBestPublicModel() {
122
+ return this.models[this.bestPublicModelKey];
123
+ }
124
+
125
+ getBestPrivateModel() {
126
+ if (!this.models.privacy) {
127
+ throw new Error(
128
+ 'No privacy model configured. Configure a privacy model or use a public model instead.'
129
+ );
130
+ }
131
+ return this.models.privacy;
132
+ }
133
+
134
+ updateBestPublicModel(name) {
135
+ this.bestPublicModelKey = name;
136
+ }
137
+
138
+ getModel(name) {
139
+ if (!name) {
140
+ return this.getBestPublicModel();
141
+ }
142
+
143
+ // First try to find by key
144
+ let modelFound = this.models[name];
145
+
146
+ // If not found by key, try to find by model name
147
+ if (!modelFound) {
148
+ modelFound = Object.values(this.models).find((model) => model.name === name);
149
+ }
150
+
151
+ if (!modelFound) {
152
+ throw new Error(`Get model by name [error]: '${name}' not found.`);
50
153
  }
51
154
  return modelFound;
52
155
  }
53
156
 
157
+ negotiateModel(preferred, negotiation = {}) {
158
+ const { privacy, reasoning, fast, cheap, good, multi } = negotiation;
159
+
160
+ // Privacy models take absolute priority
161
+ if (privacy) {
162
+ if (!this.models.privacy) {
163
+ return undefined;
164
+ }
165
+ return 'privacy';
166
+ }
167
+
168
+ // Helper function to check if a model matches all requirements
169
+ const matchesRequirements = (modelKey) => {
170
+ if (!this.models[modelKey]) {
171
+ return false;
172
+ }
173
+
174
+ const lowerModelKey = modelKey.toLowerCase();
175
+
176
+ // Check each requirement - support both positive and negative (false) requirements
177
+ // Only check requirements that are explicitly specified (not undefined)
178
+ if (fast === true && !/fast/i.test(lowerModelKey)) {
179
+ return false;
180
+ }
181
+ if (fast === false && /fast/i.test(lowerModelKey)) {
182
+ return false;
183
+ }
184
+ if (cheap === true && !/cheap/i.test(lowerModelKey)) {
185
+ return false;
186
+ }
187
+ if (cheap === false && /cheap/i.test(lowerModelKey)) {
188
+ return false;
189
+ }
190
+ if (good === true && !/good/i.test(lowerModelKey)) {
191
+ return false;
192
+ }
193
+ if (good === false && /good/i.test(lowerModelKey)) {
194
+ return false;
195
+ }
196
+ if (reasoning === true && !/reasoning/i.test(lowerModelKey)) {
197
+ return false;
198
+ }
199
+ if (reasoning === false && /reasoning/i.test(lowerModelKey)) {
200
+ return false;
201
+ }
202
+ if (multi === true && !/multi/i.test(lowerModelKey)) {
203
+ return false;
204
+ }
205
+ if (multi === false && /multi/i.test(lowerModelKey)) {
206
+ return false;
207
+ }
208
+ return true;
209
+ };
210
+
211
+ // Check if any specific requirements are given
212
+ const hasSpecificRequirements =
213
+ fast !== undefined ||
214
+ cheap !== undefined ||
215
+ good !== undefined ||
216
+ reasoning !== undefined ||
217
+ multi !== undefined;
218
+
219
+ // If no specific requirements are given, return preferred model if available
220
+ if (!hasSpecificRequirements) {
221
+ if (preferred && this.models[preferred]) {
222
+ return preferred;
223
+ }
224
+ return this.bestPublicModelKey;
225
+ }
226
+
227
+ // Find the first model that matches all requirements
228
+ for (const modelKey of prioritizedModels) {
229
+ if (matchesRequirements(modelKey)) {
230
+ return modelKey;
231
+ }
232
+ }
233
+
234
+ // Check if specific critical requirements were requested but couldn't be satisfied
235
+ if (reasoning === true) {
236
+ return undefined;
237
+ }
238
+
239
+ // If specific requirements were given but couldn't be satisfied, return undefined
240
+ return undefined;
241
+ }
242
+
54
243
  getRequestParameters(options = {}) {
55
244
  const frequencyPenalty = options.frequencyPenalty ?? frequencyPenaltyConfig;
56
245
  const presencePenalty = options.presencePenalty ?? presencePenaltyConfig;
@@ -62,7 +251,10 @@ class ModelService {
62
251
 
63
252
  let maxTokensFound = maxTokens;
64
253
  if (!maxTokens) {
65
- maxTokensFound = modelFound.maxTokens - modelFound.toTokens(prompt);
254
+ const promptTokens = modelFound.toTokens(prompt).length;
255
+ const availableTokens = modelFound.maxContextWindow - promptTokens;
256
+ // Cap to the model's maximum output tokens
257
+ maxTokensFound = Math.min(availableTokens, modelFound.maxOutputTokens);
66
258
  }
67
259
 
68
260
  return {
@@ -76,38 +268,40 @@ class ModelService {
76
268
  }
77
269
 
78
270
  getRequestConfig(options) {
79
- const {
80
- tools,
81
- toolChoice,
82
- modelName,
83
- prompt,
84
- systemPrompt,
85
- } = options;
271
+ const { tools, toolChoice, modelName, prompt, systemPrompt, response_format } = options;
86
272
 
87
273
  const modelFound = this.getModel(modelName);
88
274
 
89
- let requestPrompt = { prompt: prompt };
275
+ let requestPrompt = { prompt };
90
276
  if (/chat/.test(modelFound.endpoint)) {
91
277
  const userMessage = { role: 'user', content: prompt };
92
- const systemMessages = systemPrompt ? [{
93
- role: 'system',
94
- content: systemPrompt,
95
- }] : [];
278
+ const systemMessages = systemPrompt
279
+ ? [
280
+ {
281
+ role: 'system',
282
+ content: systemPrompt,
283
+ },
284
+ ]
285
+ : [];
96
286
  requestPrompt = {
97
- messages: [
98
- ...systemMessages,
99
- userMessage
100
- ],
287
+ messages: [...systemMessages, userMessage],
101
288
  tools,
102
- tool_choice: (tools && !toolChoice) ? 'auto' : toolChoice,
289
+ tool_choice: tools && !toolChoice ? 'auto' : toolChoice,
103
290
  };
104
291
  }
105
292
  const data = this.getRequestParameters(options);
106
293
 
107
- return {
294
+ const result = {
108
295
  ...requestPrompt,
109
296
  ...data,
110
297
  };
298
+
299
+ // Add response_format if provided
300
+ if (response_format) {
301
+ result.response_format = response_format;
302
+ }
303
+
304
+ return result;
111
305
  }
112
306
  }
113
307
 
@@ -9,8 +9,8 @@ export default class Model {
9
9
 
10
10
  budgetTokens(text, { completionMax = Infinity } = {}) {
11
11
  const prompt = this.toTokens(text).length;
12
- const total = this.maxTokens;
13
- const completion = Math.min(total - prompt, completionMax);
12
+ const total = this.maxContextWindow;
13
+ const completion = Math.min(Math.min(total - prompt, this.maxOutputTokens), completionMax);
14
14
 
15
15
  return {
16
16
  completion,