@rudra-js/core 0.6.0 → 0.7.1

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 (66) hide show
  1. package/README.md +13 -12
  2. package/dist/claim-screening.d.ts +0 -23
  3. package/dist/claim-screening.d.ts.map +1 -1
  4. package/dist/claim-screening.js +0 -69
  5. package/dist/claim-screening.js.map +1 -1
  6. package/dist/component-generator.d.ts +0 -70
  7. package/dist/component-generator.d.ts.map +1 -1
  8. package/dist/component-generator.js +10 -52
  9. package/dist/component-generator.js.map +1 -1
  10. package/dist/component-spec.d.ts +2 -110
  11. package/dist/component-spec.d.ts.map +1 -1
  12. package/dist/component-spec.js +0 -78
  13. package/dist/component-spec.js.map +1 -1
  14. package/dist/fallback-component.d.ts +0 -9
  15. package/dist/fallback-component.d.ts.map +1 -1
  16. package/dist/fallback-component.js +0 -11
  17. package/dist/fallback-component.js.map +1 -1
  18. package/dist/fit-to-shopper.d.ts.map +1 -1
  19. package/dist/fit-to-shopper.js +1 -11
  20. package/dist/fit-to-shopper.js.map +1 -1
  21. package/dist/index.d.ts +0 -7
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +0 -7
  24. package/dist/index.js.map +1 -1
  25. package/dist/model-prompt.d.ts +0 -29
  26. package/dist/model-prompt.d.ts.map +1 -1
  27. package/dist/model-prompt.js +0 -79
  28. package/dist/model-prompt.js.map +1 -1
  29. package/dist/product-selection.d.ts +0 -23
  30. package/dist/product-selection.d.ts.map +1 -1
  31. package/dist/product-selection.js +0 -19
  32. package/dist/product-selection.js.map +1 -1
  33. package/dist/provider.d.ts +0 -48
  34. package/dist/provider.d.ts.map +1 -1
  35. package/dist/provider.js +0 -5
  36. package/dist/provider.js.map +1 -1
  37. package/dist/reconciliation.d.ts +1 -44
  38. package/dist/reconciliation.d.ts.map +1 -1
  39. package/dist/reconciliation.js +2 -109
  40. package/dist/reconciliation.js.map +1 -1
  41. package/dist/signal-digest.d.ts +0 -27
  42. package/dist/signal-digest.d.ts.map +1 -1
  43. package/dist/signal-digest.js +1 -50
  44. package/dist/signal-digest.js.map +1 -1
  45. package/dist/spec-cache.d.ts +6 -80
  46. package/dist/spec-cache.d.ts.map +1 -1
  47. package/dist/spec-cache.js +1 -54
  48. package/dist/spec-cache.js.map +1 -1
  49. package/dist/tracking-input.d.ts +0 -49
  50. package/dist/tracking-input.d.ts.map +1 -1
  51. package/dist/tracking-input.js +0 -102
  52. package/dist/tracking-input.js.map +1 -1
  53. package/package.json +8 -7
  54. package/src/claim-screening.ts +17 -69
  55. package/src/component-generator.ts +24 -133
  56. package/src/component-spec.ts +15 -103
  57. package/src/fallback-component.ts +0 -11
  58. package/src/fit-to-shopper.ts +3 -12
  59. package/src/index.ts +0 -8
  60. package/src/model-prompt.ts +1 -82
  61. package/src/product-selection.ts +5 -43
  62. package/src/provider.ts +4 -53
  63. package/src/reconciliation.ts +12 -112
  64. package/src/signal-digest.ts +5 -64
  65. package/src/spec-cache.ts +8 -98
  66. package/src/tracking-input.ts +11 -108
@@ -1,72 +1,8 @@
1
1
  import { z } from 'zod';
2
- /**
3
- * The component specification — the only thing a language model is ever allowed
4
- * to return.
5
- *
6
- * The model chooses layout, ordering, emphasis and copy. Which products to show
7
- * and why is its call only in per-shopper mode, apart from the product a hero
8
- * names. It never returns markup, code, URLs, prices, product titles, or
9
- * images. Every field is an enum, a bounded number, a SKU reference resolved
10
- * against the candidate set, or free text that is clamped and escaped before it
11
- * renders. That is what makes generated output safe to put in a server-rendered
12
- * response.
13
- *
14
- * Two constraints shape this file, and both are easy to undo by accident:
15
- *
16
- * 1. It doubles as a provider structured-output schema, so it avoids
17
- * recursion, string length bounds, and numeric ranges. Providers reject
18
- * schemas that use them in strict mode. Bounds are enforced afterwards, in
19
- * reconciliation, where a violation can be repaired rather than fatal.
20
- * 2. Optionality is `.nullable()` rather than `.optional()`, because strict
21
- * structured outputs require every declared property to be present. "No
22
- * badge" has to be expressible as `null`, not as a missing key.
23
- *
24
- * A test asserts both by converting this schema to JSON Schema, so neither is
25
- * left to a comment nobody reads.
26
- *
27
- * Note the asymmetry with `tracking-input`, which rejects unknown fields: these
28
- * schemas strip them. The inputs differ in kind. An unrecognised key in a host
29
- * payload is a typo, and silently dropping it costs the shopper their history,
30
- * so it must be loud. An unrecognised key from a model is drift, and discarding
31
- * it is exactly right — rejecting the whole spec over one stray key would cost
32
- * the shopper the component. Either way the renderer only ever sees the fields
33
- * declared here, which is the property that matters.
34
- */
35
- /** Overall voice of the component. */
36
2
  export declare const TONES: readonly ['neutral', 'enthusiastic', 'urgent', 'editorial'];
