@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.
- package/README.md +13 -12
- package/dist/claim-screening.d.ts +0 -23
- package/dist/claim-screening.d.ts.map +1 -1
- package/dist/claim-screening.js +0 -69
- package/dist/claim-screening.js.map +1 -1
- package/dist/component-generator.d.ts +0 -70
- package/dist/component-generator.d.ts.map +1 -1
- package/dist/component-generator.js +10 -52
- package/dist/component-generator.js.map +1 -1
- package/dist/component-spec.d.ts +2 -110
- package/dist/component-spec.d.ts.map +1 -1
- package/dist/component-spec.js +0 -78
- package/dist/component-spec.js.map +1 -1
- package/dist/fallback-component.d.ts +0 -9
- package/dist/fallback-component.d.ts.map +1 -1
- package/dist/fallback-component.js +0 -11
- package/dist/fallback-component.js.map +1 -1
- package/dist/fit-to-shopper.d.ts.map +1 -1
- package/dist/fit-to-shopper.js +1 -11
- package/dist/fit-to-shopper.js.map +1 -1
- package/dist/index.d.ts +0 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -7
- package/dist/index.js.map +1 -1
- package/dist/model-prompt.d.ts +0 -29
- package/dist/model-prompt.d.ts.map +1 -1
- package/dist/model-prompt.js +0 -79
- package/dist/model-prompt.js.map +1 -1
- package/dist/product-selection.d.ts +0 -23
- package/dist/product-selection.d.ts.map +1 -1
- package/dist/product-selection.js +0 -19
- package/dist/product-selection.js.map +1 -1
- package/dist/provider.d.ts +0 -48
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +0 -5
- package/dist/provider.js.map +1 -1
- package/dist/reconciliation.d.ts +1 -44
- package/dist/reconciliation.d.ts.map +1 -1
- package/dist/reconciliation.js +2 -109
- package/dist/reconciliation.js.map +1 -1
- package/dist/signal-digest.d.ts +0 -27
- package/dist/signal-digest.d.ts.map +1 -1
- package/dist/signal-digest.js +1 -50
- package/dist/signal-digest.js.map +1 -1
- package/dist/spec-cache.d.ts +6 -80
- package/dist/spec-cache.d.ts.map +1 -1
- package/dist/spec-cache.js +1 -54
- package/dist/spec-cache.js.map +1 -1
- package/dist/tracking-input.d.ts +0 -49
- package/dist/tracking-input.d.ts.map +1 -1
- package/dist/tracking-input.js +0 -102
- package/dist/tracking-input.js.map +1 -1
- package/package.json +8 -7
- package/src/claim-screening.ts +17 -69
- package/src/component-generator.ts +24 -133
- package/src/component-spec.ts +15 -103
- package/src/fallback-component.ts +0 -11
- package/src/fit-to-shopper.ts +3 -12
- package/src/index.ts +0 -8
- package/src/model-prompt.ts +1 -82
- package/src/product-selection.ts +5 -43
- package/src/provider.ts +4 -53
- package/src/reconciliation.ts +12 -112
- package/src/signal-digest.ts +5 -64
- package/src/spec-cache.ts +8 -98
- package/src/tracking-input.ts +11 -108
package/dist/spec-cache.d.ts
CHANGED
|
@@ -1,101 +1,27 @@
|
|
|
1
1
|
import { type GeneratedSpec } from './component-spec.js';
|
|
2
2
|
import type { SignalDigest } from './signal-digest.js';
|
|
3
|
-
/**
|
|
4
|
-
* Where a generated component is kept between requests.
|
|
5
|
-
*
|
|
6
|
-
* A generation is stable for as long as the shopper's signals are, so asking a
|
|
7
|
-
* model again on the next page view buys nothing and costs a round trip on the
|
|
8
|
-
* render path — which is the latency this whole design exists to avoid.
|
|
9
|
-
*
|
|
10
|
-
* The store is a port rather than an implementation. A single process can use
|
|
11
|
-
* the in-memory one; anything running more than one instance needs a shared
|
|
12
|
-
* store, or each instance keeps its own copy and the hit rate divides by the
|
|
13
|
-
* instance count.
|
|
14
|
-
*/
|
|
15
|
-
/**
|
|
16
|
-
* A stored generation, with the moment it was produced.
|
|
17
|
-
*
|
|
18
|
-
* The timestamp travels with the spec because it cannot be recovered later: a
|
|
19
|
-
* component served from cache is not newly generated, and `generatedAt` is the
|
|
20
|
-
* only way anything downstream can tell how stale what it is showing has become.
|
|
21
|
-
*/
|
|
22
3
|
export interface CachedSpec {
|
|
23
4
|
spec: GeneratedSpec;
|
|
24
|
-
/** Epoch milliseconds at which the model produced this. */
|
|
25
5
|
generatedAt: number;
|
|
26
6
|
}
|
|
27
|
-
/**
|
|
28
|
-
* Asynchronous on purpose. A synchronous `get` would look simpler and would
|
|
29
|
-
* make the shared store the docs recommend impossible to write, since no Redis
|
|
30
|
-
* or Memcached client can return a value without awaiting.
|
|
31
|
-
*/
|
|
32
7
|
export interface SpecCache {
|
|
33
8
|
get(key: string): Promise<CachedSpec | undefined>;
|
|
34
9
|
set(key: string, cached: CachedSpec): Promise<void>;
|
|
35
10
|
delete?(key: string): Promise<void>;
|
|
36
11
|
}
|
|
37
12
|
export interface MemorySpecCacheOptions {
|
|
38
|
-
/** How long an entry stays valid. Defaults to 60 seconds. */
|
|
39
13
|
ttlMs?: number;
|
|
40
|
-
/** Hard ceiling on entries. Least recently read is evicted first. */
|
|
41
14
|
maxEntries?: number;
|
|
42
|
-
/** Injectable clock, so tests do not have to wait. */
|
|
43
15
|
now?: () => number;
|
|
44
16
|
}
|
|
45
|
-
/**
|
|
46
|
-
* A bounded in-process cache.
|
|
47
|
-
*
|
|
48
|
-
* `maxEntries` is generous relative to the default TTL for a reason: a ceiling
|
|
49
|
-
* low enough to evict entries before they expire silently turns a longer TTL
|
|
50
|
-
* into a setting that does nothing, and the person who raised it has no way to
|
|
51
|
-
* tell.
|
|
52
|
-
*/
|
|
53
17
|
export declare function createMemorySpecCache(options?: MemorySpecCacheOptions): SpecCache;
|
|
54
|
-
/**
|
|
55
|
-
* A cache that stores nothing, so every request generates.
|
|
56
|
-
*
|
|
57
|
-
* This is not a stub. It is the control for any measurement of generation cost
|
|
58
|
-
* or latency: with a cache in front, a benchmark reports how often it hit, not
|
|
59
|
-
* what generating costs.
|
|
60
|
-
*/
|
|
61
18
|
export declare function createNullSpecCache(): SpecCache;
|
|
62
|
-
|
|
63
|
-
* Who answered, as two named fields rather than one joined string.
|
|
64
|
-
*
|
|
65
|
-
* Joining them with a colon is ambiguous, and model ids carry colons — an
|
|
66
|
-
* `anthropic` / `claude:1` pair and an `anthropic:claude` / `1` pair flatten to
|
|
67
|
-
* the same text and read each other's entries out of a shared store. The
|
|
68
|
-
* provider is in the key precisely so that cannot happen.
|
|
69
|
-
*/
|
|
70
|
-
export interface ProviderIdentity {
|
|
19
|
+
export declare function specCacheKey(digest: SignalDigest, candidateSkus: readonly string[], provider: {
|
|
71
20
|
name: string;
|
|
72
21
|
model: string;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
* That is the entire point of this function. The previous implementation listed
|
|
79
|
-
* the fields it thought mattered, and four of them drifted: they reached the
|
|
80
|
-
* model but not the key, so two shoppers with genuinely different histories
|
|
81
|
-
* collided and were served each other's component. Hashing the whole digest
|
|
82
|
-
* makes that class of bug unreachable — a field cannot be forgotten here,
|
|
83
|
-
* because nothing is named here.
|
|
84
|
-
*
|
|
85
|
-
* The cost is a lower hit rate than a hand-tuned key would give, since every
|
|
86
|
-
* signal now moves the key. That is the right way round: a key that is too
|
|
87
|
-
* specific wastes money, and a key that is too loose shows one shopper another
|
|
88
|
-
* shopper's page. Raising the hit rate means deliberately coarsening the digest
|
|
89
|
-
* itself, which is a decision to make against measurements rather than by
|
|
90
|
-
* guessing here.
|
|
91
|
-
*
|
|
92
|
-
* Candidates enter as SKUs only. Their titles, prices and ratings reach the
|
|
93
|
-
* model too, but including them would churn the key on every price change for
|
|
94
|
-
* copy that would almost always come back the same. The consequence is bounded
|
|
95
|
-
* and worth stating: within one TTL, a price change does not refresh the
|
|
96
|
-
* generated copy. It cannot show a stale price — prices are read from the live
|
|
97
|
-
* catalog at render time, never from the model.
|
|
98
|
-
*/
|
|
99
|
-
export declare function specCacheKey(digest: SignalDigest, candidateSkus: readonly string[], provider: ProviderIdentity): string;
|
|
100
|
-
export declare function cohortCacheKey(digest: SignalDigest, candidateSkus: readonly string[], provider: ProviderIdentity): string;
|
|
22
|
+
}): string;
|
|
23
|
+
export declare function cohortCacheKey(digest: SignalDigest, candidateSkus: readonly string[], provider: {
|
|
24
|
+
name: string;
|
|
25
|
+
model: string;
|
|
26
|
+
}): string;
|
|
101
27
|
//# sourceMappingURL=spec-cache.d.ts.map
|
package/dist/spec-cache.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spec-cache.d.ts","sourceRoot":"","sources":["../src/spec-cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD
|
|
1
|
+
{"version":3,"file":"spec-cache.d.ts","sourceRoot":"","sources":["../src/spec-cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,aAAa,CAAC;IAEpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;IAClD,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAgBD,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,sBAA2B,GAAG,SAAS,CA2CrF;AAED,wBAAgB,mBAAmB,IAAI,SAAS,CAO/C;AAeD,wBAAgB,YAAY,CAC1B,MAAM,EAAE,YAAY,EACpB,aAAa,EAAE,SAAS,MAAM,EAAE,EAChC,QAAQ,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACxC,MAAM,CAUR;AAED,wBAAgB,cAAc,CAC5B,MAAM,EAAE,YAAY,EACpB,aAAa,EAAE,SAAS,MAAM,EAAE,EAChC,QAAQ,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACxC,MAAM,CAmBR"}
|
package/dist/spec-cache.js
CHANGED
|
@@ -9,19 +9,9 @@ function assertFiniteAtLeastZero(name, value) {
|
|
|
9
9
|
: '';
|
|
10
10
|
throw new RangeError(`${name} must be a finite number of at least 0, received ${value}${hint}`);
|
|
11
11
|
}
|
|
12
|
-
/**
|
|
13
|
-
* A bounded in-process cache.
|
|
14
|
-
*
|
|
15
|
-
* `maxEntries` is generous relative to the default TTL for a reason: a ceiling
|
|
16
|
-
* low enough to evict entries before they expire silently turns a longer TTL
|
|
17
|
-
* into a setting that does nothing, and the person who raised it has no way to
|
|
18
|
-
* tell.
|
|
19
|
-
*/
|
|
20
12
|
export function createMemorySpecCache(options = {}) {
|
|
21
13
|
const ttlMs = options.ttlMs ?? 60_000;
|
|
22
14
|
const maxEntries = options.maxEntries ?? 10_000;
|
|
23
|
-
// Usually `Number(process.env.X)`: an unset variable makes these NaN, and every
|
|
24
|
-
// comparison against NaN is false, so nothing would ever expire or be evicted.
|
|
25
15
|
assertFiniteAtLeastZero('ttlMs', ttlMs);
|
|
26
16
|
assertFiniteAtLeastZero('maxEntries', maxEntries);
|
|
27
17
|
if (!Number.isSafeInteger(maxEntries)) {
|
|
@@ -38,8 +28,6 @@ export function createMemorySpecCache(options = {}) {
|
|
|
38
28
|
entries.delete(key);
|
|
39
29
|
return undefined;
|
|
40
30
|
}
|
|
41
|
-
// Re-insert so insertion order tracks recency, which makes the eviction below
|
|
42
|
-
// least-recently-used rather than oldest-written.
|
|
43
31
|
entries.delete(key);
|
|
44
32
|
entries.set(key, entry);
|
|
45
33
|
return entry.cached;
|
|
@@ -59,24 +47,14 @@ export function createMemorySpecCache(options = {}) {
|
|
|
59
47
|
},
|
|
60
48
|
};
|
|
61
49
|
}
|
|
62
|
-
/**
|
|
63
|
-
* A cache that stores nothing, so every request generates.
|
|
64
|
-
*
|
|
65
|
-
* This is not a stub. It is the control for any measurement of generation cost
|
|
66
|
-
* or latency: with a cache in front, a benchmark reports how often it hit, not
|
|
67
|
-
* what generating costs.
|
|
68
|
-
*/
|
|
69
50
|
export function createNullSpecCache() {
|
|
70
51
|
return {
|
|
71
52
|
async get() {
|
|
72
53
|
return undefined;
|
|
73
54
|
},
|
|
74
|
-
async set() {
|
|
75
|
-
// Deliberately nothing.
|
|
76
|
-
},
|
|
55
|
+
async set() { },
|
|
77
56
|
};
|
|
78
57
|
}
|
|
79
|
-
/** Stable JSON: object keys sorted, so key order in a digest cannot matter. */
|
|
80
58
|
function canonicalise(value) {
|
|
81
59
|
if (value === null || typeof value !== 'object')
|
|
82
60
|
return JSON.stringify(value) ?? 'null';
|
|
@@ -88,35 +66,8 @@ function canonicalise(value) {
|
|
|
88
66
|
return `{${entries.map(([name, fieldValue]) => `${JSON.stringify(name)}:${canonicalise(fieldValue)}`).join(',')}}`;
|
|
89
67
|
}
|
|
90
68
|
const PROMPT_FINGERPRINT = createHash('sha256').update(SYSTEM_PROMPT).digest('hex').slice(0, 16);
|
|
91
|
-
/**
|
|
92
|
-
* Derives the cache key.
|
|
93
|
-
*
|
|
94
|
-
* The digest goes in **whole**, rather than as a hand-picked list of fields.
|
|
95
|
-
* That is the entire point of this function. The previous implementation listed
|
|
96
|
-
* the fields it thought mattered, and four of them drifted: they reached the
|
|
97
|
-
* model but not the key, so two shoppers with genuinely different histories
|
|
98
|
-
* collided and were served each other's component. Hashing the whole digest
|
|
99
|
-
* makes that class of bug unreachable — a field cannot be forgotten here,
|
|
100
|
-
* because nothing is named here.
|
|
101
|
-
*
|
|
102
|
-
* The cost is a lower hit rate than a hand-tuned key would give, since every
|
|
103
|
-
* signal now moves the key. That is the right way round: a key that is too
|
|
104
|
-
* specific wastes money, and a key that is too loose shows one shopper another
|
|
105
|
-
* shopper's page. Raising the hit rate means deliberately coarsening the digest
|
|
106
|
-
* itself, which is a decision to make against measurements rather than by
|
|
107
|
-
* guessing here.
|
|
108
|
-
*
|
|
109
|
-
* Candidates enter as SKUs only. Their titles, prices and ratings reach the
|
|
110
|
-
* model too, but including them would churn the key on every price change for
|
|
111
|
-
* copy that would almost always come back the same. The consequence is bounded
|
|
112
|
-
* and worth stating: within one TTL, a price change does not refresh the
|
|
113
|
-
* generated copy. It cannot show a stale price — prices are read from the live
|
|
114
|
-
* catalog at render time, never from the model.
|
|
115
|
-
*/
|
|
116
69
|
export function specCacheKey(digest, candidateSkus, provider) {
|
|
117
70
|
const material = canonicalise({
|
|
118
|
-
// So a shape change cannot read entries written by the previous shape out of
|
|
119
|
-
// a shared store that outlives a deploy.
|
|
120
71
|
specVersion: SPEC_VERSION,
|
|
121
72
|
prompt: PROMPT_FINGERPRINT,
|
|
122
73
|
provider,
|
|
@@ -125,7 +76,6 @@ export function specCacheKey(digest, candidateSkus, provider) {
|
|
|
125
76
|
});
|
|
126
77
|
return createHash('sha256').update(material).digest('hex').slice(0, 32);
|
|
127
78
|
}
|
|
128
|
-
// Leaves out the personal fields: who the shopper is, what they liked, viewed or searched.
|
|
129
79
|
export function cohortCacheKey(digest, candidateSkus, provider) {
|
|
130
80
|
const material = canonicalise({
|
|
131
81
|
specVersion: SPEC_VERSION,
|
|
@@ -137,11 +87,8 @@ export function cohortCacheKey(digest, candidateSkus, provider) {
|
|
|
137
87
|
locale: digest.locale,
|
|
138
88
|
maxItems: digest.maxItems,
|
|
139
89
|
isColdStart: digest.isColdStart,
|
|
140
|
-
// So copy written for a backpack page is not served on a tent page.
|
|
141
90
|
currentCategory: digest.currentCategory ?? null,
|
|
142
91
|
topCategory: digest.categoryAffinity[0]?.category ?? null,
|
|
143
|
-
// The model is shown products drawn from this list, so a different list must not reuse the
|
|
144
|
-
// copy. A shop that picks candidates per shopper gets smaller cohorts, not a wrong answer.
|
|
145
92
|
candidates: candidateSkus.toSorted(),
|
|
146
93
|
});
|
|
147
94
|
return createHash('sha256').update(material).digest('hex').slice(0, 32);
|
package/dist/spec-cache.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spec-cache.js","sourceRoot":"","sources":["../src/spec-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAsB,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"spec-cache.js","sourceRoot":"","sources":["../src/spec-cache.ts"],"names":[],"mappings":"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"}
|
package/dist/tracking-input.d.ts
CHANGED
|
@@ -1,34 +1,4 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
/**
|
|
3
|
-
* The tracking-input contract — the boundary between the host application and
|
|
4
|
-
* rudra-js.
|
|
5
|
-
*
|
|
6
|
-
* rudra-js does not collect, store, or aggregate anything. The host owns its
|
|
7
|
-
* tracking pipeline (an event stream, a CDP, a warehouse) and hands the
|
|
8
|
-
* framework one JSON object per render. This module is that contract: one
|
|
9
|
-
* schema, validated at the edge, so a malformed payload fails loudly here
|
|
10
|
-
* rather than quietly producing a bad prompt several layers later.
|
|
11
|
-
*
|
|
12
|
-
* Every fixed-shape object below is a `strictObject`, so an unrecognised field
|
|
13
|
-
* is an error rather than being dropped. That matters more than it looks: with
|
|
14
|
-
* a lenient object, a host that misspells `recentSearches` gets a shopper who
|
|
15
|
-
* silently looks like a first-time visitor, and nothing anywhere reports it.
|
|
16
|
-
* The only dynamic shape is `interaction.meta`, which is a record by design.
|
|
17
|
-
*/
|
|
18
|
-
/**
|
|
19
|
-
* Every free-text field and every array is length-capped.
|
|
20
|
-
*
|
|
21
|
-
* These caps are not cosmetic. Host-supplied strings end up inside the prompt
|
|
22
|
-
* we send to a language model, and a model is billed per token — so an
|
|
23
|
-
* unbounded string is an unbounded bill, and an unbounded array of candidates
|
|
24
|
-
* is the same problem multiplied.
|
|
25
|
-
*
|
|
26
|
-
* What this buys is that no single field is unbounded. It is deliberately not
|
|
27
|
-
* an aggregate budget: the caps multiply out to far more than any context
|
|
28
|
-
* window, because rejecting a large-but-legitimate payload is the wrong
|
|
29
|
-
* response to one. Fitting a payload into a prompt is `digest`'s job, and it
|
|
30
|
-
* trims rather than throws.
|
|
31
|
-
*/
|
|
32
2
|
export declare const FIELD_LIMITS: {
|
|
33
3
|
readonly identifier: 128;
|
|
34
4
|
readonly shortText: 200;
|
|
@@ -44,7 +14,6 @@ export declare const FIELD_LIMITS: {
|
|
|
44
14
|
readonly maxItems: 12;
|
|
45
15
|
readonly reason: 120;
|
|
46
16
|
};
|
|
47
|
-
/** A product the generated component is permitted to place. */
|
|
48
17
|
export declare const productSchema: z.ZodObject<{
|
|
49
18
|
sku: z.ZodString;
|
|
50
19
|
title: z.ZodString;
|
|
@@ -58,7 +27,6 @@ export declare const productSchema: z.ZodObject<{
|
|
|
58
27
|
tags: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
59
28
|
}, z.core.$strict>;
|
|
60
29
|
export type Product = z.infer<typeof productSchema>;
|
|
61
|
-
/** Base shape for any signal that points at a single SKU. */
|
|
62
30
|
export declare const skuSignalSchema: z.ZodObject<{
|
|
63
31
|
sku: z.ZodString;
|
|
64
32
|
category: z.ZodOptional<z.ZodString>;
|
|
@@ -84,11 +52,6 @@ export declare const purchaseSignalSchema: z.ZodObject<{
|
|
|
84
52
|
price: z.ZodOptional<z.ZodNumber>;
|
|
85
53
|
}, z.core.$strict>;
|
|
86
54
|
export type PurchaseSignal = z.infer<typeof purchaseSignalSchema>;
|
|
87
|
-
/**
|
|
88
|
-
* Catch-all for everything else the shopper did. `type` is an open vocabulary
|
|
89
|
-
* on purpose — 'scroll_depth', 'wishlist', 'filter_applied', whatever the host
|
|
90
|
-
* already emits — so hosts do not have to map their events onto ours.
|
|
91
|
-
*/
|
|
92
55
|
export declare const interactionSchema: z.ZodObject<{
|
|
93
56
|
type: z.ZodString;
|
|
94
57
|
sku: z.ZodOptional<z.ZodString>;
|
|
@@ -98,7 +61,6 @@ export declare const interactionSchema: z.ZodObject<{
|
|
|
98
61
|
meta: z.ZodOptional<z.ZodPipe<z.ZodCustom<Record<string, string | number | boolean>, Record<string, string | number | boolean>>, z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>>;
|
|
99
62
|
}, z.core.$strict>;
|
|
100
63
|
export type Interaction = z.infer<typeof interactionSchema>;
|
|
101
|
-
/** Where on the site this component is being rendered. */
|
|
102
64
|
export declare const renderContextSchema: z.ZodObject<{
|
|
103
65
|
surface: z.ZodString;
|
|
104
66
|
slot: z.ZodDefault<z.ZodString>;
|
|
@@ -155,7 +117,6 @@ export declare const trackingSignalsSchema: z.ZodObject<{
|
|
|
155
117
|
}, z.core.$strict>>>;
|
|
156
118
|
}, z.core.$strict>;
|
|
157
119
|
export type TrackingSignals = z.infer<typeof trackingSignalsSchema>;
|
|
158
|
-
/** A set the shop sells together. The model never picks or invents one. */
|
|
159
120
|
export declare const bundleSchema: z.ZodObject<{
|
|
160
121
|
id: z.ZodString;
|
|
161
122
|
skus: z.ZodArray<z.ZodString>;
|
|
@@ -246,18 +207,8 @@ export declare const trackingInputSchema: z.ZodObject<{
|
|
|
246
207
|
}, z.core.$strict>>>;
|
|
247
208
|
}, z.core.$strict>;
|
|
248
209
|
export type TrackingInput = z.infer<typeof trackingInputSchema>;
|
|
249
|
-
/** The shape a caller passes in, before defaults are applied. */
|
|
250
210
|
export type TrackingInputDraft = z.input<typeof trackingInputSchema>;
|
|
251
|
-
/**
|
|
252
|
-
* The result of a non-throwing parse. Exported so a consumer can type a
|
|
253
|
-
* validation failure without depending on zod directly.
|
|
254
|
-
*/
|
|
255
211
|
export type TrackingInputResult = z.ZodSafeParseResult<TrackingInput>;
|
|
256
|
-
/**
|
|
257
|
-
* Validates a payload, throwing a `ZodError` if it does not satisfy the
|
|
258
|
-
* contract. An invalid payload is a caller bug, and it should be loud.
|
|
259
|
-
*/
|
|
260
212
|
export declare function parseTrackingInput(value: unknown): TrackingInput;
|
|
261
|
-
/** Non-throwing variant, for callers that want to inspect the failure. */
|
|
262
213
|
export declare function safeParseTrackingInput(value: unknown): TrackingInputResult;
|
|
263
214
|
//# sourceMappingURL=tracking-input.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracking-input.d.ts","sourceRoot":"","sources":["../src/tracking-input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB
|
|
1
|
+
{"version":3,"file":"tracking-input.d.ts","sourceRoot":"","sources":["../src/tracking-input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,YAAY;aACvB,UAAU,EAAE,GAAG;aACf,SAAS,EAAE,GAAG;aACd,WAAW,EAAE,GAAG;aAChB,GAAG,EAAE,EAAE;aACP,cAAc,EAAE,EAAE;aAClB,WAAW,EAAE,EAAE;aACf,kBAAkB,EAAE,GAAG;aACvB,UAAU,EAAE,GAAG;aACf,iBAAiB,EAAE,CAAC;aACpB,OAAO,EAAE,EAAE;aACX,SAAS,EAAE,EAAE;aACb,QAAQ,EAAE,EAAE;aAEZ,MAAM,EAAE,GAAG;CACH,CAAC;AA0BX,eAAO,MAAM,aAAa;;;;;;;;;;;kBAmBxB,CAAC;AACH,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAEpD,eAAO,MAAM,eAAe;;;;;kBAM1B,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD,eAAO,MAAM,gBAAgB;;;;;;;kBAG3B,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,eAAO,MAAM,oBAAoB;;;;;;;kBAG/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAmBlE,eAAO,MAAM,iBAAiB;;;;;;;kBAO5B,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,eAAO,MAAM,mBAAmB;;;;;;;;kBAe9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAKhE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAQhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,eAAO,MAAM,YAAY;;;;;;kBAgBvB,CAAC;AACH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA0C7B,CAAC;AAEJ,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAErE,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,kBAAkB,CAAC,aAAa,CAAC,CAAC;AAEtE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,CAEhE;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,mBAAmB,CAE1E"}
|
package/dist/tracking-input.js
CHANGED
|
@@ -1,34 +1,4 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
/**
|
|
3
|
-
* The tracking-input contract — the boundary between the host application and
|
|
4
|
-
* rudra-js.
|
|
5
|
-
*
|
|
6
|
-
* rudra-js does not collect, store, or aggregate anything. The host owns its
|
|
7
|
-
* tracking pipeline (an event stream, a CDP, a warehouse) and hands the
|
|
8
|
-
* framework one JSON object per render. This module is that contract: one
|
|
9
|
-
* schema, validated at the edge, so a malformed payload fails loudly here
|
|
10
|
-
* rather than quietly producing a bad prompt several layers later.
|
|
11
|
-
*
|
|
12
|
-
* Every fixed-shape object below is a `strictObject`, so an unrecognised field
|
|
13
|
-
* is an error rather than being dropped. That matters more than it looks: with
|
|
14
|
-
* a lenient object, a host that misspells `recentSearches` gets a shopper who
|
|
15
|
-
* silently looks like a first-time visitor, and nothing anywhere reports it.
|
|
16
|
-
* The only dynamic shape is `interaction.meta`, which is a record by design.
|
|
17
|
-
*/
|
|
18
|
-
/**
|
|
19
|
-
* Every free-text field and every array is length-capped.
|
|
20
|
-
*
|
|
21
|
-
* These caps are not cosmetic. Host-supplied strings end up inside the prompt
|
|
22
|
-
* we send to a language model, and a model is billed per token — so an
|
|
23
|
-
* unbounded string is an unbounded bill, and an unbounded array of candidates
|
|
24
|
-
* is the same problem multiplied.
|
|
25
|
-
*
|
|
26
|
-
* What this buys is that no single field is unbounded. It is deliberately not
|
|
27
|
-
* an aggregate budget: the caps multiply out to far more than any context
|
|
28
|
-
* window, because rejecting a large-but-legitimate payload is the wrong
|
|
29
|
-
* response to one. Fitting a payload into a prompt is `digest`'s job, and it
|
|
30
|
-
* trims rather than throws.
|
|
31
|
-
*/
|
|
32
2
|
export const FIELD_LIMITS = {
|
|
33
3
|
identifier: 128,
|
|
34
4
|
shortText: 200,
|
|
@@ -42,44 +12,21 @@ export const FIELD_LIMITS = {
|
|
|
42
12
|
bundles: 20,
|
|
43
13
|
localeTag: 35,
|
|
44
14
|
maxItems: 12,
|
|
45
|
-
// Matches CLAMP.reason in reconciliation: a host reason is rendered in the
|
|
46
|
-
// same place a model's is, so the same length has to hold.
|
|
47
15
|
reason: 120,
|
|
48
16
|
};
|
|
49
|
-
/** Assigning this as an object key mutates the prototype instead of the object. */
|
|
50
17
|
const RESERVED_META_KEY = '__proto__';
|
|
51
18
|
const MAX_EPOCH_MS = Date.UTC(2100, 0, 1);
|
|
52
19
|
const identifier = () => z.string().min(1).max(FIELD_LIMITS.identifier);
|
|
53
20
|
const optionalIdentifier = () => z.string().min(1).max(FIELD_LIMITS.identifier).optional();
|
|
54
|
-
/**
|
|
55
|
-
* Epoch milliseconds, used only for recency ordering. Bounded because a
|
|
56
|
-
* negative or year-3000 timestamp does not fail anywhere downstream — it just
|
|
57
|
-
* sorts to one end and silently reorders the shopper's history.
|
|
58
|
-
*/
|
|
59
21
|
const epochMs = () => z.number().int().min(0).max(MAX_EPOCH_MS).optional();
|
|
60
|
-
/**
|
|
61
|
-
* Whether a path stays on the page's own origin.
|
|
62
|
-
*
|
|
63
|
-
* Read the way a browser reads it, not the way it looks. A browser drops tab,
|
|
64
|
-
* carriage return and newline from a URL before parsing it, and treats a
|
|
65
|
-
* backslash as a slash, so `/\evil.example/x.png` and `/<tab>//evil.example/x.png`
|
|
66
|
-
* both point at someone else's host while passing a plain "starts with one
|
|
67
|
-
* slash" test.
|
|
68
|
-
*/
|
|
69
22
|
const isRootRelative = (value) => {
|
|
70
23
|
const asParsed = value.replace(/[\t\n\r]/g, '');
|
|
71
24
|
return value.startsWith('/') && /^\/(?![/\\])/.test(asParsed);
|
|
72
25
|
};
|
|
73
|
-
/**
|
|
74
|
-
* An absolute http(s) URL, or a root-relative path such as `/images/tr-102.png`.
|
|
75
|
-
* Anything else — a bare word, a `javascript:` URI, a protocol-relative `//host`
|
|
76
|
-
* — is rejected before it can reach an `<img src>`.
|
|
77
|
-
*/
|
|
78
26
|
const imageReference = () => z
|
|
79
27
|
.string()
|
|
80
28
|
.max(FIELD_LIMITS.shortText)
|
|
81
29
|
.refine((value) => isRootRelative(value) ? true : z.url({ protocol: /^https?$/ }).safeParse(value).success, { message: 'expected an http(s) URL or a root-relative path' });
|
|
82
|
-
/** A product the generated component is permitted to place. */
|
|
83
30
|
export const productSchema = z.strictObject({
|
|
84
31
|
sku: identifier(),
|
|
85
32
|
title: z.string().min(1).max(FIELD_LIMITS.shortText),
|
|
@@ -89,15 +36,8 @@ export const productSchema = z.strictObject({
|
|
|
89
36
|
.string()
|
|
90
37
|
.regex(/^[A-Z]{3}$/, 'expected a three-letter ISO 4217 code')
|
|
91
38
|
.default('USD'),
|
|
92
|
-
// This lands in an `<img src>` the host did not write, so the scheme matters:
|
|
93
|
-
// a bare capped string would accept '' and 'javascript:'. Root-relative paths
|
|
94
|
-
// are allowed because most catalogs store images that way, and they carry no
|
|
95
|
-
// scheme to abuse.
|
|
96
39
|
imageUrl: imageReference().optional(),
|
|
97
40
|
rating: z.number().min(0).max(5).optional(),
|
|
98
|
-
// Your phrase for why this product is here, when your own ranking already has
|
|
99
|
-
// one. It renders as the item's reason and is not screened: these are your
|
|
100
|
-
// words about your product, like the title, so you stand behind them.
|
|
101
41
|
reason: z.string().min(1).max(FIELD_LIMITS.reason).optional(),
|
|
102
42
|
isInStock: z.boolean().default(true),
|
|
103
43
|
tags: z
|
|
@@ -105,12 +45,10 @@ export const productSchema = z.strictObject({
|
|
|
105
45
|
.max(FIELD_LIMITS.tagsPerProduct)
|
|
106
46
|
.default([]),
|
|
107
47
|
});
|
|
108
|
-
/** Base shape for any signal that points at a single SKU. */
|
|
109
48
|
export const skuSignalSchema = z.strictObject({
|
|
110
49
|
sku: identifier(),
|
|
111
50
|
category: optionalIdentifier(),
|
|
112
51
|
at: epochMs(),
|
|
113
|
-
/** Caller-supplied strength, 0..1. Defaults to 1 when absent. */
|
|
114
52
|
weight: z.number().min(0).max(1).optional(),
|
|
115
53
|
});
|
|
116
54
|
export const viewSignalSchema = skuSignalSchema.extend({
|
|
@@ -121,26 +59,12 @@ export const purchaseSignalSchema = skuSignalSchema.extend({
|
|
|
121
59
|
quantity: z.number().int().positive().default(1),
|
|
122
60
|
price: z.number().nonnegative().optional(),
|
|
123
61
|
});
|
|
124
|
-
/**
|
|
125
|
-
* `meta` is the one dynamic shape in the contract, so its key is checked before
|
|
126
|
-
* the record is parsed rather than after. Zod builds its result by assigning
|
|
127
|
-
* each key, and assigning `__proto__` sets the prototype instead of adding a
|
|
128
|
-
* key — so the entry would vanish from the parsed output with no error, which
|
|
129
|
-
* is the silent drop this module exists to prevent.
|
|
130
|
-
*/
|
|
131
62
|
const metaKeysAreSafe = z.custom((value) => typeof value === 'object' && value !== null && !Object.hasOwn(value, RESERVED_META_KEY), { message: `meta may not use the reserved key ${RESERVED_META_KEY}` });
|
|
132
|
-
// `z.record` bounds key and value shape but not how many entries a record may
|
|
133
|
-
// carry, so the count is checked separately.
|
|
134
63
|
const metaSchema = metaKeysAreSafe.pipe(z
|
|
135
64
|
.record(z.string().min(1).max(FIELD_LIMITS.identifier), z.union([z.string().max(FIELD_LIMITS.shortText), z.number(), z.boolean()]))
|
|
136
65
|
.refine((entries) => Object.keys(entries).length <= FIELD_LIMITS.metaEntries, {
|
|
137
66
|
message: `meta may carry at most ${FIELD_LIMITS.metaEntries} entries`,
|
|
138
67
|
}));
|
|
139
|
-
/**
|
|
140
|
-
* Catch-all for everything else the shopper did. `type` is an open vocabulary
|
|
141
|
-
* on purpose — 'scroll_depth', 'wishlist', 'filter_applied', whatever the host
|
|
142
|
-
* already emits — so hosts do not have to map their events onto ours.
|
|
143
|
-
*/
|
|
144
68
|
export const interactionSchema = z.strictObject({
|
|
145
69
|
type: identifier(),
|
|
146
70
|
sku: optionalIdentifier(),
|
|
@@ -149,23 +73,17 @@ export const interactionSchema = z.strictObject({
|
|
|
149
73
|
value: z.union([z.string().max(FIELD_LIMITS.shortText), z.number(), z.boolean()]).optional(),
|
|
150
74
|
meta: metaSchema.optional(),
|
|
151
75
|
});
|
|
152
|
-
/** Where on the site this component is being rendered. */
|
|
153
76
|
export const renderContextSchema = z.strictObject({
|
|
154
|
-
/** 'pdp', 'home', 'cart', 'search', or any host-defined surface. */
|
|
155
77
|
surface: identifier(),
|
|
156
|
-
/** Named placement, e.g. 'below-fold-recommendations'. */
|
|
157
78
|
slot: z.string().min(1).max(FIELD_LIMITS.identifier).default('recommendations'),
|
|
158
79
|
currentSku: optionalIdentifier(),
|
|
159
80
|
currentCategory: optionalIdentifier(),
|
|
160
81
|
searchQuery: z.string().max(FIELD_LIMITS.searchQuery).optional(),
|
|
161
|
-
// One language tag, not the Accept-Language header it is often copied from:
|
|
162
|
-
// the locale is part of the cohort cache key, so a list makes its own cohort.
|
|
163
82
|
locale: z
|
|
164
83
|
.string()
|
|
165
84
|
.max(FIELD_LIMITS.localeTag)
|
|
166
85
|
.regex(/^[A-Za-z]{2,8}(?:-[A-Za-z0-9]{1,8})*$/, 'expected one language tag, such as en-US')
|
|
167
86
|
.default('en-US'),
|
|
168
|
-
/** Upper bound on products across the whole generated component. */
|
|
169
87
|
maxItems: z.number().int().min(1).max(FIELD_LIMITS.maxItems).default(4),
|
|
170
88
|
});
|
|
171
89
|
const signalArray = (schema) => z.array(schema).max(FIELD_LIMITS.signalsPerCategory).default([]);
|
|
@@ -178,7 +96,6 @@ export const trackingSignalsSchema = z.strictObject({
|
|
|
178
96
|
recentSearches: signalArray(z.string().min(1).max(FIELD_LIMITS.searchQuery)),
|
|
179
97
|
interactions: signalArray(interactionSchema),
|
|
180
98
|
});
|
|
181
|
-
/** A set the shop sells together. The model never picks or invents one. */
|
|
182
99
|
export const bundleSchema = z.strictObject({
|
|
183
100
|
id: identifier(),
|
|
184
101
|
skus: z
|
|
@@ -188,8 +105,6 @@ export const bundleSchema = z.strictObject({
|
|
|
188
105
|
.refine((skus) => new Set(skus).size === skus.length, {
|
|
189
106
|
message: 'a bundle must not list the same product twice',
|
|
190
107
|
}),
|
|
191
|
-
// The shop's price for the set — not derived from the parts, so the set says
|
|
192
|
-
// which money it is in rather than borrowing it from a member.
|
|
193
108
|
price: z.number().nonnegative(),
|
|
194
109
|
currency: z
|
|
195
110
|
.string()
|
|
@@ -206,17 +121,7 @@ export const trackingInputSchema = z
|
|
|
206
121
|
isReturning: z.boolean().optional(),
|
|
207
122
|
}),
|
|
208
123
|
context: renderContextSchema,
|
|
209
|
-
// A payload with no `signals` block at all is the cold-start case, not an error.
|
|
210
124
|
signals: trackingSignalsSchema.prefault({}),
|
|
211
|
-
/**
|
|
212
|
-
* The only products the generated component may place. Merchandising rules
|
|
213
|
-
* belong here: whatever the host leaves out cannot be recommended, which is
|
|
214
|
-
* what makes it impossible to surface a product that does not exist or is not
|
|
215
|
-
* merchandised for this shopper.
|
|
216
|
-
*
|
|
217
|
-
* SKUs must be unique — a duplicate is a host bug that spends prompt budget
|
|
218
|
-
* twice and invites the same product in two slots.
|
|
219
|
-
*/
|
|
220
125
|
candidates: z
|
|
221
126
|
.array(productSchema)
|
|
222
127
|
.min(1)
|
|
@@ -224,8 +129,6 @@ export const trackingInputSchema = z
|
|
|
224
129
|
.refine((products) => new Set(products.map((product) => product.sku)).size === products.length, {
|
|
225
130
|
message: 'candidates must have unique SKUs',
|
|
226
131
|
}),
|
|
227
|
-
// Ids must be unique — the renderer looks a bundle up by id alone, so a
|
|
228
|
-
// duplicate would let it draw the wrong set at the wrong price.
|
|
229
132
|
bundles: z
|
|
230
133
|
.array(bundleSchema)
|
|
231
134
|
.max(FIELD_LIMITS.bundles)
|
|
@@ -244,14 +147,9 @@ export const trackingInputSchema = z
|
|
|
244
147
|
}
|
|
245
148
|
return true;
|
|
246
149
|
}, { message: 'every product in a bundle must also be a candidate' });
|
|
247
|
-
/**
|
|
248
|
-
* Validates a payload, throwing a `ZodError` if it does not satisfy the
|
|
249
|
-
* contract. An invalid payload is a caller bug, and it should be loud.
|
|
250
|
-
*/
|
|
251
150
|
export function parseTrackingInput(value) {
|
|
252
151
|
return trackingInputSchema.parse(value);
|
|
253
152
|
}
|
|
254
|
-
/** Non-throwing variant, for callers that want to inspect the failure. */
|
|
255
153
|
export function safeParseTrackingInput(value) {
|
|
256
154
|
return trackingInputSchema.safeParse(value);
|
|
257
155
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracking-input.js","sourceRoot":"","sources":["../src/tracking-input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB
|
|
1
|
+
{"version":3,"file":"tracking-input.js","sourceRoot":"","sources":["../src/tracking-input.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rudra-js/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "The contracts and logic that turn one tracking payload into one renderable component specification",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"llm",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
],
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"author": "Clive Dsouza",
|
|
16
|
-
"homepage": "https://
|
|
16
|
+
"homepage": "https://rudrajs.com",
|
|
17
17
|
"bugs": {
|
|
18
18
|
"url": "https://github.com/clivedsouza1010/rudra-js/issues"
|
|
19
19
|
},
|
|
@@ -50,13 +50,14 @@
|
|
|
50
50
|
"publishConfig": {
|
|
51
51
|
"access": "public"
|
|
52
52
|
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"zod": "^4.0.0"
|
|
55
|
+
},
|
|
53
56
|
"peerDependencies": {
|
|
54
|
-
"@rudra-js/attested": "^0.
|
|
55
|
-
"zod": "^4.5.0"
|
|
57
|
+
"@rudra-js/attested": "^0.7.1"
|
|
56
58
|
},
|
|
57
59
|
"devDependencies": {
|
|
58
|
-
"@rudra-js/attested": "0.
|
|
59
|
-
"@types/node": "^26.4.1"
|
|
60
|
-
"zod": "^4.6.5"
|
|
60
|
+
"@rudra-js/attested": "0.7.1",
|
|
61
|
+
"@types/node": "^26.4.1"
|
|
61
62
|
}
|
|
62
63
|
}
|