@trazum/core 1.8.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 (223) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +163 -0
  3. package/dist/advisories.d.ts +23 -0
  4. package/dist/advisories.d.ts.map +1 -0
  5. package/dist/advisories.js +376 -0
  6. package/dist/advisories.js.map +1 -0
  7. package/dist/aws-sigv4.d.ts +88 -0
  8. package/dist/aws-sigv4.d.ts.map +1 -0
  9. package/dist/aws-sigv4.js +117 -0
  10. package/dist/aws-sigv4.js.map +1 -0
  11. package/dist/baseline.d.ts +171 -0
  12. package/dist/baseline.d.ts.map +1 -0
  13. package/dist/baseline.js +273 -0
  14. package/dist/baseline.js.map +1 -0
  15. package/dist/cache.d.ts +26 -0
  16. package/dist/cache.d.ts.map +1 -0
  17. package/dist/cache.js +28 -0
  18. package/dist/cache.js.map +1 -0
  19. package/dist/changes.d.ts +29 -0
  20. package/dist/changes.d.ts.map +1 -0
  21. package/dist/changes.js +142 -0
  22. package/dist/changes.js.map +1 -0
  23. package/dist/compare.d.ts +65 -0
  24. package/dist/compare.d.ts.map +1 -0
  25. package/dist/compare.js +58 -0
  26. package/dist/compare.js.map +1 -0
  27. package/dist/config-schema.d.ts +118 -0
  28. package/dist/config-schema.d.ts.map +1 -0
  29. package/dist/config-schema.js +315 -0
  30. package/dist/config-schema.js.map +1 -0
  31. package/dist/config.d.ts +47 -0
  32. package/dist/config.d.ts.map +1 -0
  33. package/dist/config.js +112 -0
  34. package/dist/config.js.map +1 -0
  35. package/dist/detect.d.ts +70 -0
  36. package/dist/detect.d.ts.map +1 -0
  37. package/dist/detect.js +228 -0
  38. package/dist/detect.js.map +1 -0
  39. package/dist/evaluate.d.ts +98 -0
  40. package/dist/evaluate.d.ts.map +1 -0
  41. package/dist/evaluate.js +110 -0
  42. package/dist/evaluate.js.map +1 -0
  43. package/dist/extract.d.ts +81 -0
  44. package/dist/extract.d.ts.map +1 -0
  45. package/dist/extract.js +280 -0
  46. package/dist/extract.js.map +1 -0
  47. package/dist/gcp-auth.d.ts +58 -0
  48. package/dist/gcp-auth.d.ts.map +1 -0
  49. package/dist/gcp-auth.js +113 -0
  50. package/dist/gcp-auth.js.map +1 -0
  51. package/dist/glob.d.ts +49 -0
  52. package/dist/glob.d.ts.map +1 -0
  53. package/dist/glob.js +154 -0
  54. package/dist/glob.js.map +1 -0
  55. package/dist/host.d.ts +30 -0
  56. package/dist/host.d.ts.map +1 -0
  57. package/dist/host.js +69 -0
  58. package/dist/host.js.map +1 -0
  59. package/dist/i18n/en.d.ts +4 -0
  60. package/dist/i18n/en.d.ts.map +1 -0
  61. package/dist/i18n/en.js +168 -0
  62. package/dist/i18n/en.js.map +1 -0
  63. package/dist/i18n/es.d.ts +4 -0
  64. package/dist/i18n/es.d.ts.map +1 -0
  65. package/dist/i18n/es.js +168 -0
  66. package/dist/i18n/es.js.map +1 -0
  67. package/dist/i18n/index.d.ts +36 -0
  68. package/dist/i18n/index.d.ts.map +1 -0
  69. package/dist/i18n/index.js +50 -0
  70. package/dist/i18n/index.js.map +1 -0
  71. package/dist/i18n/types.d.ts +180 -0
  72. package/dist/i18n/types.d.ts.map +1 -0
  73. package/dist/i18n/types.js +11 -0
  74. package/dist/i18n/types.js.map +1 -0
  75. package/dist/index.d.ts +66 -0
  76. package/dist/index.d.ts.map +1 -0
  77. package/dist/index.js +69 -0
  78. package/dist/index.js.map +1 -0
  79. package/dist/llm.d.ts +226 -0
  80. package/dist/llm.d.ts.map +1 -0
  81. package/dist/llm.js +485 -0
  82. package/dist/llm.js.map +1 -0
  83. package/dist/nearest.d.ts +20 -0
  84. package/dist/nearest.d.ts.map +1 -0
  85. package/dist/nearest.js +54 -0
  86. package/dist/nearest.js.map +1 -0
  87. package/dist/net.d.ts +90 -0
  88. package/dist/net.d.ts.map +1 -0
  89. package/dist/net.js +203 -0
  90. package/dist/net.js.map +1 -0
  91. package/dist/node.d.ts +32 -0
  92. package/dist/node.d.ts.map +1 -0
  93. package/dist/node.js +33 -0
  94. package/dist/node.js.map +1 -0
  95. package/dist/openrouter.d.ts +25 -0
  96. package/dist/openrouter.d.ts.map +1 -0
  97. package/dist/openrouter.js +72 -0
  98. package/dist/openrouter.js.map +1 -0
  99. package/dist/optimize.d.ts +38 -0
  100. package/dist/optimize.d.ts.map +1 -0
  101. package/dist/optimize.js +183 -0
  102. package/dist/optimize.js.map +1 -0
  103. package/dist/otlp.d.ts +91 -0
  104. package/dist/otlp.d.ts.map +1 -0
  105. package/dist/otlp.js +102 -0
  106. package/dist/otlp.js.map +1 -0
  107. package/dist/phrases.d.ts +169 -0
  108. package/dist/phrases.d.ts.map +1 -0
  109. package/dist/phrases.js +939 -0
  110. package/dist/phrases.js.map +1 -0
  111. package/dist/pricing-overlay.d.ts +55 -0
  112. package/dist/pricing-overlay.d.ts.map +1 -0
  113. package/dist/pricing-overlay.js +241 -0
  114. package/dist/pricing-overlay.js.map +1 -0
  115. package/dist/pricing.d.ts +115 -0
  116. package/dist/pricing.d.ts.map +1 -0
  117. package/dist/pricing.js +400 -0
  118. package/dist/pricing.js.map +1 -0
  119. package/dist/profile.d.ts +71 -0
  120. package/dist/profile.d.ts.map +1 -0
  121. package/dist/profile.js +55 -0
  122. package/dist/profile.js.map +1 -0
  123. package/dist/promptfoo.d.ts +58 -0
  124. package/dist/promptfoo.d.ts.map +1 -0
  125. package/dist/promptfoo.js +149 -0
  126. package/dist/promptfoo.js.map +1 -0
  127. package/dist/prune.d.ts +91 -0
  128. package/dist/prune.d.ts.map +1 -0
  129. package/dist/prune.js +110 -0
  130. package/dist/prune.js.map +1 -0
  131. package/dist/reorder.d.ts +82 -0
  132. package/dist/reorder.d.ts.map +1 -0
  133. package/dist/reorder.js +215 -0
  134. package/dist/reorder.js.map +1 -0
  135. package/dist/review.d.ts +54 -0
  136. package/dist/review.d.ts.map +1 -0
  137. package/dist/review.js +131 -0
  138. package/dist/review.js.map +1 -0
  139. package/dist/rules.d.ts +5 -0
  140. package/dist/rules.d.ts.map +1 -0
  141. package/dist/rules.js +279 -0
  142. package/dist/rules.js.map +1 -0
  143. package/dist/savings.d.ts +36 -0
  144. package/dist/savings.d.ts.map +1 -0
  145. package/dist/savings.js +83 -0
  146. package/dist/savings.js.map +1 -0
  147. package/dist/segment.d.ts +8 -0
  148. package/dist/segment.d.ts.map +1 -0
  149. package/dist/segment.js +74 -0
  150. package/dist/segment.js.map +1 -0
  151. package/dist/shared-prefix.d.ts +63 -0
  152. package/dist/shared-prefix.d.ts.map +1 -0
  153. package/dist/shared-prefix.js +151 -0
  154. package/dist/shared-prefix.js.map +1 -0
  155. package/dist/similarity.d.ts +13 -0
  156. package/dist/similarity.d.ts.map +1 -0
  157. package/dist/similarity.js +30 -0
  158. package/dist/similarity.js.map +1 -0
  159. package/dist/structure.d.ts +144 -0
  160. package/dist/structure.d.ts.map +1 -0
  161. package/dist/structure.js +455 -0
  162. package/dist/structure.js.map +1 -0
  163. package/dist/suggest.d.ts +100 -0
  164. package/dist/suggest.d.ts.map +1 -0
  165. package/dist/suggest.js +151 -0
  166. package/dist/suggest.js.map +1 -0
  167. package/dist/tokenizer.d.ts +57 -0
  168. package/dist/tokenizer.d.ts.map +1 -0
  169. package/dist/tokenizer.js +157 -0
  170. package/dist/tokenizer.js.map +1 -0
  171. package/dist/types.d.ts +296 -0
  172. package/dist/types.d.ts.map +1 -0
  173. package/dist/types.js +3 -0
  174. package/dist/types.js.map +1 -0
  175. package/dist/walk.d.ts +40 -0
  176. package/dist/walk.d.ts.map +1 -0
  177. package/dist/walk.js +95 -0
  178. package/dist/walk.js.map +1 -0
  179. package/package.json +56 -0
  180. package/src/advisories.ts +431 -0
  181. package/src/aws-sigv4.ts +174 -0
  182. package/src/baseline.ts +390 -0
  183. package/src/cache.ts +54 -0
  184. package/src/changes.ts +158 -0
  185. package/src/compare.ts +131 -0
  186. package/src/config-schema.ts +451 -0
  187. package/src/config.ts +161 -0
  188. package/src/detect.ts +312 -0
  189. package/src/evaluate.ts +188 -0
  190. package/src/extract.ts +336 -0
  191. package/src/gcp-auth.ts +166 -0
  192. package/src/glob.ts +160 -0
  193. package/src/host.ts +90 -0
  194. package/src/i18n/en.ts +236 -0
  195. package/src/i18n/es.ts +236 -0
  196. package/src/i18n/index.ts +68 -0
  197. package/src/i18n/types.ts +230 -0
  198. package/src/index.ts +228 -0
  199. package/src/llm.ts +708 -0
  200. package/src/nearest.ts +61 -0
  201. package/src/net.ts +233 -0
  202. package/src/node.ts +63 -0
  203. package/src/openrouter.ts +125 -0
  204. package/src/optimize.ts +228 -0
  205. package/src/otlp.ts +179 -0
  206. package/src/phrases.ts +1047 -0
  207. package/src/pricing-overlay.ts +319 -0
  208. package/src/pricing.ts +468 -0
  209. package/src/profile.ts +124 -0
  210. package/src/promptfoo.ts +213 -0
  211. package/src/prune.ts +211 -0
  212. package/src/reorder.ts +307 -0
  213. package/src/review.ts +180 -0
  214. package/src/rules.ts +324 -0
  215. package/src/savings.ts +121 -0
  216. package/src/segment.ts +106 -0
  217. package/src/shared-prefix.ts +198 -0
  218. package/src/similarity.ts +28 -0
  219. package/src/structure.ts +652 -0
  220. package/src/suggest.ts +254 -0
  221. package/src/tokenizer.ts +190 -0
  222. package/src/types.ts +323 -0
  223. package/src/walk.ts +117 -0
