@graphext/cuery 0.4.0 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. package/esm/browser.d.ts +1 -1
  2. package/esm/browser.d.ts.map +1 -1
  3. package/esm/browser.js +1 -1
  4. package/esm/mod.d.ts +5 -2
  5. package/esm/mod.d.ts.map +1 -1
  6. package/esm/mod.js +7 -2
  7. package/esm/src/api.d.ts +36 -5
  8. package/esm/src/api.d.ts.map +1 -1
  9. package/esm/src/api.js +84 -37
  10. package/esm/src/apis/chatgptScraper/brightdata.js +1 -1
  11. package/esm/src/apis/chatgptScraper/oxy.js +1 -1
  12. package/esm/src/apis/chatgptScraper/scraper.js +2 -2
  13. package/esm/src/apis/hasdata/aim.js +1 -1
  14. package/esm/src/apis/hasdata/aio.js +1 -1
  15. package/esm/src/apis/hasdata/helpers.d.ts +1 -1
  16. package/esm/src/apis/hasdata/helpers.d.ts.map +1 -1
  17. package/esm/src/apis/hasdata/helpers.js +2 -2
  18. package/esm/src/assets/models.d.ts +60725 -0
  19. package/esm/src/assets/models.d.ts.map +1 -0
  20. package/esm/src/assets/models.js +71915 -0
  21. package/esm/src/helpers/async.d.ts.map +1 -0
  22. package/esm/src/{async.js → helpers/async.js} +1 -1
  23. package/esm/src/helpers/seedKeywords.d.ts.map +1 -0
  24. package/esm/src/helpers/urls.d.ts.map +1 -0
  25. package/esm/src/helpers/utils.d.ts.map +1 -0
  26. package/esm/src/llm.d.ts +35 -0
  27. package/esm/src/llm.d.ts.map +1 -0
  28. package/esm/src/llm.js +59 -0
  29. package/esm/src/providers/google.d.ts +12 -0
  30. package/esm/src/providers/google.d.ts.map +1 -0
  31. package/esm/src/providers/google.js +111 -0
  32. package/esm/src/providers/index.d.ts +13 -0
  33. package/esm/src/providers/index.d.ts.map +1 -0
  34. package/esm/src/providers/index.js +14 -0
  35. package/esm/src/providers/openai.d.ts +12 -0
  36. package/esm/src/providers/openai.d.ts.map +1 -0
  37. package/esm/src/providers/openai.js +141 -0
  38. package/esm/src/providers/pricing.d.ts +72 -0
  39. package/esm/src/providers/pricing.d.ts.map +1 -0
  40. package/esm/src/providers/pricing.js +88 -0
  41. package/esm/src/providers/registry.d.ts +20 -0
  42. package/esm/src/providers/registry.d.ts.map +1 -0
  43. package/esm/src/providers/registry.js +35 -0
  44. package/esm/src/providers/types.d.ts +49 -0
  45. package/esm/src/providers/types.d.ts.map +1 -0
  46. package/esm/src/providers/types.js +7 -0
  47. package/esm/src/response.d.ts +74 -0
  48. package/esm/src/response.d.ts.map +1 -0
  49. package/esm/src/response.js +110 -0
  50. package/esm/src/tool.d.ts +58 -0
  51. package/esm/src/tool.d.ts.map +1 -0
  52. package/esm/src/tool.js +91 -0
  53. package/esm/src/tools/brands.js +6 -6
  54. package/esm/src/tools/classifier.d.ts +80 -17
  55. package/esm/src/tools/classifier.d.ts.map +1 -1
  56. package/esm/src/tools/classifier.js +68 -80
  57. package/esm/src/tools/entities.d.ts +23 -12
  58. package/esm/src/tools/entities.d.ts.map +1 -1
  59. package/esm/src/tools/entities.js +27 -47
  60. package/esm/src/tools/funnel.js +7 -7
  61. package/esm/src/tools/generic.d.ts +17 -4
  62. package/esm/src/tools/generic.d.ts.map +1 -1
  63. package/esm/src/tools/generic.js +39 -14
  64. package/esm/src/tools/keywords.js +5 -5
  65. package/esm/src/tools/personas.d.ts +49 -2
  66. package/esm/src/tools/personas.d.ts.map +1 -1
  67. package/esm/src/tools/personas.js +59 -35
  68. package/esm/src/tools/scorer.d.ts +24 -6
  69. package/esm/src/tools/scorer.d.ts.map +1 -1
  70. package/esm/src/tools/scorer.js +27 -22
  71. package/esm/src/tools/search.d.ts.map +1 -1
  72. package/esm/src/tools/search.js +33 -9
  73. package/esm/src/tools/sentiment.d.ts +30 -8
  74. package/esm/src/tools/sentiment.d.ts.map +1 -1
  75. package/esm/src/tools/sentiment.js +33 -28
  76. package/esm/src/tools/sources.d.ts +5 -5
  77. package/esm/src/tools/sources.d.ts.map +1 -1
  78. package/esm/src/tools/sources.js +5 -6
  79. package/esm/src/tools/topics.d.ts +44 -16
  80. package/esm/src/tools/topics.d.ts.map +1 -1
  81. package/esm/src/tools/topics.js +77 -68
  82. package/esm/src/tools/translate.d.ts +22 -31
  83. package/esm/src/tools/translate.d.ts.map +1 -1
  84. package/esm/src/tools/translate.js +40 -36
  85. package/package.json +2 -1
  86. package/script/browser.d.ts +1 -1
  87. package/script/browser.d.ts.map +1 -1
  88. package/script/browser.js +1 -1
  89. package/script/mod.d.ts +5 -2
  90. package/script/mod.d.ts.map +1 -1
  91. package/script/mod.js +14 -2
  92. package/script/src/api.d.ts +36 -5
  93. package/script/src/api.d.ts.map +1 -1
  94. package/script/src/api.js +84 -35
  95. package/script/src/apis/chatgptScraper/brightdata.js +1 -1
  96. package/script/src/apis/chatgptScraper/oxy.js +1 -1
  97. package/script/src/apis/chatgptScraper/scraper.js +2 -2
  98. package/script/src/apis/hasdata/aim.js +1 -1
  99. package/script/src/apis/hasdata/aio.js +1 -1
  100. package/script/src/apis/hasdata/helpers.d.ts +1 -1
  101. package/script/src/apis/hasdata/helpers.d.ts.map +1 -1
  102. package/script/src/apis/hasdata/helpers.js +2 -2
  103. package/script/src/assets/models.d.ts +60725 -0
  104. package/script/src/assets/models.d.ts.map +1 -0
  105. package/script/src/assets/models.js +71917 -0
  106. package/script/src/helpers/async.d.ts.map +1 -0
  107. package/script/src/{async.js → helpers/async.js} +1 -1
  108. package/script/src/helpers/seedKeywords.d.ts.map +1 -0
  109. package/script/src/helpers/urls.d.ts.map +1 -0
  110. package/script/src/helpers/utils.d.ts.map +1 -0
  111. package/script/src/llm.d.ts +35 -0
  112. package/script/src/llm.d.ts.map +1 -0
  113. package/script/src/llm.js +65 -0
  114. package/script/src/providers/google.d.ts +12 -0
  115. package/script/src/providers/google.d.ts.map +1 -0
  116. package/script/src/providers/google.js +148 -0
  117. package/script/src/providers/index.d.ts +13 -0
  118. package/script/src/providers/index.d.ts.map +1 -0
  119. package/script/src/providers/index.js +24 -0
  120. package/script/src/providers/openai.d.ts +12 -0
  121. package/script/src/providers/openai.d.ts.map +1 -0
  122. package/script/src/providers/openai.js +181 -0
  123. package/script/src/providers/pricing.d.ts +72 -0
  124. package/script/src/providers/pricing.d.ts.map +1 -0
  125. package/script/src/providers/pricing.js +97 -0
  126. package/script/src/providers/registry.d.ts +20 -0
  127. package/script/src/providers/registry.d.ts.map +1 -0
  128. package/script/src/providers/registry.js +39 -0
  129. package/script/src/providers/types.d.ts +49 -0
  130. package/script/src/providers/types.d.ts.map +1 -0
  131. package/script/src/providers/types.js +8 -0
  132. package/script/src/response.d.ts +74 -0
  133. package/script/src/response.d.ts.map +1 -0
  134. package/script/src/response.js +114 -0
  135. package/script/src/tool.d.ts +58 -0
  136. package/script/src/tool.d.ts.map +1 -0
  137. package/script/src/tool.js +95 -0
  138. package/script/src/tools/brands.js +6 -6
  139. package/script/src/tools/classifier.d.ts +80 -17
  140. package/script/src/tools/classifier.d.ts.map +1 -1
  141. package/script/src/tools/classifier.js +72 -85
  142. package/script/src/tools/entities.d.ts +23 -12
  143. package/script/src/tools/entities.d.ts.map +1 -1
  144. package/script/src/tools/entities.js +29 -51
  145. package/script/src/tools/funnel.js +7 -7
  146. package/script/src/tools/generic.d.ts +17 -4
  147. package/script/src/tools/generic.d.ts.map +1 -1
  148. package/script/src/tools/generic.js +39 -14
  149. package/script/src/tools/keywords.js +5 -5
  150. package/script/src/tools/personas.d.ts +49 -2
  151. package/script/src/tools/personas.d.ts.map +1 -1
  152. package/script/src/tools/personas.js +63 -36
  153. package/script/src/tools/scorer.d.ts +24 -6
  154. package/script/src/tools/scorer.d.ts.map +1 -1
  155. package/script/src/tools/scorer.js +28 -24
  156. package/script/src/tools/search.d.ts.map +1 -1
  157. package/script/src/tools/search.js +69 -9
  158. package/script/src/tools/sentiment.d.ts +30 -8
  159. package/script/src/tools/sentiment.d.ts.map +1 -1
  160. package/script/src/tools/sentiment.js +37 -30
  161. package/script/src/tools/sources.d.ts +5 -5
  162. package/script/src/tools/sources.d.ts.map +1 -1
  163. package/script/src/tools/sources.js +4 -5
  164. package/script/src/tools/topics.d.ts +44 -16
  165. package/script/src/tools/topics.d.ts.map +1 -1
  166. package/script/src/tools/topics.js +80 -72
  167. package/script/src/tools/translate.d.ts +22 -31
  168. package/script/src/tools/translate.d.ts.map +1 -1
  169. package/script/src/tools/translate.js +43 -40
  170. package/esm/src/async.d.ts.map +0 -1
  171. package/esm/src/models.d.ts +0 -18
  172. package/esm/src/models.d.ts.map +0 -1
  173. package/esm/src/models.js +0 -48
  174. package/esm/src/openai.d.ts +0 -17
  175. package/esm/src/openai.d.ts.map +0 -1
  176. package/esm/src/openai.js +0 -136
  177. package/esm/src/tools/seedKeywords.d.ts.map +0 -1
  178. package/esm/src/urls.d.ts.map +0 -1
  179. package/esm/src/utils.d.ts.map +0 -1
  180. package/script/src/async.d.ts.map +0 -1
  181. package/script/src/models.d.ts +0 -18
  182. package/script/src/models.d.ts.map +0 -1
  183. package/script/src/models.js +0 -52
  184. package/script/src/openai.d.ts +0 -17
  185. package/script/src/openai.d.ts.map +0 -1
  186. package/script/src/openai.js +0 -175
  187. package/script/src/tools/seedKeywords.d.ts.map +0 -1
  188. package/script/src/urls.d.ts.map +0 -1
  189. package/script/src/utils.d.ts.map +0 -1
  190. /package/esm/src/{async.d.ts → helpers/async.d.ts} +0 -0
  191. /package/esm/src/{tools → helpers}/seedKeywords.d.ts +0 -0
  192. /package/esm/src/{tools → helpers}/seedKeywords.js +0 -0
  193. /package/esm/src/{urls.d.ts → helpers/urls.d.ts} +0 -0
  194. /package/esm/src/{urls.js → helpers/urls.js} +0 -0
  195. /package/esm/src/{utils.d.ts → helpers/utils.d.ts} +0 -0
  196. /package/esm/src/{utils.js → helpers/utils.js} +0 -0
  197. /package/script/src/{async.d.ts → helpers/async.d.ts} +0 -0
  198. /package/script/src/{tools → helpers}/seedKeywords.d.ts +0 -0
  199. /package/script/src/{tools → helpers}/seedKeywords.js +0 -0
  200. /package/script/src/{urls.d.ts → helpers/urls.d.ts} +0 -0
  201. /package/script/src/{urls.js → helpers/urls.js} +0 -0
  202. /package/script/src/{utils.d.ts → helpers/utils.d.ts} +0 -0
  203. /package/script/src/{utils.js → helpers/utils.js} +0 -0