37
- /** What a banner is claiming. */
38
3
  export declare const BANNER_TONES: readonly ['info', 'promo', 'urgency', 'restock'];
39
- /** How prominently a single product is placed. */
40
4
  export declare const EMPHASIS: readonly ['normal', 'featured'];
41
- /**
42
- * Why a product was chosen — the recommendation strategy behind the pick.
43
- *
44
- * This is a closed set rather than free text because every value here is a
45
- * factual claim about the shopper, and a claim the server can check. "Because
46
- * you viewed this" written as prose is unverifiable: nothing downstream can
47
- * tell whether the shopper viewed anything. Declared as `most_viewed`,
48
- * reconciliation can look it up in the digest and drop the claim if it is
49
- * false.
50
- *
51
- * Every value is deliberately checkable against data already in hand — the
52
- * signal digest or the host's own catalog. A basis that needs data the
53
- * framework never receives (`new_arrival`, `back_in_stock`, `trending_today`)
54
- * is not in this list, because it could only ever be taken on trust.
55
- */
56
- export declare const RECOMMENDATION_BASES: readonly [
57
- /** Same category as the product being viewed. */
58
- 'similar_to_current',
59
- /** The shopper has viewed this product. */
60
- 'most_viewed',
61
- /** Goes with something already in the cart. */
62
- 'complements_cart',
63
- /** Goes with something the shopper has bought. */
64
- 'complements_purchase',
65
- /** In a category the shopper's signals favour. */
66
- 'liked_category',
67
- /** No claim about this shopper at all — the safe default. */
68
- 'popular'];
69
- /** A reference to one product from the candidate set, and why it was chosen. */
5
+ export declare const RECOMMENDATION_BASES: readonly ['similar_to_current', 'most_viewed', 'complements_cart', 'complements_purchase', 'liked_category', 'popular'];
70
6
  export declare const productReferenceSchema: z.ZodObject<{
71
7
  sku: z.ZodString;
72
8
  basis: z.ZodEnum<{
@@ -86,7 +22,6 @@ export declare const productReferenceSchema: z.ZodObject<{
86
22
  }, z.core.$strip>;
87
23
  export type ProductReference = z.infer<typeof productReferenceSchema>;
88
24
  export type RecommendationBasis = (typeof RECOMMENDATION_BASES)[number];
89
- /** One large featured statement, optionally anchored to a single product. */
90
25
  declare const heroBlockSchema: z.ZodObject<{
91
26
  kind: z.ZodLiteral<"hero">;
92
27
  headline: z.ZodString;
@@ -94,7 +29,6 @@ declare const heroBlockSchema: z.ZodObject<{
94
29
  sku: z.ZodNullable<z.ZodString>;
95
30
  ctaLabel: z.ZodNullable<z.ZodString>;
96
31
  }, z.core.$strip>;
97
- /** The general-purpose choice when several products are comparably relevant. */
98
32
  declare const gridBlockSchema: z.ZodObject<{
99
33
  kind: z.ZodLiteral<"grid">;
100
34
  title: z.ZodNullable<z.ZodString>;
@@ -117,7 +51,6 @@ declare const gridBlockSchema: z.ZodObject<{
117
51
  }>;
118
52
  }, z.core.$strip>>;
119
53
  }, z.core.$strip>;
120
- /** A horizontally scanned row, for when order implies a ranking. */
121
54
  declare const carouselBlockSchema: z.ZodObject<{
122
55
  kind: z.ZodLiteral<"carousel">;
123
56
  title: z.ZodNullable<z.ZodString>;
@@ -139,7 +72,6 @@ declare const carouselBlockSchema: z.ZodObject<{
139
72
  }>;
140
73
  }, z.core.$strip>>;
141
74
  }, z.core.$strip>;
142
- /** A single line of merchandising copy. */
143
75
  declare const bannerBlockSchema: z.ZodObject<{
144
76
  kind: z.ZodLiteral<"banner">;
145
77
  tone: z.ZodEnum<{
@@ -151,13 +83,11 @@ declare const bannerBlockSchema: z.ZodObject<{
151
83
  text: z.ZodString;
152
84
  ctaLabel: z.ZodNullable<z.ZodString>;
153
85
  }, z.core.$strip>;
154
- /** Short editorial prose, for explaining the theme of a selection. */
155
86
  declare const copyBlockSchema: z.ZodObject<{
156
87
  kind: z.ZodLiteral<"copy">;
157
88
  title: z.ZodNullable<z.ZodString>;
158
89
  body: z.ZodString;
159
90
  }, z.core.$strip>;
160
- /** A set the shop sells together. The shop picks which one; this only asks for it. */
161
91
  declare const bundleBlockSchema: z.ZodObject<{
162
92
  kind: z.ZodLiteral<"bundle">;
163
93
  title: z.ZodNullable<z.ZodString>;
@@ -165,7 +95,6 @@ declare const bundleBlockSchema: z.ZodObject<{
165
95
  ctaLabel: z.ZodNullable<z.ZodString>;
166
96
  bundleId: z.ZodNullable<z.ZodString>;
167
97
  }, z.core.$strip>;
168
- /** Blocks do not nest. The vocabulary is closed on purpose. */
169
98
  export declare const blockSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
170
99
  kind: z.ZodLiteral<"hero">;
171
100
  headline: z.ZodString;
@@ -242,11 +171,6 @@ export type CarouselBlock = z.infer<typeof carouselBlockSchema>;
242
171
  export type BannerBlock = z.infer<typeof bannerBlockSchema>;
243
172
  export type CopyBlock = z.infer<typeof copyBlockSchema>;
244
173
  export type BundleBlock = z.infer<typeof bundleBlockSchema>;
245
- /**
246
- * Exactly what the model must return. Provenance — version, slot, latency, which
247
- * provider answered — is added by the server afterwards, and is deliberately not
248
- * part of the model's burden.
249
- */
250
174
  export declare const generatedSpecSchema: z.ZodObject<{
251
175
  tone: z.ZodEnum<{
252
176
  editorial: "editorial";
@@ -328,52 +252,20 @@ export declare const generatedSpecSchema: z.ZodObject<{
328
252
  }, z.core.$strip>;
329
253
  export type GeneratedSpec = z.infer<typeof generatedSpecSchema>;
330
254
  export type GeneratedSpecResult = z.ZodSafeParseResult<GeneratedSpec>;
331
- /** How a spec came to exist. Surfaced for benchmarking and observability. */
332
255
  export type SpecSource = 'llm' | 'cache' | 'fallback';
333
- /**
334
- * Why a component is not what the model would have produced.
335
- *
336
- * A closed set, like `SpecSource`: it is rendered into pages as
337
- * `data-rudra-degraded` and counted in dashboards, so a host needs to know what
338
- * it can receive without reading the generator.
339
- */
340
- export type DegradedReason =
341
- /** No provider was configured, so nothing was ever asked. */
342
- 'no-provider'
343
- /** The provider errored, or threw before it reached the vendor. */
344
- | 'provider-error'
345
- /** The deadline fired before an answer arrived. */
346
- | 'timeout'
347
- /** An answer came back that did not satisfy the schema. */
348
- | 'invalid-generation'
349
- /** A usable answer reconciled down to nothing for this shopper. */
350
- | 'unusable-on-serve'
351
- /** The caller asked for the deterministic component on purpose. */
352
- | 'requested';
256
+ export type DegradedReason = 'no-provider' | 'provider-error' | 'timeout' | 'invalid-generation' | 'unusable-on-serve' | 'requested';
353
257
  export declare const SPEC_VERSION: '1';
354
- /** A generated spec plus the provenance the server owns. This is what renders. */
355
258
  export interface ComponentSpec extends GeneratedSpec {
356
259
  specVersion: typeof SPEC_VERSION;
357
260
  slot: string;
358
261
  source: SpecSource;
359
- /** Epoch milliseconds at which the underlying generation completed. */
360
262
  generatedAt: number;
361
- /** Wall-clock milliseconds spent producing it, including any cache lookup. */
362
263
  latencyMs: number;
363
- /** Provider name, or null when no model was involved. */
364
264
  provider: string | null;
365
- /** Model identifier, or null when no model was involved. */
366
265
  model: string | null;
367
- /**
368
- * Why the deterministic component is showing instead of a generated one.
369
- * Present on every fallback, including the ones where no model was involved
370
- * at all — no provider configured, or the caller asked for it directly.
371
- */
372
266
  degradedReason?: DegradedReason;
373
267
  }
374
- /** Throws a `ZodError` if the value is not a well-formed generated spec. */
375
268
  export declare function parseGeneratedSpec(value: unknown): GeneratedSpec;
376
- /** Non-throwing variant, for validating untrusted model output. */
377
269
  export declare function safeParseGeneratedSpec(value: unknown): GeneratedSpecResult;
378
270
  export {};
379
271
  //# sourceMappingURL=component-spec.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"component-spec.d.ts","sourceRoot":"","sources":["../src/component-spec.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"component-spec.d.ts","sourceRoot":"","sources":["../src/component-spec.ts"],"names":[],"mappings":"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"}
@@ -1,85 +1,22 @@
1
1
  import { z } from 'zod';
2
- /**
3
- * The component specification — the only thing a language model is ever allowed
4
- * to return.
5
- *
6
- * The model chooses layout, ordering, emphasis and copy. Which products to show
7
- * and why is its call only in per-shopper mode, apart from the product a hero
8
- * names. It never returns markup, code, URLs, prices, product titles, or
9
- * images. Every field is an enum, a bounded number, a SKU reference resolved
10
- * against the candidate set, or free text that is clamped and escaped before it
11
- * renders. That is what makes generated output safe to put in a server-rendered
12
- * response.
13
- *
14
- * Two constraints shape this file, and both are easy to undo by accident:
15
- *
16
- * 1. It doubles as a provider structured-output schema, so it avoids
17
- * recursion, string length bounds, and numeric ranges. Providers reject
18
- * schemas that use them in strict mode. Bounds are enforced afterwards, in
19
- * reconciliation, where a violation can be repaired rather than fatal.
20
- * 2. Optionality is `.nullable()` rather than `.optional()`, because strict
21
- * structured outputs require every declared property to be present. "No
22
- * badge" has to be expressible as `null`, not as a missing key.
23
- *
24
- * A test asserts both by converting this schema to JSON Schema, so neither is
25
- * left to a comment nobody reads.
26
- *
27
- * Note the asymmetry with `tracking-input`, which rejects unknown fields: these
28
- * schemas strip them. The inputs differ in kind. An unrecognised key in a host
29
- * payload is a typo, and silently dropping it costs the shopper their history,
30
- * so it must be loud. An unrecognised key from a model is drift, and discarding
31
- * it is exactly right — rejecting the whole spec over one stray key would cost
32
- * the shopper the component. Either way the renderer only ever sees the fields
33
- * declared here, which is the property that matters.
34
- */
35
- /** Overall voice of the component. */
36
2
  export const TONES = ['neutral', 'enthusiastic', 'urgent', 'editorial'];
37
- /** What a banner is claiming. */
38
3
  export const BANNER_TONES = ['info', 'promo', 'urgency', 'restock'];
39
- /** How prominently a single product is placed. */
40
4
  export const EMPHASIS = ['normal', 'featured'];
41
- /**
42
- * Why a product was chosen — the recommendation strategy behind the pick.
43
- *
44
- * This is a closed set rather than free text because every value here is a
45
- * factual claim about the shopper, and a claim the server can check. "Because
46
- * you viewed this" written as prose is unverifiable: nothing downstream can
47
- * tell whether the shopper viewed anything. Declared as `most_viewed`,
48
- * reconciliation can look it up in the digest and drop the claim if it is
49
- * false.
50
- *
51
- * Every value is deliberately checkable against data already in hand — the
52
- * signal digest or the host's own catalog. A basis that needs data the
53
- * framework never receives (`new_arrival`, `back_in_stock`, `trending_today`)
54
- * is not in this list, because it could only ever be taken on trust.
55
- */
56
5
  export const RECOMMENDATION_BASES = [
57
- /** Same category as the product being viewed. */
58
6
  'similar_to_current',
59
- /** The shopper has viewed this product. */
60
7
  'most_viewed',
61
- /** Goes with something already in the cart. */
62
8
  'complements_cart',
63
- /** Goes with something the shopper has bought. */
64
9
  'complements_purchase',
65
- /** In a category the shopper's signals favour. */
66
10
  'liked_category',
67
- /** No claim about this shopper at all — the safe default. */
68
11
  'popular',
69
12
  ];
70
- /** A reference to one product from the candidate set, and why it was chosen. */
71
13
  export const productReferenceSchema = z.object({
72
- /** Must be a SKU the host supplied in `TrackingInput.candidates`. */
73
14
  sku: z.string(),
74
- /** Checked against the shopper's signals, so the model cannot assert a pick it did not earn. */
75
15
  basis: z.enum(RECOMMENDATION_BASES),
76
- /** How the basis is phrased, e.g. "Pairs with the boots you bought". Null once unverifiable. */
77
16
  reason: z.string().nullable(),
78
- /** Short accent label, e.g. "Worth a look". Null when nothing warrants one. */
79
17
  badge: z.string().nullable(),
80
18
  emphasis: z.enum(EMPHASIS),
81
19
  });
82
- /** One large featured statement, optionally anchored to a single product. */
83
20
  const heroBlockSchema = z.object({
84
21
  kind: z.literal('hero'),
85
22
  headline: z.string(),
@@ -87,42 +24,35 @@ const heroBlockSchema = z.object({
87
24
  sku: z.string().nullable(),
88
25
  ctaLabel: z.string().nullable(),
89
26
  });
90
- /** The general-purpose choice when several products are comparably relevant. */
91
27
  const gridBlockSchema = z.object({
92
28
  kind: z.literal('grid'),
93
29
  title: z.string().nullable(),
94
30
  columns: z.union([z.literal(2), z.literal(3), z.literal(4)]),
95
31
  items: z.array(productReferenceSchema),
96
32
  });
97
- /** A horizontally scanned row, for when order implies a ranking. */
98
33
  const carouselBlockSchema = z.object({
99
34
  kind: z.literal('carousel'),
100
35
  title: z.string().nullable(),
101
36
  items: z.array(productReferenceSchema),
102
37
  });
103
- /** A single line of merchandising copy. */
104
38
  const bannerBlockSchema = z.object({
105
39
  kind: z.literal('banner'),
106
40
  tone: z.enum(BANNER_TONES),
107
41
  text: z.string(),
108
42
  ctaLabel: z.string().nullable(),
109
43
  });
110
- /** Short editorial prose, for explaining the theme of a selection. */
111
44
  const copyBlockSchema = z.object({
112
45
  kind: z.literal('copy'),
113
46
  title: z.string().nullable(),
114
47
  body: z.string(),
115
48
  });
116
- /** A set the shop sells together. The shop picks which one; this only asks for it. */
117
49
  const bundleBlockSchema = z.object({
118
50
  kind: z.literal('bundle'),
119
51
  title: z.string().nullable(),
120
52
  body: z.string().nullable(),
121
53
  ctaLabel: z.string().nullable(),
122
- // Filled in per request. Whatever the model puts here is thrown away.
123
54
  bundleId: z.string().nullable(),
124
55
  });
125
- /** Blocks do not nest. The vocabulary is closed on purpose. */
126
56
  export const blockSchema = z.discriminatedUnion('kind', [
127
57
  heroBlockSchema,
128
58
  gridBlockSchema,
@@ -131,25 +61,17 @@ export const blockSchema = z.discriminatedUnion('kind', [
131
61
  copyBlockSchema,
132
62
  bundleBlockSchema,
133
63
  ]);
134
- /**
135
- * Exactly what the model must return. Provenance — version, slot, latency, which
136
- * provider answered — is added by the server afterwards, and is deliberately not
137
- * part of the model's burden.
138
- */
139
64
  export const generatedSpecSchema = z.object({
140
65
  tone: z.enum(TONES),
141
66
  headline: z.string(),
142
67
  subheadline: z.string().nullable(),
143
68
  blocks: z.array(blockSchema),
144
- /** One sentence for generation logs, not for shoppers. Not rendered by default. */
145
69
  rationale: z.string(),
146
70
  });
147
71
  export const SPEC_VERSION = '1';
148
- /** Throws a `ZodError` if the value is not a well-formed generated spec. */
149
72
  export function parseGeneratedSpec(value) {
150
73
  return generatedSpecSchema.parse(value);
151
74
  }
152
- /** Non-throwing variant, for validating untrusted model output. */
153
75
  export function safeParseGeneratedSpec(value) {
154
76
  return generatedSpecSchema.safeParse(value);
155
77
  }
@@ -1 +1 @@
1
- {"version":3,"file":"component-spec.js","sourceRoot":"","sources":["../src/component-spec.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"component-spec.js","sourceRoot":"","sources":["../src/component-spec.ts"],"names":[],"mappings":"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"}
@@ -2,14 +2,5 @@ import type { GeneratedSpec } from './component-spec.js';
2
2
  import type { SignalDigest } from './signal-digest.js';
3
3
  import { type SelectOptions } from './product-selection.js';
4
4
  import type { TrackingInput } from './tracking-input.js';
5
- /**
6
- * Builds a renderable spec from signals alone. Never throws. Returns a spec with
7
- * no blocks only when there is genuinely nothing in stock left to show, which
8
- * the renderer treats as "render nothing" — an empty recommendation region is
9
- * worse than none.
10
- *
11
- * Reads the same digest and selector the model path does, so a degraded render is
12
- * a weaker version of the same decision rather than an unrelated one.
13
- */
14
5
  export declare function buildFallbackSpec(input: TrackingInput, digest: SignalDigest, options?: SelectOptions): GeneratedSpec;
15
6
  //# sourceMappingURL=fallback-component.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fallback-component.d.ts","sourceRoot":"","sources":["../src/fallback-component.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAoB,MAAM,qBAAqB,CAAC;AAC3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAkB,KAAK,aAAa,EAAoB,MAAM,wBAAwB,CAAC;AAC9F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAoCzD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,YAAY,EACpB,OAAO,GAAE,aAAkB,GAC1B,aAAa,CAiBf"}
1
+ {"version":3,"file":"fallback-component.d.ts","sourceRoot":"","sources":["../src/fallback-component.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAoB,MAAM,qBAAqB,CAAC;AAC3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAkB,KAAK,aAAa,EAAoB,MAAM,wBAAwB,CAAC;AAC9F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAkCzD,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,YAAY,EACpB,OAAO,GAAE,aAAkB,GAC1B,aAAa,CAiBf"}
@@ -1,5 +1,4 @@
1
1
  import { selectProducts } from './product-selection.js';
2
- /** A featured lead only reads as deliberate when something follows it. */
3
2
  const MIN_PICKS_FOR_A_FEATURED_LEAD = 3;
4
3
  function headlineFor(digest) {
5
4
  if (digest.isColdStart) {
@@ -14,7 +13,6 @@ function headlineFor(digest) {
14
13
  }
15
14
  return { headline: 'You might also like', subheadline: null };
16
15
  }
17
- /** Wide enough to fill, never wider. */
18
16
  function columnsFor(itemCount) {
19
17
  if (itemCount >= 4)
20
18
  return 4;
@@ -31,15 +29,6 @@ function toProductReference(pick, index, total) {
31
29
  emphasis: index === 0 && total >= MIN_PICKS_FOR_A_FEATURED_LEAD ? 'featured' : 'normal',
32
30
  };
33
31
  }
34
- /**
35
- * Builds a renderable spec from signals alone. Never throws. Returns a spec with
36
- * no blocks only when there is genuinely nothing in stock left to show, which
37
- * the renderer treats as "render nothing" — an empty recommendation region is
38
- * worse than none.
39
- *
40
- * Reads the same digest and selector the model path does, so a degraded render is
41
- * a weaker version of the same decision rather than an unrelated one.
42
- */
43
32
  export function buildFallbackSpec(input, digest, options = {}) {
44
33
  const picks = selectProducts(input, digest, options).slice(0, digest.maxItems);
45
34
  const { headline, subheadline } = headlineFor(digest);
@@ -1 +1 @@
1
- {"version":3,"file":"fallback-component.js","sourceRoot":"","sources":["../src/fallback-component.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAwC,MAAM,wBAAwB,CAAC;AAG9F,0EAA0E;AAC1E,MAAM,6BAA6B,GAAG,CAAC,CAAC;AAExC,SAAS,WAAW,CAAC,MAAoB;IACvC,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;IAC9D,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,QAAQ,EAAE,qBAAqB,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;IAChE,CAAC;IACD,MAAM,WAAW,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC;IACzD,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,WAAW,EAAE,aAAa,WAAW,EAAE,EAAE,CAAC;IACjF,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,qBAAqB,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;AAChE,CAAC;AAED,wCAAwC;AACxC,SAAS,UAAU,CAAC,SAAiB;IACnC,IAAI,SAAS,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IAC7B,IAAI,SAAS,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAiB,EAAE,KAAa,EAAE,KAAa;IACzE,OAAO;QACL,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG;QACrB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,KAAK,EAAE,IAAI;QACX,QAAQ,EAAE,KAAK,KAAK,CAAC,IAAI,KAAK,IAAI,6BAA6B,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ;KACxF,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAoB,EACpB,MAAoB,EACpB,OAAO,GAAkB,EAAE;IAE3B,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/E,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACtD,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,kBAAkB,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IAExF,OAAO;QACL,IAAI,EAAE,SAAS;QACf,QAAQ;QACR,WAAW;QACX,MAAM,EACJ,KAAK,CAAC,MAAM,KAAK,CAAC;YAChB,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;QAC/E,SAAS,EAAE,MAAM,CAAC,WAAW;YAC3B,CAAC,CAAC,oEAAoE;YACtE,CAAC,CAAC,8EAA8E;KACnF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"fallback-component.js","sourceRoot":"","sources":["../src/fallback-component.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAwC,MAAM,wBAAwB,CAAC;AAG9F,MAAM,6BAA6B,GAAG,CAAC,CAAC;AAExC,SAAS,WAAW,CAAC,MAAoB;IACvC,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;IAC9D,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,QAAQ,EAAE,qBAAqB,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;IAChE,CAAC;IACD,MAAM,WAAW,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC;IACzD,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,WAAW,EAAE,aAAa,WAAW,EAAE,EAAE,CAAC;IACjF,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,qBAAqB,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;AAChE,CAAC;AAED,SAAS,UAAU,CAAC,SAAiB;IACnC,IAAI,SAAS,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IAC7B,IAAI,SAAS,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAiB,EAAE,KAAa,EAAE,KAAa;IACzE,OAAO;QACL,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG;QACrB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,KAAK,EAAE,IAAI;QACX,QAAQ,EAAE,KAAK,KAAK,CAAC,IAAI,KAAK,IAAI,6BAA6B,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ;KACxF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,KAAoB,EACpB,MAAoB,EACpB,OAAO,GAAkB,EAAE;IAE3B,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/E,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACtD,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,kBAAkB,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IAExF,OAAO;QACL,IAAI,EAAE,SAAS;QACf,QAAQ;QACR,WAAW;QACX,MAAM,EACJ,KAAK,CAAC,MAAM,KAAK,CAAC;YAChB,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;QAC/E,SAAS,EAAE,MAAM,CAAC,WAAW;YAC3B,CAAC,CAAC,oEAAoE;YACtE,CAAC,CAAC,8EAA8E;KACnF,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"fit-to-shopper.d.ts","sourceRoot":"","sources":["../src/fit-to-shopper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAS,aAAa,EAAoB,MAAM,qBAAqB,CAAC;AAClF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1D,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,aAAa,CAAC;IACpB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAID,wBAAgB,YAAY,CAC1B,IAAI,EAAE,aAAa,EACnB,KAAK,EAAE,SAAS,WAAW,EAAE,EAC7B,QAAQ,EAAE,MAAM,GACf,UAAU,CAuCZ"}
1
+ {"version":3,"file":"fit-to-shopper.d.ts","sourceRoot":"","sources":["../src/fit-to-shopper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAS,aAAa,EAAoB,MAAM,qBAAqB,CAAC;AAClF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1D,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,aAAa,CAAC;IACpB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,aAAa,EACnB,KAAK,EAAE,SAAS,WAAW,EAAE,EAC7B,QAAQ,EAAE,MAAM,GACf,UAAU,CAgCZ"}
@@ -1,30 +1,20 @@
1
- // The model picks the shape. Selection picks the grid and carousel products and
2
- // what may be said about them, so a shared component still fits one shopper.
3
1
  export function fitToShopper(spec, picks, maxItems) {
4
- // Picks are ordered best first. Every slot takes the next one.
5
2
  let next = 0;
6
3
  const limit = Math.min(picks.length, maxItems);
7
4
  const ourReasons = new Map();
8
5
  const blocks = [];
9
6
  for (const block of spec.blocks) {
10
- // A hero is left alone. Its headline and body were written about the
11
- // product it names, so swapping the product would leave copy that describes
12
- // something else. Reconciliation drops the link if this shopper cannot see
13
- // that product, and the words stay.
14
7
  if (block.kind === 'grid' || block.kind === 'carousel') {
15
8
  const items = [];
16
9
  for (const item of block.items) {
17
10
  if (next >= limit)
18
- break; // shrink, never pad
11
+ break;
19
12
  const chosen = picks[next];
20
- // Every reason here is written by this library or handed to it by the
21
- // shop. None of them is the model's, whatever the model wrote in this slot.
22
13
  ourReasons.set(chosen.product.sku, chosen.reason);
23
14
  items.push({
24
15
  sku: chosen.product.sku,
25
16
  basis: chosen.basis,
26
17
  reason: chosen.reason,
27
- // The badge was written about a different product.
28
18
  badge: null,
29
19
  emphasis: item.emphasis,
30
20
  });
@@ -1 +1 @@
1
- {"version":3,"file":"fit-to-shopper.js","sourceRoot":"","sources":["../src/fit-to-shopper.ts"],"names":[],"mappings":"AAQA,gFAAgF;AAChF,6EAA6E;AAC7E,MAAM,UAAU,YAAY,CAC1B,IAAmB,EACnB,KAA6B,EAC7B,QAAgB;IAEhB,+DAA+D;IAC/D,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAE/C,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC7C,MAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChC,qEAAqE;QACrE,4EAA4E;QAC5E,2EAA2E;QAC3E,oCAAoC;QAEpC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YACvD,MAAM,KAAK,GAAuB,EAAE,CAAC;YACrC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;gBAC/B,IAAI,IAAI,IAAI,KAAK;oBAAE,MAAM,CAAC,oBAAoB;gBAC9C,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAE,CAAC;gBAC5B,sEAAsE;gBACtE,4EAA4E;gBAC5E,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;gBAClD,KAAK,CAAC,IAAI,CAAC;oBACT,GAAG,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG;oBACvB,KAAK,EAAE,MAAM,CAAC,KAAK;oBACnB,MAAM,EAAE,MAAM,CAAC,MAAM;oBACrB,mDAAmD;oBACnD,KAAK,EAAE,IAAI;oBACX,QAAQ,EAAE,IAAI,CAAC,QAAQ;iBACxB,CAAC,CAAC;gBACH,IAAI,IAAI,CAAC,CAAC;YACZ,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;YACjC,SAAS;QACX,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,CAAC;AACnD,CAAC"}
1
+ {"version":3,"file":"fit-to-shopper.js","sourceRoot":"","sources":["../src/fit-to-shopper.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,YAAY,CAC1B,IAAmB,EACnB,KAA6B,EAC7B,QAAgB;IAEhB,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAE/C,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC7C,MAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YACvD,MAAM,KAAK,GAAuB,EAAE,CAAC;YACrC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;gBAC/B,IAAI,IAAI,IAAI,KAAK;oBAAE,MAAM;gBACzB,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAE,CAAC;gBAE5B,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;gBAClD,KAAK,CAAC,IAAI,CAAC;oBACT,GAAG,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG;oBACvB,KAAK,EAAE,MAAM,CAAC,KAAK;oBACnB,MAAM,EAAE,MAAM,CAAC,MAAM;oBAErB,KAAK,EAAE,IAAI;oBACX,QAAQ,EAAE,IAAI,CAAC,QAAQ;iBACxB,CAAC,CAAC;gBACH,IAAI,IAAI,CAAC,CAAC;YACZ,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;YACjC,SAAS;QACX,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,CAAC;AACnD,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,10 +1,3 @@
1
- /**
2
- * @rudra-js/core — the contracts and logic that turn one tracking payload into one
3
- * renderable component specification.
4
- *
5
- * Carries no React and no model-vendor SDK, so it can be unit tested in
6
- * isolation and imported from any server runtime.
7
- */
8
1
  export { FIELD_LIMITS, productSchema, skuSignalSchema, viewSignalSchema, purchaseSignalSchema, interactionSchema, renderContextSchema, trackingSignalsSchema, bundleSchema, trackingInputSchema, parseTrackingInput, safeParseTrackingInput, type Product, type SkuSignal, type ViewSignal, type PurchaseSignal, type Interaction, type RenderContext, type TrackingSignals, type Bundle, type TrackingInput, type TrackingInputDraft, type TrackingInputResult, } from './tracking-input.js';
9
2
  export { DIGEST_LIMITS, buildDigest, toCohortDigest, type CategoryAffinity, type InteractionCount, type SignalDigest, type ViewedProduct, } from './signal-digest.js';
10
3
  export { BANNER_TONES, EMPHASIS, RECOMMENDATION_BASES, SPEC_VERSION, TONES, blockSchema, generatedSpecSchema, parseGeneratedSpec, productReferenceSchema, safeParseGeneratedSpec, type BannerBlock, type Block, type BlockKind, type BundleBlock, type CarouselBlock, type ComponentSpec, type CopyBlock, type GeneratedSpec, type GeneratedSpecResult, type GridBlock, type HeroBlock, type ProductReference, type RecommendationBasis, type DegradedReason, type SpecSource, } from './component-spec.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,YAAY,EACZ,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACtB,KAAK,OAAO,EACZ,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,MAAM,EACX,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,GACzB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,aAAa,EACb,WAAW,EACX,cAAc,EACd,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,aAAa,GACnB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,oBAAoB,EACpB,YAAY,EACZ,KAAK,EACL,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACtB,sBAAsB,EACtB,KAAK,WAAW,EAChB,KAAK,KAAK,EACV,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,UAAU,GAChB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1E,OAAO,EACL,uBAAuB,EACvB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,UAAU,GAChB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,KAAK,UAAU,EACf,KAAK,sBAAsB,EAC3B,KAAK,SAAS,GACf,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEjE,OAAO,EACL,wBAAwB,EACxB,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,eAAe,GACrB,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACtB,KAAK,OAAO,EACZ,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,MAAM,EACX,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,GACzB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,aAAa,EACb,WAAW,EACX,cAAc,EACd,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,aAAa,GACnB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,oBAAoB,EACpB,YAAY,EACZ,KAAK,EACL,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACtB,sBAAsB,EACtB,KAAK,WAAW,EAChB,KAAK,KAAK,EACV,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,UAAU,GAChB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1E,OAAO,EACL,uBAAuB,EACvB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,UAAU,GAChB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,KAAK,UAAU,EACf,KAAK,sBAAsB,EAC3B,KAAK,SAAS,GACf,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEjE,OAAO,EACL,wBAAwB,EACxB,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,eAAe,GACrB,MAAM,0BAA0B,CAAC"}
package/dist/index.js CHANGED
@@ -1,10 +1,3 @@
1
- /**
2
- * @rudra-js/core — the contracts and logic that turn one tracking payload into one
3
- * renderable component specification.
4
- *
5
- * Carries no React and no model-vendor SDK, so it can be unit tested in
6
- * isolation and imported from any server runtime.
7
- */
8
1
  export { FIELD_LIMITS, productSchema, skuSignalSchema, viewSignalSchema, purchaseSignalSchema, interactionSchema, renderContextSchema, trackingSignalsSchema, bundleSchema, trackingInputSchema, parseTrackingInput, safeParseTrackingInput, } from './tracking-input.js';
9
2
  export { DIGEST_LIMITS, buildDigest, toCohortDigest, } from './signal-digest.js';
10
3
  export { BANNER_TONES, EMPHASIS, RECOMMENDATION_BASES, SPEC_VERSION, TONES, blockSchema, generatedSpecSchema, parseGeneratedSpec, productReferenceSchema, safeParseGeneratedSpec, } from './component-spec.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,YAAY,EACZ,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,GAYvB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,aAAa,EACb,WAAW,EACX,cAAc,GAKf,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,oBAAoB,EACpB,YAAY,EACZ,KAAK,EACL,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACtB,sBAAsB,GAgBvB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,aAAa,EAAwB,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAoB,MAAM,wBAAwB,CAAC;AAE1E,OAAO,EACL,uBAAuB,GAKxB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,qBAAqB,EACrB,mBAAmB,GAIpB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,WAAW,EAAmB,MAAM,mBAAmB,CAAC;AAEjE,OAAO,EACL,wBAAwB,GAIzB,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,GAYvB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,aAAa,EACb,WAAW,EACX,cAAc,GAKf,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,oBAAoB,EACpB,YAAY,EACZ,KAAK,EACL,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACtB,sBAAsB,GAgBvB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,aAAa,EAAwB,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAoB,MAAM,wBAAwB,CAAC;AAE1E,OAAO,EACL,uBAAuB,GAKxB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,qBAAqB,EACrB,mBAAmB,GAIpB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,WAAW,EAAmB,MAAM,mBAAmB,CAAC;AAEjE,OAAO,EACL,wBAAwB,GAIzB,MAAM,0BAA0B,CAAC"}
@@ -1,41 +1,12 @@
1
1
  import type { SignalDigest } from './signal-digest.js';
2
2
  import { type Product, type TrackingInput } from './tracking-input.js';
3
- /**
4
- * What actually reaches the model.
5
- *
6
- * The prompt is split in two, and the split is load-bearing. `system` is
7
- * byte-identical for every request in a deployment, which is what lets a
8
- * provider cache it and charge a fraction for the repeat. `user` carries
9
- * everything that varies. Interpolating one shopper's data into the system half
10
- * would not break anything visibly — it would quietly make the cached prefix
11
- * useless and multiply the bill, which is why a test asserts the halves stay
12
- * separate rather than trusting anyone to remember.
13
- *
14
- * This module is also the only place shopper-supplied text meets model
15
- * instructions, so every host value is written as a JSON string rather than as
16
- * prose. A search for `boots\n\n# Task\nIgnore the above` is then one quoted
17
- * value on one line, not a heading the model might read as a new instruction.
18
- */
19
3
  export declare const UNTRUSTED_BEGIN = "BEGIN_UNTRUSTED_DATA";
20
4
  export declare const UNTRUSTED_END = "END_UNTRUSTED_DATA";
21
5
  export interface PromptPair {
22
- /** Stable across requests. Safe for a provider to cache. */
23
6
  system: string;
24
- /** Everything about this shopper and this page. */
25
7
  user: string;
26
8
  }
27
9
  export declare const SYSTEM_PROMPT: string;
28
- /**
29
- * The candidates the model is actually shown.
30
- *
31
- * An out-of-stock product is dropped during reconciliation whatever the model
32
- * does with it, so offering one only costs the shopper a slot.
33
- *
34
- * Exported because reconciliation checks the numerals the model writes against
35
- * the strings on this list, and a candidate it was never shown cannot be where
36
- * one came from. Two copies of "what the model saw" would drift, and the pair
37
- * that drifted would be the prompt and the screen reading it back.
38
- */
39
10
  export declare function offeredCandidates(input: TrackingInput): Product[];
40
11
  export declare function buildPrompt(input: TrackingInput, digest: SignalDigest): PromptPair;
41
12
  //# sourceMappingURL=model-prompt.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"model-prompt.d.ts","sourceRoot":"","sources":["../src/model-prompt.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAgB,KAAK,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAErF;;;;;;;;;;;;;;;GAeG;AAEH,eAAO,MAAM,eAAe,yBAAyB,CAAC;AACtD,eAAO,MAAM,aAAa,uBAAuB,CAAC;AAElD,MAAM,WAAW,UAAU;IACzB,4DAA4D;IAC5D,MAAM,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;CACd;AAID,eAAO,MAAM,aAAa,QA6FtB,CAAC;AA6HL;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,EAAE,CAEjE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,YAAY,GAAG,UAAU,CA0BlF"}
1
+ {"version":3,"file":"model-prompt.d.ts","sourceRoot":"","sources":["../src/model-prompt.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAgB,KAAK,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAErF,eAAO,MAAM,eAAe,yBAAyB,CAAC;AACtD,eAAO,MAAM,aAAa,uBAAuB,CAAC;AAElD,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IAEf,IAAI,EAAE,MAAM,CAAC;CACd;AAID,eAAO,MAAM,aAAa,QA6FtB,CAAC;AA6EL,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,EAAE,CAEjE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,YAAY,GAAG,UAAU,CAsBlF"}