@@ -0,0 +1,296 @@
1
+ /** Public types of @trazum/core. */
2
+ import type { RuleChange } from './changes.js';
3
+ import type { Locale, RuleId } from './i18n/types.js';
4
+ import type { PricingCatalogue } from './pricing.js';
5
+ /** How aggressive the deterministic rules are allowed to be. */
6
+ export type RuleLevel = 'safe' | 'aggressive';
7
+ /**
8
+ * A deterministic rule applied to the mutable text of a prompt.
9
+ *
10
+ * The rule carries no copy of its own: its title and rationale live in the
11
+ * locale catalogues, keyed by `id`. That is what lets the same rule report
12
+ * itself in any language.
13
+ */
14
+ export interface Rule {
15
+ id: RuleId;
16
+ level: RuleLevel;
17
+ /** Returns the transformed text and how many times the rule applied. */
18
+ apply(text: string): {
19
+ text: string;
20
+ hits: number;
21
+ };
22
+ }
23
+ /** A rule after it has run, with its copy already resolved for a locale. */
24
+ export interface RuleResult {
25
+ id: RuleId;
26
+ title: string;
27
+ rationale: string;
28
+ level: RuleLevel;
29
+ hits: number;
30
+ /** Tokens saved attributable to this rule (estimated). */
31
+ tokensSaved: number;
32
+ /**
33
+ * A sample of what this rule actually changed, so an aggressive run can be
34
+ * reviewed rule by rule. Capped — `hits` carries the true total — and empty
35
+ * when the change was too large to summarise usefully.
36
+ */
37
+ changes: RuleChange[];
38
+ }
39
+ /** Severity of an advisory: the higher it is, the more money is usually at stake. */
40
+ export type AdvisorySeverity = 'info' | 'opportunity' | 'warning';
41
+ /** Every advisory the core can emit. */
42
+ export type AdvisoryId = 'context-overflow' | 'prompt-caching' | 'prompt-caching-not-worth-it' | 'below-cache-minimum' | 'cache-prefix-reorder' | 'batch-api' | 'model-downgrade' | 'output-dominated' | 'promo-pricing' | 'contradictory-instructions' | 'redundant-examples' | 'restated-output-format' | 'movable-output-schema';
43
+ /** A recommendation that does NOT modify the prompt, only informs. */
44
+ export interface Advisory {
45
+ id: AdvisoryId;
46
+ severity: AdvisorySeverity;
47
+ title: string;
48
+ detail: string;
49
+ /** Estimated monthly saving in USD if applied. `null` when not quantifiable. */
50
+ estimatedMonthlyUsd: number | null;
51
+ }
52
+ /** Price of a model, in USD per million tokens. */
53
+ /**
54
+ * How a provider prices caching and batching.
55
+ *
56
+ * These were global constants until models from other providers arrived, and
57
+ * being global made them quietly wrong: a cache read costs about 10% of the
58
+ * input price on Anthropic and about 50% on OpenAI. One number for both would
59
+ * have overstated an OpenAI caching saving fivefold — an invented saving, which
60
+ * is the one thing this tool must never print.
61
+ *
62
+ * Every field is optional and falls back to the Anthropic values, so a model
63
+ * added without them prices exactly as it did before.
64
+ */
65
+ export interface CostMultipliers {
66
+ /** Cache read as a fraction of the input price. */
67
+ cacheRead?: number;
68
+ /** Cache write with the short TTL, as a multiple of the input price. */
69
+ cacheWrite5m?: number;
70
+ /** Cache write with the long TTL, where the provider offers one. */
71
+ cacheWrite1h?: number;
72
+ /**
73
+ * Batch discount, or `null` where the provider has no batch API. `null` and
74
+ * `undefined` mean different things here: "there is no batch API" versus
75
+ * "nobody has said", and only the first should stop the advisory firing.
76
+ */
77
+ batch?: number | null;
78
+ }
79
+ /**
80
+ * How prompt caching is turned on.
81
+ *
82
+ * The advice to move stable content into the prefix is the same everywhere,
83
+ * because prefix caching is prefix caching. What differs is whether you have to
84
+ * ask for it: telling an OpenAI user to "set cache_control" names a parameter
85
+ * that does not exist for them.
86
+ */
87
+ export type CachingMode =
88
+ /** The caller marks the prefix, e.g. Anthropic's `cache_control`. */
89
+ 'explicit'
90
+ /** The provider caches long-enough prefixes with no marker. */
91
+ | 'automatic'
92
+ /** No prompt caching at all. */
93
+ | 'none'
94
+ /**
95
+ * Nobody here knows, and saying so beats guessing.
96
+ *
97
+ * A catalogue can now be built from a live source — OpenRouter publishes
98
+ * price and context window for hundreds of models — and that source publishes
99
+ * neither whether a model caches nor the minimum prefix it caches at. Both
100
+ * halves of the caching advisory need those, and that advisory is the largest
101
+ * saving Trazum reports.
102
+ *
103
+ * The two wrong answers are symmetrical. Assume caching works and Trazum
104
+ * offers a saving that cannot be bought at any price, which is the Mistral
105
+ * bug in a new costume. Assume it does not and Trazum hides the biggest
106
+ * saving there is. So: `unknown` fires nothing and the report says the
107
+ * catalogue does not know, which is a fact the reader can act on.
108
+ */
109
+ | 'unknown';
110
+ /**
111
+ * Capability, without a vendor's ladder in the name.
112
+ *
113
+ * `tier` used Anthropic's own names as the generic axis, which reads as nonsense
114
+ * the moment the model is not Anthropic's — telling somebody on Kimi that their
115
+ * task "looks like haiku complexity" is a label that means something other than
116
+ * what it says.
117
+ */
118
+ export type Capability = 'small' | 'mid' | 'large' | 'frontier' | 'unknown';
119
+ export interface ModelPricing {
120
+ id: string;
121
+ displayName: string;
122
+ /** Who sells it. Used to group the model list and to explain caching. */
123
+ provider?: string;
124
+ /** USD per 1M input tokens. */
125
+ inputPerMTok: number;
126
+ /** USD per 1M output tokens. */
127
+ outputPerMTok: number;
128
+ /** Context window in tokens. */
129
+ contextWindow: number;
130
+ /**
131
+ * Minimum tokens before prompt caching actually caches.
132
+ *
133
+ * `null` when the catalogue does not know — see `CachingMode.unknown`. A
134
+ * number here is a claim about a specific provider's behaviour, and a live
135
+ * price feed is not a source for it.
136
+ */
137
+ cacheMinTokens: number | null;
138
+ /** How caching is enabled. Defaults to `explicit`. */
139
+ caching?: CachingMode;
140
+ /** Provider-specific cache and batch pricing. Defaults to Anthropic's. */
141
+ multipliers?: CostMultipliers;
142
+ /**
143
+ * Whether to offer this model as a cheaper alternative.
144
+ *
145
+ * Defaults to true. A model behind a private programme or a waitlist is real
146
+ * and worth pricing, but recommending a switch to something the reader cannot
147
+ * buy is advice that wastes their time.
148
+ */
149
+ recommendable?: boolean;
150
+ /** Capability, on a vendor-neutral scale. */
151
+ capability: Capability;
152
+ /**
153
+ * @deprecated Use `capability`. Anthropic's ladder used as a generic axis
154
+ * stopped making sense once other providers were priced. Kept in step with
155
+ * `capability` for the whole of 1.x and removed in 2.0 — see VERSIONING.md.
156
+ */
157
+ tier: 'haiku' | 'sonnet' | 'opus' | 'frontier' | 'unknown';
158
+ /** Promotional pricing, when one is running. */
159
+ promo?: {
160
+ inputPerMTok: number;
161
+ outputPerMTok: number;
162
+ /** ISO date (inclusive) the promotional price applies until. */
163
+ until: string;
164
+ };
165
+ /** Notes relevant to cost calculation. */
166
+ notes?: string;
167
+ }
168
+ /** Usage scenario used to turn token savings into money. */
169
+ export interface UsageProfile {
170
+ /** Model the cost is computed against. */
171
+ model: string;
172
+ /** Calls per month using this prompt. */
173
+ callsPerMonth: number;
174
+ /** Average output tokens per call. */
175
+ avgOutputTokens: number;
176
+ /**
177
+ * Fraction of calls that would reuse the cached prefix (0-1).
178
+ * Only used by the prompt caching advisory.
179
+ */
180
+ cacheHitRate: number;
181
+ /** If the work tolerates latency, the Batch API costs half. */
182
+ batchEligible: boolean;
183
+ }
184
+ /** Itemised cost of a scenario. */
185
+ export interface CostBreakdown {
186
+ inputUsd: number;
187
+ outputUsd: number;
188
+ totalUsd: number;
189
+ }
190
+ /** Before/after cost comparison. */
191
+ export interface SavingsReport {
192
+ model: string;
193
+ modelDisplayName: string;
194
+ /** Whether a promotional price is currently being applied. */
195
+ promoApplied: boolean;
196
+ perCall: {
197
+ before: CostBreakdown;
198
+ after: CostBreakdown;
199
+ };
200
+ perMonth: {
201
+ before: CostBreakdown;
202
+ after: CostBreakdown;
203
+ };
204
+ monthlySavingsUsd: number;
205
+ /** Percentage saved against the total monthly cost (0-100). */
206
+ monthlySavingsPct: number;
207
+ }
208
+ /** A slice of the prompt: protected slices are never modified. */
209
+ export interface Segment {
210
+ kind: 'mutable' | 'protected';
211
+ /** What kind of protected content this is (for diagnostics). */
212
+ protection?: ProtectionKind;
213
+ text: string;
214
+ }
215
+ export type ProtectionKind = 'fenced-code' | 'inline-code' | 'url' | 'placeholder' | 'xml-tag';
216
+ /** Optimisation options. */
217
+ export interface OptimizeOptions {
218
+ /** `safe` (the default) only applies rules with no semantic risk. */
219
+ level?: RuleLevel;
220
+ /** Rule ids to disable. */
221
+ disableRules?: RuleId[];
222
+ /** Usage profile used to quantify the saving. */
223
+ usage?: Partial<UsageProfile>;
224
+ /** Alternative token counter (e.g. the real token-counting API). */
225
+ tokenCounter?: TokenCounter;
226
+ /** Language of the report. Defaults to English. */
227
+ locale?: Locale;
228
+ /**
229
+ * Prices to work from. Defaults to the catalogue bundled with this release.
230
+ *
231
+ * Build one with `applyPricingOverlay` when a published price has moved: a
232
+ * stale price is a wrong number in a budget decision, and correcting it should
233
+ * not require a library upgrade.
234
+ */
235
+ pricing?: PricingCatalogue;
236
+ }
237
+ /** Counts tokens in a text. Synchronous so it can run inside the rule loop. */
238
+ export type TokenCounter = (text: string) => number;
239
+ /** Full result of an optimisation. */
240
+ export interface OptimizationResult {
241
+ original: string;
242
+ optimized: string;
243
+ tokensBefore: number;
244
+ tokensAfter: number;
245
+ tokensSaved: number;
246
+ /** Percentage reduction of input tokens (0-100). */
247
+ reductionPct: number;
248
+ rules: RuleResult[];
249
+ advisories: Advisory[];
250
+ savings: SavingsReport;
251
+ usage: UsageProfile;
252
+ /** Locale the report was rendered in. */
253
+ locale: Locale;
254
+ /** How tokens were counted, so the caller knows the margin of error. */
255
+ tokenSource: 'heuristic' | 'external';
256
+ /**
257
+ * Where the prices came from.
258
+ *
259
+ * Reported rather than assumed: once prices can be overlaid locally, a figure
260
+ * from the bundled catalogue and a figure from somebody's JSON file look
261
+ * identical, and a reader has to be able to tell which they are reading.
262
+ */
263
+ pricingSource: {
264
+ lastReviewed: string;
265
+ /** Bundled prices an overlay replaced. Empty when none did. */
266
+ overriddenModels: string[];
267
+ /** Models an overlay introduced. Empty when none did. */
268
+ addedModels: string[];
269
+ };
270
+ /** Present only when an LLM pass ran. */
271
+ llm?: LlmRefinement;
272
+ }
273
+ /** Result of the optional LLM pass. */
274
+ export interface LlmRefinement {
275
+ applied: boolean;
276
+ /** Why it was not applied, when `applied` is false. */
277
+ rejectedReason?: string;
278
+ provider: string;
279
+ model: string;
280
+ candidate: string;
281
+ tokensBefore: number;
282
+ tokensAfter: number;
283
+ }
284
+ /** Pluggable LLM provider: this is where your own model plugs in. */
285
+ export interface LlmProvider {
286
+ /** Human-readable name, shown in the report. */
287
+ name: string;
288
+ /** Identifier of the model used. */
289
+ model: string;
290
+ complete(input: {
291
+ system: string;
292
+ user: string;
293
+ }): Promise<string>;
294
+ }
295
+ export type { Locale, RuleId };
296
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ /** Public types of @trazum/core. */
2
+ export {};
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,oCAAoC"}
package/dist/walk.d.ts ADDED
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Finding the prompt files under a directory.
3
+ *
4
+ * Three things this deliberately does not do, each because of what it would
5
+ * mean on a CI runner reading a repository somebody else opened a pull request
6
+ * against:
7
+ *
8
+ * 1. **It does not follow symlinks.** A link is skipped, not resolved. A link
9
+ * to `/etc` or to a parent directory turns "check the prompts folder" into
10
+ * reading and printing token counts for files outside the project, and a
11
+ * link loop turns it into a hang.
12
+ * 2. **It does not walk without bound.** Depth and file count are capped, and
13
+ * hitting the cap is reported rather than silently truncating the list —
14
+ * "0 files over budget" and "I stopped looking" must not read the same.
15
+ * 3. **It does not guess at what a prompt is.** Only the configured extensions
16
+ * are read. Everything else is left alone rather than tokenised on the
17
+ * chance it might be a prompt.
18
+ */
19
+ export declare const MAX_WALK_DEPTH = 12;
20
+ export declare const MAX_WALK_FILES = 2000;
21
+ export interface WalkResult {
22
+ /** Matching files, as paths relative to the root, with `/` separators. */
23
+ files: string[];
24
+ /** True when a cap stopped the walk early, so the caller can say so. */
25
+ truncated: boolean;
26
+ }
27
+ export interface WalkOptions {
28
+ extensions?: readonly string[];
29
+ maxFiles?: number;
30
+ maxDepth?: number;
31
+ }
32
+ /**
33
+ * Lists prompt files under `root`, relative to it and sorted.
34
+ *
35
+ * Sorted because the output is read by humans and compared between runs: a
36
+ * report whose row order depends on the filesystem's directory order is one
37
+ * nobody can diff.
38
+ */
39
+ export declare function walkPrompts(root: string, options?: WalkOptions): Promise<WalkResult>;
40
+ //# sourceMappingURL=walk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"walk.d.ts","sourceRoot":"","sources":["../src/walk.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;GAiBG;AAEH,eAAO,MAAM,cAAc,KAAK,CAAC;AACjC,eAAO,MAAM,cAAc,OAAO,CAAC;AAenC,MAAM,WAAW,UAAU;IACzB,0EAA0E;IAC1E,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,wEAAwE;IACxE,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,UAAU,CAAC,CAwD9F"}
package/dist/walk.js ADDED
@@ -0,0 +1,95 @@
1
+ import { readdir } from 'node:fs/promises';
2
+ import { extname, join, relative, sep } from 'node:path';
3
+ import { DEFAULT_EXTENSIONS } from './config-schema.js';
4
+ /**
5
+ * Finding the prompt files under a directory.
6
+ *
7
+ * Three things this deliberately does not do, each because of what it would
8
+ * mean on a CI runner reading a repository somebody else opened a pull request
9
+ * against:
10
+ *
11
+ * 1. **It does not follow symlinks.** A link is skipped, not resolved. A link
12
+ * to `/etc` or to a parent directory turns "check the prompts folder" into
13
+ * reading and printing token counts for files outside the project, and a
14
+ * link loop turns it into a hang.
15
+ * 2. **It does not walk without bound.** Depth and file count are capped, and
16
+ * hitting the cap is reported rather than silently truncating the list —
17
+ * "0 files over budget" and "I stopped looking" must not read the same.
18
+ * 3. **It does not guess at what a prompt is.** Only the configured extensions
19
+ * are read. Everything else is left alone rather than tokenised on the
20
+ * chance it might be a prompt.
21
+ */
22
+ export const MAX_WALK_DEPTH = 12;
23
+ export const MAX_WALK_FILES = 2000;
24
+ /** Directories never worth descending into, and expensive when they are. */
25
+ const SKIPPED_DIRECTORIES = new Set([
26
+ 'node_modules',
27
+ '.git',
28
+ '.next',
29
+ 'dist',
30
+ 'build',
31
+ 'coverage',
32
+ 'vendor',
33
+ '.venv',
34
+ '__pycache__',
35
+ ]);
36
+ /**
37
+ * Lists prompt files under `root`, relative to it and sorted.
38
+ *
39
+ * Sorted because the output is read by humans and compared between runs: a
40
+ * report whose row order depends on the filesystem's directory order is one
41
+ * nobody can diff.
42
+ */
43
+ export async function walkPrompts(root, options = {}) {
44
+ const extensions = (options.extensions ?? DEFAULT_EXTENSIONS).map((value) => value.toLowerCase());
45
+ const maxFiles = options.maxFiles ?? MAX_WALK_FILES;
46
+ const maxDepth = options.maxDepth ?? MAX_WALK_DEPTH;
47
+ const files = [];
48
+ let truncated = false;
49
+ const visit = async (directory, depth) => {
50
+ if (depth > maxDepth) {
51
+ truncated = true;
52
+ return;
53
+ }
54
+ let entries;
55
+ try {
56
+ entries = await readdir(directory, { withFileTypes: true });
57
+ }
58
+ catch {
59
+ // An unreadable directory is skipped rather than fatal: one permission
60
+ // problem deep in a tree should not throw away the rest of the report.
61
+ return;
62
+ }
63
+ // Sorted here as well as at the end, so the file that trips the cap is the
64
+ // same one on every run.
65
+ entries.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
66
+ for (const entry of entries) {
67
+ if (files.length >= maxFiles) {
68
+ truncated = true;
69
+ return;
70
+ }
71
+ // Skipped before the type checks: a symlink is never followed, whatever
72
+ // it points at.
73
+ if (entry.isSymbolicLink())
74
+ continue;
75
+ if (entry.name.startsWith('.'))
76
+ continue;
77
+ const full = join(directory, entry.name);
78
+ if (entry.isDirectory()) {
79
+ if (SKIPPED_DIRECTORIES.has(entry.name))
80
+ continue;
81
+ await visit(full, depth + 1);
82
+ continue;
83
+ }
84
+ if (!entry.isFile())
85
+ continue;
86
+ if (!extensions.includes(extname(entry.name).toLowerCase()))
87
+ continue;
88
+ files.push(relative(root, full).split(sep).join('/'));
89
+ }
90
+ };
91
+ await visit(root, 0);
92
+ files.sort();
93
+ return { files, truncated };
94
+ }
95
+ //# sourceMappingURL=walk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"walk.js","sourceRoot":"","sources":["../src/walk.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@trazum/core",
3
+ "version": "1.8.0",
4
+ "description": "Trazum core: priced advisories for LLM prompts (caching, model tier, batching, schemas), plus deterministic trimming, token counting and pricing.",
5
+ "license": "MIT",
6
+ "author": "David Mu\u00f1oz Rey",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/Davmunrey/Trazum.git",
10
+ "directory": "packages/core"
11
+ },
12
+ "keywords": [
13
+ "prompt",
14
+ "llm",
15
+ "tokens",
16
+ "cost",
17
+ "optimizer",
18
+ "claude",
19
+ "openai"
20
+ ],
21
+ "publishConfig": {
22
+ "access": "public"
23
+ },
24
+ "type": "module",
25
+ "main": "./dist/index.js",
26
+ "types": "./dist/index.d.ts",
27
+ "exports": {
28
+ ".": {
29
+ "types": "./dist/index.d.ts",
30
+ "default": "./dist/index.js"
31
+ },
32
+ "./node": {
33
+ "types": "./dist/node.d.ts",
34
+ "default": "./dist/node.js"
35
+ }
36
+ },
37
+ "files": [
38
+ "dist",
39
+ "src",
40
+ "LICENSE",
41
+ "README.md"
42
+ ],
43
+ "scripts": {
44
+ "build": "tsc -p tsconfig.json",
45
+ "test": "npm run build && node --test test/*.test.js",
46
+ "typecheck": "tsc -p tsconfig.json --noEmit",
47
+ "prepublishOnly": "npm run build && npm test"
48
+ },
49
+ "devDependencies": {
50
+ "@types/node": "^26.2.0",
51
+ "typescript": "^7.0.2"
52
+ },
53
+ "engines": {
54
+ "node": ">=20"
55
+ }
56
+ }