@@ -1,3 +1,50 @@
1
- import type { PersonasOptions, PersonasResponse } from '../schemas/persona.schema.js';
2
- export declare function generatePersonas({ sector, market, brand, brandDomain, language, userLanguage, count, model, briefing, instructions, personas }: PersonasOptions): Promise<PersonasResponse>;
1
+ import { Tool, type ModelConfig } from '../tool.js';
2
+ import type { Persona, PersonasResponse } from '../schemas/persona.schema.js';
3
+ /**
4
+ * Configuration for the PersonaGenerator tool.
5
+ */
6
+ export interface PersonaGeneratorConfig {
7
+ /** Industry sector the brand operates in */
8
+ sector: string;
9
+ /** Geographical market or region */
10
+ market: string;
11
+ /** Brand name */
12
+ brand?: string;
13
+ /** Brand domain */
14
+ brandDomain?: string;
15
+ /** Language for keyword seeds (default: 'english') */
16
+ language?: string;
17
+ /** Language for persona descriptions (default: same as language) */
18
+ userLanguage?: string | null;
19
+ /** Number of personas to generate (default: 5) */
20
+ count?: number;
21
+ /** Brand briefing context */
22
+ briefing?: string;
23
+ /** Additional instructions */
24
+ instructions?: string | null;
25
+ }
26
+ /**
27
+ * A tool that generates customer personas for a brand.
28
+ */
29
+ export declare class PersonaGenerator extends Tool<Array<Persona> | null, PersonasResponse, PersonasResponse> {
30
+ private readonly promptTemplate;
31
+ constructor(config: PersonaGeneratorConfig, modelConfig: ModelConfig);
32
+ protected schema(): import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodObject<{
33
+ personas: import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodArray<import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodObject<{
34
+ name: import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodString;
35
+ description: import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodString;
36
+ keywordSeeds: import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodArray<import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodString>;
37
+ }, import("../../deps/jsr.io/@zod/zod/4.3.6/src/v4/core/schemas.js").$strip>>;
38
+ explanation: import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodString;
39
+ }, import("../../deps/jsr.io/@zod/zod/4.3.6/src/v4/core/schemas.js").$strip>;
40
+ protected prompt(existingPersonas: Array<Persona> | null): string;
41
+ protected isEmpty(_input: Array<Persona> | null): boolean;
42
+ /**
43
+ * Not supported. PersonaGenerator is configured for a specific brand context
44
+ * and generates personas in a single call. Use invoke() instead.
45
+ */
46
+ batch(): never;
47
+ }
48
+ export type { Persona, PersonasResponse, PersonasOptions } from '../schemas/persona.schema.js';
49
+ export { PersonaSchema, PersonasResponseSchema } from '../schemas/persona.schema.js';
3
50
  //# sourceMappingURL=personas.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"personas.d.ts","sourceRoot":"","sources":["../../../src/src/tools/personas.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAkDtF,wBAAsB,gBAAgB,CAAC,EACtC,MAAM,EACN,MAAM,EACN,KAAK,EACL,WAAW,EACX,QAAoB,EACpB,YAAmB,EACnB,KAAS,EACT,KAAiB,EACjB,QAAQ,EACR,YAAY,EACZ,QAAe,EACf,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA4C7C"}
1
+ {"version":3,"file":"personas.d.ts","sourceRoot":"","sources":["../../../src/src/tools/personas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAEpD,OAAO,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAsD9E;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACtC,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mBAAmB;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8BAA8B;IAC9B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED;;GAEG;AACH,qBAAa,gBAAiB,SAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,IAAI,EAAE,gBAAgB,EAAE,gBAAgB,CAAC;IACpG,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;gBAE5B,MAAM,EAAE,sBAAsB,EAAE,WAAW,EAAE,WAAW;cAgDjD,MAAM;;;;;;;;IAIzB,SAAS,CAAC,MAAM,CAAC,gBAAgB,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,IAAI,GAAG,MAAM;cAW9C,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,IAAI,GAAG,OAAO;IAKlE;;;OAGG;IACM,KAAK,IAAI,KAAK;CAOvB;AAGD,YAAY,EAAE,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/F,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC"}
@@ -1,7 +1,7 @@
1
- import { askOpenAISafe } from '../openai.js';
1
+ import { Tool } from '../tool.js';
2
2
  import { buildBrandContext } from './brands.js';
3
3
  import { PersonasResponseSchema } from '../schemas/persona.schema.js';
4
- import { dedent } from '../utils.js';
4
+ import { dedent } from '../helpers/utils.js';
5
5
  const PROMPT = dedent(`
6
6
  You're a marketing expert identifying typical profiles/personas of people searching
7
7
  for brands, products or services. Generate {count} detailed customer personas for a brand
@@ -46,43 +46,67 @@ from this list, you MUST return at least all the same competitors that are alrea
46
46
  current data. If no modification instructions are provided, maintain the existing list and only add
47
47
  new competitors if they are relevant.
48
48
  `);
49
- export async function generatePersonas({ sector, market, brand, brandDomain, language = 'english', userLanguage = null, count = 5, model = 'gpt-4.1', briefing, instructions, personas = null }) {
50
- if (!brand && !brandDomain) {
51
- throw new Error('Either brand or brandDomain must be provided');
52
- }
53
- const brandContext = buildBrandContext({
54
- brand,
55
- brandDomain,
56
- sector,
57
- market,
58
- briefing
59
- });
60
- let brandExclusion;
61
- if (brandDomain) {
62
- if (brand) {
63
- brandExclusion = ` "${brand}" or the domain`;
49
+ /**
50
+ * A tool that generates customer personas for a brand.
51
+ */
52
+ export class PersonaGenerator extends Tool {
53
+ promptTemplate;
54
+ constructor(config, modelConfig) {
55
+ super(modelConfig);
56
+ const { sector, market, brand, brandDomain, language = 'english', userLanguage = null, count = 5, briefing, instructions } = config;
57
+ if (!brand && !brandDomain) {
58
+ throw new Error('Either brand or brandDomain must be provided');
59
+ }
60
+ const brandContext = buildBrandContext({
61
+ brand,
62
+ brandDomain,
63
+ sector,
64
+ market,
65
+ briefing
66
+ });
67
+ let brandExclusion;
68
+ if (brandDomain) {
69
+ if (brand) {
70
+ brandExclusion = ` "${brand}" or the domain`;
71
+ }
72
+ else {
73
+ brandExclusion = ' or domain';
74
+ }
64
75
  }
65
76
  else {
66
- brandExclusion = ' or domain';
77
+ brandExclusion = ` "${brand}"`;
67
78
  }
79
+ this.promptTemplate = PROMPT
80
+ .replace('{count}', count.toString())
81
+ .replaceAll('{sector}', sector)
82
+ .replaceAll('{market}', market)
83
+ .replaceAll('{brand_context}', brandContext)
84
+ .replaceAll('{brand_exclusion}', brandExclusion)
85
+ .replaceAll('{language}', language)
86
+ .replaceAll('{userLanguage}', userLanguage ?? language)
87
+ .replaceAll('{instructions}', instructions || '');
88
+ }
89
+ schema() {
90
+ return PersonasResponseSchema;
91
+ }
92
+ prompt(existingPersonas) {
93
+ const currentData = existingPersonas && existingPersonas.length > 0
94
+ ? CURRENT_DATA_CLAUSE.replace('{currentData}', JSON.stringify({ personas: existingPersonas }, null, 2))
95
+ : '';
96
+ return this.promptTemplate.replace('{currentPersonasInfo}', currentData);
68
97
  }
69
- else {
70
- brandExclusion = ` "${brand}"`;
98
+ isEmpty(_input) {
99
+ // Never skip - null means generate fresh personas
100
+ return false;
71
101
  }
72
- const currentData = personas && personas.length > 0 ? CURRENT_DATA_CLAUSE.replace('{currentData}', JSON.stringify({ personas }, null, 2)) : null;
73
- const content = PROMPT
74
- .replace('{count}', count.toString())
75
- .replaceAll('{sector}', sector)
76
- .replaceAll('{market}', market)
77
- .replaceAll('{brand_context}', brandContext)
78
- .replaceAll('{brand_exclusion}', brandExclusion)
79
- .replaceAll('{language}', language)
80
- .replaceAll('{userLanguage}', userLanguage ?? language)
81
- .replaceAll('{instructions}', instructions || '')
82
- .replaceAll('{currentPersonasInfo}', currentData || '');
83
- const { parsed } = await askOpenAISafe(content, model, PersonasResponseSchema);
84
- if (!parsed) {
85
- throw new Error('Failed to parse response from OpenAI');
102
+ /**
103
+ * Not supported. PersonaGenerator is configured for a specific brand context
104
+ * and generates personas in a single call. Use invoke() instead.
105
+ */
106
+ batch() {
107
+ throw new Error('PersonaGenerator.batch() is not supported. ' +
108
+ 'This tool generates personas for a specific brand context. ' +
109
+ 'Use invoke() instead.');
86
110
  }
87
- return parsed;
88
111
  }
112
+ export { PersonaSchema, PersonasResponseSchema } from '../schemas/persona.schema.js';
@@ -1,14 +1,32 @@
1
1
  import { z } from '../../deps/jsr.io/@zod/zod/4.3.6/src/index.js';
2
- export type ScoreSchema = z.ZodObject<{
2
+ import { Tool, type ModelConfig } from '../tool.js';
3
+ type ScoreSchema = z.ZodObject<{
3
4
  value: z.ZodNumber;
4
5
  }>;
5
6
  /**
6
- * Dynamically create a Zod schema for a score based on provided parameters.
7
+ * Configuration for the Scorer tool.
7
8
  */
8
- export declare function makeScoreSchema(type: 'integer' | 'number', min: number, max: number, description: string): ScoreSchema;
9
+ export interface ScorerConfig {
10
+ name: string;
11
+ description: string;
12
+ type: 'integer' | 'number';
13
+ min: number;
14
+ max: number;
15
+ }
9
16
  /**
10
- * Assumes only remaining placeholder in prompt is {record}
17
+ * A tool that scores records based on configured criteria.
11
18
  */
12
- export declare function score(record: Record<string, unknown>, prompt: string, schema: ScoreSchema, model?: string): Promise<number>;
13
- export declare function scoreBatch(records: Array<Record<string, unknown>>, name: string, description: string, type: 'integer' | 'number', min: number, max: number, model?: string, maxConcurrency?: number): Promise<Array<number>>;
19
+ export declare class Scorer extends Tool<Record<string, unknown> | null, {
20
+ value: number;
21
+ }, number> {
22
+ private readonly scoreSchema;
23
+ private readonly promptTemplate;
24
+ constructor(config: ScorerConfig, modelConfig: ModelConfig);
25
+ protected schema(): ScoreSchema;
26
+ protected prompt(record: Record<string, unknown> | null): string;
27
+ protected extractResult(parsed: {
28
+ value: number;
29
+ }): number;
30
+ }
31
+ export {};
14
32
  //# sourceMappingURL=scorer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scorer.d.ts","sourceRoot":"","sources":["../../../src/src/tools/scorer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,+CAA+C,CAAC;AAqBlE,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,SAAS,CAAC;IAAE,KAAK,EAAE,CAAC,CAAC,SAAS,CAAA;CAAE,CAAC,CAAC;AAE9D;;GAEG;AACH,wBAAgB,eAAe,CAC9B,IAAI,EAAE,SAAS,GAAG,QAAQ,EAC1B,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,GACjB,WAAW,CAWb;AAED;;GAEG;AACH,wBAAsB,KAAK,CAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,WAAW,EACnB,KAAK,GAAE,MAAuB,GAC5B,OAAO,CAAC,MAAM,CAAC,CAajB;AAED,wBAAsB,UAAU,CAC/B,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACvC,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,SAAS,GAAG,QAAQ,EAC1B,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,KAAK,GAAE,MAAuB,EAC9B,cAAc,GAAE,MAAY,GAC1B,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAcxB"}
1
+ {"version":3,"file":"scorer.d.ts","sourceRoot":"","sources":["../../../src/src/tools/scorer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,+CAA+C,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAkBpD,KAAK,WAAW,GAAG,CAAC,CAAC,SAAS,CAAC;IAAE,KAAK,EAAE,CAAC,CAAC,SAAS,CAAA;CAAE,CAAC,CAAC;AAuBvD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACZ;AAED;;GAEG;AACH,qBAAa,MAAO,SAAQ,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,MAAM,CAAC;IAC1F,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;gBAE5B,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW;cAYvC,MAAM;IAIzB,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;cAIpC,aAAa,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE;CAG1D"}
@@ -1,7 +1,6 @@
1
1
  import { z } from '../../deps/jsr.io/@zod/zod/4.3.6/src/index.js';
2
- import { mapParallel } from '../async.js';
3
- import { askOpenAISafe } from '../openai.js';
4
- import { dedent } from '../utils.js';
2
+ import { Tool } from '../tool.js';
3
+ import { dedent } from '../helpers/utils.js';
5
4
  const PROMPT = dedent(`
6
5
  # Instructions
7
6
 
@@ -19,7 +18,7 @@ based on the content of the attributes.
19
18
  /**
20
19
  * Dynamically create a Zod schema for a score based on provided parameters.
21
20
  */
22
- export function makeScoreSchema(type, min, max, description) {
21
+ function makeScoreSchema(type, min, max, description) {
23
22
  let schema;
24
23
  if (type === 'integer') {
25
24
  schema = z.number().int().min(min).max(max).describe(description);
@@ -28,27 +27,33 @@ export function makeScoreSchema(type, min, max, description) {
28
27
  schema = z.number().min(min).max(max).describe(description);
29
28
  }
30
29
  return z.object({
31
- value: schema
30
+ value: schema,
32
31
  });
33
32
  }
34
33
  /**
35
- * Assumes only remaining placeholder in prompt is {record}
34
+ * A tool that scores records based on configured criteria.
36
35
  */
37
- export async function score(record, prompt, schema, model = 'gpt-4.1-mini') {
38
- const renderedPrompt = prompt.replace('record', JSON.stringify(record, null, 2));
39
- const response = await askOpenAISafe(renderedPrompt, model, schema);
40
- if (response.parsed == null) {
41
- throw new Error('Failed to parse score from OpenAI response');
36
+ export class Scorer extends Tool {
37
+ scoreSchema;
38
+ promptTemplate;
39
+ constructor(config, modelConfig) {
40
+ super(modelConfig);
41
+ const { name, description, type, min, max } = config;
42
+ this.scoreSchema = makeScoreSchema(type, min, max, description);
43
+ this.promptTemplate = PROMPT
44
+ .replace('{name}', name)
45
+ .replace('{type}', type)
46
+ .replace('{min}', min.toString())
47
+ .replace('{max}', max.toString())
48
+ .replace('{description}', description);
49
+ }
50
+ schema() {
51
+ return this.scoreSchema;
52
+ }
53
+ prompt(record) {
54
+ return this.promptTemplate.replace('{record}', JSON.stringify(record, null, 2));
55
+ }
56
+ extractResult(parsed) {
57
+ return parsed.value;
42
58
  }
43
- return response.parsed.value;
44
- }
45
- export async function scoreBatch(records, name, description, type, min, max, model = 'gpt-4.1-mini', maxConcurrency = 100) {
46
- const schema = makeScoreSchema(type, min, max, description);
47
- const prompt = PROMPT
48
- .replace('{name}', name)
49
- .replace('{type}', type)
50
- .replace('{min}', min.toString())
51
- .replace('{max}', max.toString())
52
- .replace('{description}', description);
53
- return mapParallel(records, maxConcurrency, (record) => score(record, prompt, schema, model));
54
59
  }
@@ -1 +1 @@
1
- {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/src/tools/search.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAK3H,YAAY,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,EAClC,MAAM,EACN,KAAsB,EACtB,SAAgB,EAChB,cAAqB,EACrB,WAAmB,EACnB,eAAuB,EACvB,UAAyB,EACzB,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAqBvC;AAqED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,EAAE,EACzC,MAAM,EACN,KAAK,EACL,cAAc,EACd,SAAgB,EAChB,cAAqB,EACrB,WAAsB,EACtB,eAAuB,EACvB,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CA0BxC;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,EAC3B,OAAO,EACP,KAAsB,EACtB,SAAgB,EAChB,cAAqB,EACrB,WAAsB,EACtB,eAAuB,EACvB,cAAoB,EACpB,EAAE,kBAAkB,GAAG,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAanD"}
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/src/tools/search.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AA0B3H,YAAY,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,EAClC,MAAM,EACN,KAAsB,EACtB,SAAgB,EAChB,cAAqB,EACrB,WAAmB,EACnB,eAAuB,EACvB,UAAyB,EACzB,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CA4BvC;AAqED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,EAAE,EACzC,MAAM,EACN,KAAK,EACL,cAAc,EACd,SAAgB,EAChB,cAAqB,EACrB,WAAsB,EACtB,eAAuB,EACvB,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CA0BxC;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,EAC3B,OAAO,EACP,KAAsB,EACtB,SAAgB,EAChB,cAAqB,EACrB,WAAsB,EACtB,eAAuB,EACvB,cAAoB,EACpB,EAAE,kBAAkB,GAAG,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAanD"}
@@ -1,7 +1,25 @@
1
- import { mapParallel } from '../async.js';
2
- import { askOpenAISafe } from '../openai.js';
3
- import { extractDomain } from '../urls.js';
4
- import { dedent } from '../utils.js';
1
+ import * as dntShim from "../../_dnt.shims.js";
2
+ import OpenAI from 'openai';
3
+ import { mapParallel } from '../helpers/async.js';
4
+ import { askLLMSafe } from '../llm.js';
5
+ import { extractDomain } from '../helpers/urls.js';
6
+ import { dedent } from '../helpers/utils.js';
7
+ // Lazy-initialized OpenAI client for web search functionality
8
+ let openaiClient = null;
9
+ function getOpenAIClient() {
10
+ if (!openaiClient) {
11
+ const fetchOptions = {};
12
+ const abortSignal = dntShim.dntGlobalThis.abortSignal;
13
+ if (abortSignal) {
14
+ fetchOptions.signal = abortSignal;
15
+ }
16
+ openaiClient = new OpenAI({
17
+ apiKey: dntShim.Deno.env.get('OPENAI_API_KEY'),
18
+ fetchOptions,
19
+ });
20
+ }
21
+ return openaiClient;
22
+ }
5
23
  /**
6
24
  * Call OpenAI Responses API with Web Search enabled (async).
7
25
  *
@@ -21,11 +39,17 @@ export async function searchOpenAI({ prompt, model = 'gpt-4.1-mini', useSearch =
21
39
  }];
22
40
  params.tool_choice = 'required';
23
41
  }
24
- const { output } = await askOpenAISafe(prompt, model, undefined, params);
25
- if (!output) {
42
+ const client = getOpenAIClient();
43
+ const response = await client.responses.create({
44
+ ...params,
45
+ model,
46
+ input: [{ role: 'user', content: prompt }],
47
+ stream: false,
48
+ });
49
+ if (!response.output) {
26
50
  throw new Error('No output from OpenAI');
27
51
  }
28
- return validateOpenAI(output);
52
+ return validateOpenAI(response.output);
29
53
  }
30
54
  /**
31
55
  * Convert a raw web search response into a SearchResult instance.
@@ -109,9 +133,9 @@ export async function searchWithFormat({ prompt, model, responseSchema, useSearc
109
133
  .replace('{prompt}', prompt)
110
134
  .replace('{answer}', searchResult.answer)
111
135
  .replace('{sources}', sources);
112
- const { parsed } = await askOpenAISafe(formattedPrompt, 'gpt-4.1-mini', responseSchema);
136
+ const { parsed } = await askLLMSafe({ prompt: formattedPrompt, model: 'gpt-4.1-mini', schema: responseSchema });
113
137
  if (!parsed) {
114
- throw new Error('Failed to parse structured response from OpenAI');
138
+ throw new Error('Failed to parse structured response from LLM');
115
139
  }
116
140
  return parsed;
117
141
  }
@@ -1,11 +1,33 @@
1
- import { type BrandContext } from '../schemas/brand.schema.js';
2
- import { type ABSentiment } from '../schemas/sentiment.schema.js';
1
+ import { Tool, type ModelConfig } from '../tool.js';
2
+ import type { Message } from '../llm.js';
3
+ import type { BrandContext } from '../schemas/brand.schema.js';
4
+ import { type ABSentiment, type ABSentiments } from '../schemas/sentiment.schema.js';
5
+ export interface SentimentExtractorConfig {
6
+ /** Additional instructions for sentiment extraction */
7
+ instructions?: string;
8
+ /** Brand context for focused analysis */
9
+ brand?: BrandContext | null;
10
+ }
3
11
  /**
4
- * Extracts aspect-based sentiments from a text.
12
+ * A tool that extracts aspect-based sentiments from text.
5
13
  */
6
- export declare function extractAspectBasedSentiments(text: string | null, instructions?: string, model?: string): Promise<Array<ABSentiment>>;
7
- /**
8
- * Classifies multiple data records concurrently while preserving order.
9
- */
10
- export declare function extractABSForBrandBatch(texts: Array<string | null>, brand?: BrandContext | null, model?: string, maxConcurrency?: number): Promise<Array<Array<ABSentiment>>>;
14
+ export declare class SentimentExtractor extends Tool<string | null, ABSentiments, Array<ABSentiment>> {
15
+ private readonly systemPrompt;
16
+ constructor(config: SentimentExtractorConfig | undefined, modelConfig: ModelConfig);
17
+ protected schema(): import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodObject<{
18
+ aspects: import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodArray<import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodObject<{
19
+ aspect: import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodString;
20
+ sentiment: import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodEnum<{
21
+ positive: "positive";
22
+ negative: "negative";
23
+ }>;
24
+ reason: import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodString;
25
+ }, import("../../deps/jsr.io/@zod/zod/4.3.6/src/v4/core/schemas.js").$strip>>;
26
+ }, import("../../deps/jsr.io/@zod/zod/4.3.6/src/v4/core/schemas.js").$strip>;
27
+ protected prompt(text: string | null): Message[];
28
+ protected isEmpty(text: string | null): boolean;
29
+ protected extractResult(parsed: ABSentiments): Array<ABSentiment>;
30
+ }
31
+ export type { ABSentiment, ABSentiments } from '../schemas/sentiment.schema.js';
32
+ export { ABSentimentSchema, ABSentimentsSchema } from '../schemas/sentiment.schema.js';
11
33
  //# sourceMappingURL=sentiment.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sentiment.d.ts","sourceRoot":"","sources":["../../../src/src/tools/sentiment.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAwCtF;;GAEG;AACH,wBAAsB,4BAA4B,CACjD,IAAI,EAAE,MAAM,GAAG,IAAI,EACnB,YAAY,GAAE,MAAW,EACzB,KAAK,GAAE,MAAuB,GAC5B,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAoB7B;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC5C,KAAK,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,EAC3B,KAAK,GAAE,YAAY,GAAG,IAAW,EACjC,KAAK,GAAE,MAAuB,EAC9B,cAAc,GAAE,MAAY,GAC1B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAYpC"}
1
+ {"version":3,"file":"sentiment.d.ts","sourceRoot":"","sources":["../../../src/src/tools/sentiment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAsB,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAwCzG,MAAM,WAAW,wBAAwB;IACxC,uDAAuD;IACvD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yCAAyC;IACzC,KAAK,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;CAC5B;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,IAAI,CAAC,MAAM,GAAG,IAAI,EAAE,YAAY,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;IAC5F,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAE1B,MAAM,EAAE,wBAAwB,YAAK,EAAE,WAAW,EAAE,WAAW;cAgBxD,MAAM;;;;;;;;;;IAIzB,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,EAAE;cAQ7B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO;cAIrC,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG,KAAK,CAAC,WAAW,CAAC;CAG1E;AAED,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAChF,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC"}
@@ -1,7 +1,6 @@
1
- import { mapParallel } from '../async.js';
2
- import { askOpenAISafe } from '../openai.js';
1
+ import { Tool } from '../tool.js';
3
2
  import { ABSentimentsSchema } from '../schemas/sentiment.schema.js';
4
- import { dedent } from '../utils.js';
3
+ import { dedent } from '../helpers/utils.js';
5
4
  const ABS_PROMPT_SYSTEM = dedent(`
6
5
  You're an expert in Aspect-Based Sentiment Analysis. Your task involves identifying specific
7
6
  entities mentioned in a text (e.g. a person, product, service, or experience) and determining the
@@ -37,32 +36,38 @@ Return the entities and their sentiments with reasons from the following text se
37
36
  {text}
38
37
  `);
39
38
  /**
40
- * Extracts aspect-based sentiments from a text.
39
+ * A tool that extracts aspect-based sentiments from text.
41
40
  */
42
- export async function extractAspectBasedSentiments(text, instructions = '', model = 'gpt-4.1-mini') {
43
- if (text == null || text.trim() === '') {
44
- return [];
41
+ export class SentimentExtractor extends Tool {
42
+ systemPrompt;
43
+ constructor(config = {}, modelConfig) {
44
+ super(modelConfig);
45
+ const { instructions = '', brand = null } = config;
46
+ const brandInstructions = brand
47
+ ? dedent(`
48
+ When analyzing the text, pay special attention to any mentions of the brand "${brand.shortName}"
49
+ or its products/services (${brand.portfolio}). Ensure that any sentiments expressed toward this
50
+ brand or its offerings are accurately captured in your output. Respond in language code ${brand.language}.
51
+ `)
52
+ : '';
53
+ const combinedInstructions = [instructions, brandInstructions].filter(Boolean).join('\n\n');
54
+ this.systemPrompt = ABS_PROMPT_SYSTEM.replace('{instructions}', combinedInstructions);
45
55
  }
46
- const promptSystem = ABS_PROMPT_SYSTEM.replace('{instructions}', instructions);
47
- const promptUser = ABS_PROMPT_USER.replace('{text}', text);
48
- const conversation = [
49
- { role: 'system', content: promptSystem },
50
- { role: 'user', content: promptUser }
51
- ];
52
- const { parsed } = await askOpenAISafe(conversation, model, ABSentimentsSchema);
53
- if (!parsed) {
54
- throw new Error('Failed to parse response from OpenAI');
56
+ schema() {
57
+ return ABSentimentsSchema;
58
+ }
59
+ prompt(text) {
60
+ const userPrompt = ABS_PROMPT_USER.replace('{text}', text ?? '');
61
+ return [
62
+ { role: 'system', content: this.systemPrompt },
63
+ { role: 'user', content: userPrompt }
64
+ ];
65
+ }
66
+ isEmpty(text) {
67
+ return text == null || text.trim() === '';
68
+ }
69
+ extractResult(parsed) {
70
+ return parsed.aspects;
55
71
  }
56
- return parsed.aspects;
57
- }
58
- /**
59
- * Classifies multiple data records concurrently while preserving order.
60
- */
61
- export async function extractABSForBrandBatch(texts, brand = null, model = 'gpt-4.1-mini', maxConcurrency = 100) {
62
- const instructions = brand ? dedent(`
63
- When analyzing the text, pay special attention to any mentions of the brand "${brand.shortName}"
64
- or its products/services (${brand.portfolio}). Ensure that any sentiments expressed toward this
65
- brand or its offerings are accurately captured in your output. Respond in language code ${brand.language}.
66
- `) : '';
67
- return mapParallel(texts, maxConcurrency, (text) => extractAspectBasedSentiments(text, instructions, model));
68
72
  }
73
+ export { ABSentimentSchema, ABSentimentsSchema } from '../schemas/sentiment.schema.js';
@@ -1,7 +1,7 @@
1
- import { type FlaggedBrand } from '../schemas/brand.schema.js';
1
+ import type { FlaggedBrand } from '../schemas/brand.schema.js';
2
2
  import type { CategorizedSource, EnrichedSource, Source } from '../schemas/sources.schema.js';
3
3
  import { type TopicLabel } from './topics.js';
4
- import type { AIParams } from '../openai.js';
4
+ import type { ProviderParams } from '../llm.js';
5
5
  import type { Entity } from './entities.js';
6
6
  export type { Source, EnrichedSource, CategorizedSource } from '../schemas/sources.schema.js';
7
7
  /**
@@ -27,13 +27,13 @@ export declare function collectURLs(sourceLists: Array<Array<Source>>, domains?:
27
27
  /**
28
28
  * Classifies an array of URLs into categories based on WEB_TAXONOMY.
29
29
  */
30
- export declare function classifyURLs(urls: Array<string>, model?: string, modelParams?: AIParams, maxConcurrency?: number): Promise<Record<string, TopicLabel | null>>;
30
+ export declare function classifyURLs(urls: Array<string>, model?: string, modelParams?: ProviderParams, maxConcurrency?: number): Promise<Record<string, TopicLabel | null>>;
31
31
  /**
32
32
  * Creates a category mapper for sources by collecting unique URLs/domains and classifying them.
33
33
  */
34
- export declare function makeCategoryMapper(sourceLists: Array<Array<Source>>, domains?: boolean, model?: string, modelParams?: AIParams, maxConcurrency?: number): Promise<Record<string, TopicLabel | null>>;
34
+ export declare function makeCategoryMapper(sourceLists: Array<Array<Source>>, domains?: boolean, model?: string, modelParams?: ProviderParams, maxConcurrency?: number): Promise<Record<string, TopicLabel | null>>;
35
35
  /**
36
36
  * Categorizes sources by assigning topic and subtopic to each EnrichedSource in-place(!).
37
37
  */
38
- export declare function categorizeSources(sourceLists: Array<Array<EnrichedSource>>, domains?: boolean, model?: string, modelParams?: AIParams, maxConcurrency?: number): Promise<Array<Array<CategorizedSource>>>;
38
+ export declare function categorizeSources(sourceLists: Array<Array<EnrichedSource>>, domains?: boolean, model?: string, modelParams?: ProviderParams, maxConcurrency?: number): Promise<Array<Array<CategorizedSource>>>;
39
39
  //# sourceMappingURL=sources.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sources.d.ts","sourceRoot":"","sources":["../../../src/src/tools/sources.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAC9F,OAAO,EAA4C,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AACxF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAE5C,YAAY,EAAE,MAAM,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAE9F;;GAEG;AACH,wBAAgB,YAAY,CAC3B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,KAAK,CAAC,YAAY,CAAC,EAC3B,QAAQ,GAAE,KAAK,CAAC,MAAM,CAAM,GAC1B,cAAc,CAoEhB;AAED,wBAAsB,aAAa,CAClC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,EACpC,MAAM,EAAE,KAAK,CAAC,YAAY,CAAC,EAC3B,QAAQ,GAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAM,GACjC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAIvC;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACtC,OAAO,EAAE,KAAK,CAAC,cAAc,CAAC,GAC5B;IAAE,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAAC,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;CAAE,CA8DjE;AAED,wBAAgB,qBAAqB,CACpC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,GACnC;IAAE,eAAe,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IAAC,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAA;CAAE,CAc/E;AAED;;GAEG;AACH,wBAAgB,WAAW,CAC1B,WAAW,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EACjC,OAAO,GAAE,OAAe,GACtB,KAAK,CAAC,MAAM,CAAC,CAgBf;AAiED;;GAEG;AACH,wBAAsB,YAAY,CACjC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,EACnB,KAAK,GAAE,MAAkB,EACzB,WAAW,GAAE,QAA4C,EACzD,cAAc,GAAE,MAAY,GAC1B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC,CAAC,CAa5C;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACvC,WAAW,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EACjC,OAAO,GAAE,OAAe,EACxB,KAAK,GAAE,MAAkB,EACzB,WAAW,GAAE,QAA4C,EACzD,cAAc,GAAE,MAAY,GAC1B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC,CAAC,CAI5C;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACtC,WAAW,EAAE,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,EACzC,OAAO,GAAE,OAAe,EACxB,KAAK,GAAE,MAAkB,EACzB,WAAW,GAAE,QAA4C,EACzD,cAAc,GAAE,MAAY,GAC1B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAiB1C"}
1
+ {"version":3,"file":"sources.d.ts","sourceRoot":"","sources":["../../../src/src/tools/sources.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAC9F,OAAO,EAA2B,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAE5C,YAAY,EAAE,MAAM,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAE9F;;GAEG;AACH,wBAAgB,YAAY,CAC3B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,KAAK,CAAC,YAAY,CAAC,EAC3B,QAAQ,GAAE,KAAK,CAAC,MAAM,CAAM,GAC1B,cAAc,CAoEhB;AAED,wBAAsB,aAAa,CAClC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,EACpC,MAAM,EAAE,KAAK,CAAC,YAAY,CAAC,EAC3B,QAAQ,GAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAM,GACjC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAIvC;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACtC,OAAO,EAAE,KAAK,CAAC,cAAc,CAAC,GAC5B;IAAE,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAAC,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;CAAE,CA8DjE;AAED,wBAAgB,qBAAqB,CACpC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,GACnC;IAAE,eAAe,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IAAC,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAA;CAAE,CAc/E;AAED;;GAEG;AACH,wBAAgB,WAAW,CAC1B,WAAW,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EACjC,OAAO,GAAE,OAAe,GACtB,KAAK,CAAC,MAAM,CAAC,CAgBf;AA+DD;;GAEG;AACH,wBAAsB,YAAY,CACjC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,EACnB,KAAK,GAAE,MAAkB,EACzB,WAAW,GAAE,cAAkD,EAC/D,cAAc,GAAE,MAAY,GAC1B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC,CAAC,CAc5C;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACvC,WAAW,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EACjC,OAAO,GAAE,OAAe,EACxB,KAAK,GAAE,MAAkB,EACzB,WAAW,GAAE,cAAkD,EAC/D,cAAc,GAAE,MAAY,GAC1B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC,CAAC,CAI5C;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACtC,WAAW,EAAE,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,EACzC,OAAO,GAAE,OAAe,EACxB,KAAK,GAAE,MAAkB,EACzB,WAAW,GAAE,cAAkD,EAC/D,cAAc,GAAE,MAAY,GAC1B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAiB1C"}
@@ -1,6 +1,5 @@
1
- import { mapParallel } from '../async.js';
2
1
  import { createBrandMatchKey } from './brands.js';
3
- import { assignTopic, createLabelSchema, toTopics } from './topics.js';
2
+ import { TopicAssigner, toTopics } from './topics.js';
4
3
  /**
5
4
  * Checks if brand or competitor is mentioned in the source title or URL.
6
5
  */
@@ -222,16 +221,16 @@ const WEB_TAXONOMY = {
222
221
  'Personal / Portfolio Site'
223
222
  ]
224
223
  };
225
- const WEB_LABEL_SCHEMA = createLabelSchema({ topics: toTopics(WEB_TAXONOMY) });
226
- const WEB_TAXONOMY_SERIALIZED = JSON.stringify(WEB_TAXONOMY, null, 2);
224
+ const WEB_TAXONOMY_TOPICS = toTopics(WEB_TAXONOMY);
227
225
  /**
228
226
  * Classifies an array of URLs into categories based on WEB_TAXONOMY.
229
227
  */
230
228
  export async function classifyURLs(urls, model = 'gpt-5.1', modelParams = { reasoning: { effort: 'none' } }, maxConcurrency = 100) {
231
- const labels = await mapParallel(urls, maxConcurrency, url => assignTopic(url, WEB_TAXONOMY_SERIALIZED, WEB_LABEL_SCHEMA, model, modelParams));
229
+ const assigner = new TopicAssigner({ taxonomy: WEB_TAXONOMY_TOPICS }, { model, modelParams, maxConcurrency });
230
+ const results = await assigner.batch(urls);
232
231
  const urlToCategory = {};
233
232
  urls.forEach((url, index) => {
234
- urlToCategory[url] = labels[index];
233
+ urlToCategory[url] = results.toArray()[index];
235
234
  });
236
235
  return urlToCategory;
237
236
  }