pi-mega-compact 0.20.13 → 0.20.15

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 (103) hide show
  1. package/dist/config/vector-cortex-early.js +89 -0
  2. package/dist/config/vector-cortex-flag.js +25 -0
  3. package/dist/config/vector-cortex.js +43 -83
  4. package/dist/config.js +1 -1
  5. package/dist/extensions/dashboard-server/api-contracts/vector-cortex-economics.js +20 -0
  6. package/dist/extensions/dashboard-server/route-dispatch.js +7 -0
  7. package/dist/extensions/dashboard-server/routes-rag-settings-vector-cortex.js +2 -0
  8. package/dist/extensions/dashboard-server/routes-vector-cortex-economics.js +59 -0
  9. package/dist/src/config/vector-cortex-early.js +89 -0
  10. package/dist/src/config/vector-cortex-flag.js +25 -0
  11. package/dist/src/config/vector-cortex.js +43 -83
  12. package/dist/src/config.js +1 -1
  13. package/dist/src/vector-cortex/cache/_economics-fixture.js +41 -0
  14. package/dist/src/vector-cortex/cache/compiler.js +201 -0
  15. package/dist/src/vector-cortex/cache/economics-emit.js +85 -0
  16. package/dist/src/vector-cortex/migrations/request-hash-v2-ops.js +143 -0
  17. package/dist/src/vector-cortex/migrations/request-hash-v2-types.js +30 -0
  18. package/dist/src/vector-cortex/migrations/request-hash-v2.js +56 -0
  19. package/dist/src/vector-cortex/provider/economics-ids.js +29 -0
  20. package/dist/src/vector-cortex/provider/economics.js +176 -0
  21. package/dist/src/vector-cortex/provider/experiments.js +166 -0
  22. package/dist/vector-cortex/cache/_economics-fixture.js +41 -0
  23. package/dist/vector-cortex/cache/compiler.js +201 -0
  24. package/dist/vector-cortex/cache/economics-emit.js +85 -0
  25. package/dist/vector-cortex/migrations/request-hash-v2-ops.js +143 -0
  26. package/dist/vector-cortex/migrations/request-hash-v2-types.js +30 -0
  27. package/dist/vector-cortex/migrations/request-hash-v2.js +56 -0
  28. package/dist/vector-cortex/provider/economics-ids.js +29 -0
  29. package/dist/vector-cortex/provider/economics.js +176 -0
  30. package/dist/vector-cortex/provider/experiments.js +166 -0
  31. package/extensions/dashboard-client/dist/assets/{AreaChart-CB-U7ViX.js → AreaChart-CV8WqMmt.js} +2 -2
  32. package/extensions/dashboard-client/dist/assets/{AreaChart-CB-U7ViX.js.map → AreaChart-CV8WqMmt.js.map} +1 -1
  33. package/extensions/dashboard-client/dist/assets/{BarChart-DnLw0fxA.js → BarChart-M-HEBq9l.js} +2 -2
  34. package/extensions/dashboard-client/dist/assets/{BarChart-DnLw0fxA.js.map → BarChart-M-HEBq9l.js.map} +1 -1
  35. package/extensions/dashboard-client/dist/assets/{CacheTab-CjyTVDiP.js → CacheTab-DJ_yPAhP.js} +2 -2
  36. package/extensions/dashboard-client/dist/assets/{CacheTab-CjyTVDiP.js.map → CacheTab-DJ_yPAhP.js.map} +1 -1
  37. package/extensions/dashboard-client/dist/assets/{EventsTab-Bz3QEWam.js → EventsTab-DNVlKzt6.js} +2 -2
  38. package/extensions/dashboard-client/dist/assets/{EventsTab-Bz3QEWam.js.map → EventsTab-DNVlKzt6.js.map} +1 -1
  39. package/extensions/dashboard-client/dist/assets/{HealthTab-CUylEvEY.js → HealthTab-B5yjuInb.js} +2 -2
  40. package/extensions/dashboard-client/dist/assets/{HealthTab-CUylEvEY.js.map → HealthTab-B5yjuInb.js.map} +1 -1
  41. package/extensions/dashboard-client/dist/assets/{MaintenanceTab-Cz_hj_E7.js → MaintenanceTab-DoQedESF.js} +2 -2
  42. package/extensions/dashboard-client/dist/assets/{MaintenanceTab-Cz_hj_E7.js.map → MaintenanceTab-DoQedESF.js.map} +1 -1
  43. package/extensions/dashboard-client/dist/assets/{MemoryMapTab-Dh8brIR1.js → MemoryMapTab-CuL5CzdH.js} +2 -2
  44. package/extensions/dashboard-client/dist/assets/{MemoryMapTab-Dh8brIR1.js.map → MemoryMapTab-CuL5CzdH.js.map} +1 -1
  45. package/extensions/dashboard-client/dist/assets/{MetricsTab-CkqSXc6e.js → MetricsTab-CZSTaCpK.js} +2 -2
  46. package/extensions/dashboard-client/dist/assets/{MetricsTab-CkqSXc6e.js.map → MetricsTab-CZSTaCpK.js.map} +1 -1
  47. package/extensions/dashboard-client/dist/assets/{OverviewTab-DGbJcx6d.js → OverviewTab-vkZlXRW6.js} +2 -2
  48. package/extensions/dashboard-client/dist/assets/{OverviewTab-DGbJcx6d.js.map → OverviewTab-vkZlXRW6.js.map} +1 -1
  49. package/extensions/dashboard-client/dist/assets/{ReposTab-BawS3nfF.js → ReposTab-DgPD96rF.js} +2 -2
  50. package/extensions/dashboard-client/dist/assets/{ReposTab-BawS3nfF.js.map → ReposTab-DgPD96rF.js.map} +1 -1
  51. package/extensions/dashboard-client/dist/assets/{SessionsTab-CUVnmYks.js → SessionsTab-XPbWh7XN.js} +2 -2
  52. package/extensions/dashboard-client/dist/assets/{SessionsTab-CUVnmYks.js.map → SessionsTab-XPbWh7XN.js.map} +1 -1
  53. package/extensions/dashboard-client/dist/assets/{SetupTab-cxTuyZNk.js → SetupTab-Dz74XAtR.js} +2 -2
  54. package/extensions/dashboard-client/dist/assets/{SetupTab-cxTuyZNk.js.map → SetupTab-Dz74XAtR.js.map} +1 -1
  55. package/extensions/dashboard-client/dist/assets/{TimeSavedCard-Cv5SENkE.js → TimeSavedCard-FynCpJdx.js} +2 -2
  56. package/extensions/dashboard-client/dist/assets/{TimeSavedCard-Cv5SENkE.js.map → TimeSavedCard-FynCpJdx.js.map} +1 -1
  57. package/extensions/dashboard-client/dist/assets/{TurnsTab-yl6BBG_F.js → TurnsTab-C7m3GDy0.js} +2 -2
  58. package/extensions/dashboard-client/dist/assets/{TurnsTab-yl6BBG_F.js.map → TurnsTab-C7m3GDy0.js.map} +1 -1
  59. package/extensions/dashboard-client/dist/assets/VectorCortexTab-jRd_Iztk.js +2 -0
  60. package/extensions/dashboard-client/dist/assets/VectorCortexTab-jRd_Iztk.js.map +1 -0
  61. package/extensions/dashboard-client/dist/assets/{WikiTab-DKv-0xCQ.js → WikiTab-C6viLa0u.js} +2 -2
  62. package/extensions/dashboard-client/dist/assets/{WikiTab-DKv-0xCQ.js.map → WikiTab-C6viLa0u.js.map} +1 -1
  63. package/extensions/dashboard-client/dist/assets/{button-CVPrO4UU.js → button-mBEgbBVU.js} +2 -2
  64. package/extensions/dashboard-client/dist/assets/{button-CVPrO4UU.js.map → button-mBEgbBVU.js.map} +1 -1
  65. package/extensions/dashboard-client/dist/assets/{card-BFLnQJEo.js → card-CalUQAKG.js} +2 -2
  66. package/extensions/dashboard-client/dist/assets/{card-BFLnQJEo.js.map → card-CalUQAKG.js.map} +1 -1
  67. package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-B-IUoLd1.js → generateCategoricalChart-CMmkuwj5.js} +2 -2
  68. package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-B-IUoLd1.js.map → generateCategoricalChart-CMmkuwj5.js.map} +1 -1
  69. package/extensions/dashboard-client/dist/assets/{index-Do749WlW.js → index-Dz8GPBOE.js} +3 -3
  70. package/extensions/dashboard-client/dist/assets/{index-Do749WlW.js.map → index-Dz8GPBOE.js.map} +1 -1
  71. package/extensions/dashboard-client/dist/assets/{switch-3uFnZmtq.js → switch-8QKO6CTU.js} +2 -2
  72. package/extensions/dashboard-client/dist/assets/{switch-3uFnZmtq.js.map → switch-8QKO6CTU.js.map} +1 -1
  73. package/extensions/dashboard-client/dist/assets/{toggle-C1rYLeXe.js → toggle-9eCkWI4q.js} +2 -2
  74. package/extensions/dashboard-client/dist/assets/{toggle-C1rYLeXe.js.map → toggle-9eCkWI4q.js.map} +1 -1
  75. package/extensions/dashboard-client/dist/assets/{useSSE-D1qzLzgR.js → useSSE-s6IqOKoD.js} +2 -2
  76. package/extensions/dashboard-client/dist/assets/{useSSE-D1qzLzgR.js.map → useSSE-s6IqOKoD.js.map} +1 -1
  77. package/extensions/dashboard-client/dist/index.html +1 -1
  78. package/extensions/dashboard-client/src/api/vector-cortex.ts +18 -0
  79. package/extensions/dashboard-client/src/tabs/VectorCortexEconomicsCard.tsx +41 -0
  80. package/extensions/dashboard-client/src/tabs/VectorCortexTab.tsx +24 -114
  81. package/extensions/dashboard-client/src/tabs/useVectorCortexPoll.ts +123 -0
  82. package/extensions/dashboard-client/src/types/vector-cortex-vc7.ts +63 -0
  83. package/extensions/dashboard-client/src/types/vector-cortex.ts +5 -19
  84. package/extensions/dashboard-server/api-contracts/vector-cortex-economics.ts +47 -0
  85. package/extensions/dashboard-server/route-dispatch.ts +6 -0
  86. package/extensions/dashboard-server/routes-rag-settings-vector-cortex.ts +12 -0
  87. package/extensions/dashboard-server/routes-vector-cortex-economics.ts +68 -0
  88. package/package.json +1 -1
  89. package/src/config/vector-cortex-early.ts +99 -0
  90. package/src/config/vector-cortex-flag.ts +24 -0
  91. package/src/config/vector-cortex.ts +55 -89
  92. package/src/config.ts +2 -0
  93. package/src/vector-cortex/cache/_economics-fixture.ts +128 -0
  94. package/src/vector-cortex/cache/compiler.ts +280 -0
  95. package/src/vector-cortex/cache/economics-emit.ts +116 -0
  96. package/src/vector-cortex/migrations/request-hash-v2-ops.ts +195 -0
  97. package/src/vector-cortex/migrations/request-hash-v2-types.ts +87 -0
  98. package/src/vector-cortex/migrations/request-hash-v2.ts +80 -0
  99. package/src/vector-cortex/provider/economics-ids.ts +38 -0
  100. package/src/vector-cortex/provider/economics.ts +289 -0
  101. package/src/vector-cortex/provider/experiments.ts +248 -0
  102. package/extensions/dashboard-client/dist/assets/VectorCortexTab-94fqVjat.js +0 -2
  103. package/extensions/dashboard-client/dist/assets/VectorCortexTab-94fqVjat.js.map +0 -1
@@ -0,0 +1,143 @@
1
+ /**
2
+ * request-hash-v2-ops.ts — M5 migration operational logic (copy/verify/switch).
3
+ *
4
+ * Extracted from request-hash-v2.ts to keep the parent file under the 300-line
5
+ * soft limit (soft-as-hard gate). Pure logic over an injected M5Host;
6
+ * deterministic + testable; no console. PREVENT-002/011/PI-004 honored.
7
+ */
8
+ import { createHash } from "node:crypto";
9
+ import { invalidationKey } from "../topology/query.js";
10
+ import { M5_FAIL, REQUEST_HASH_LEGACY_VERSION, } from "./request-hash-v2-types.js";
11
+ /** Length-prefixed framing so the folded fields cannot alias. */
12
+ function field(value) {
13
+ return `${Buffer.byteLength(value, "utf8")}:${value}`;
14
+ }
15
+ const identity = (profileId, requestDigest) => `${profileId}::${requestDigest}`;
16
+ /**
17
+ * The authoritative v2 hash: SHA-256 over the version tag, profile, request
18
+ * digest, and economics version. Length-prefixed for injectivity, exactly as the
19
+ * crystal key encoder frames its fields.
20
+ */
21
+ export function deriveRequestHashV2(profileId, requestDigest, economicsVersion) {
22
+ return createHash("sha256")
23
+ .update(field("request-hash-v2") +
24
+ field(profileId) +
25
+ field(requestDigest) +
26
+ field(economicsVersion), "utf8")
27
+ .digest("hex");
28
+ }
29
+ /** Derive the v2 row for one v1 row. */
30
+ export function deriveRequestHashRow(host, v1) {
31
+ const economicsVersion = host.economicsVersionOf(v1.profileId);
32
+ return {
33
+ profileId: v1.profileId,
34
+ // IDENTITY-PRESERVING: carried through verbatim, never re-derived.
35
+ requestDigest: v1.requestDigest,
36
+ economicsVersion,
37
+ hash: deriveRequestHashV2(v1.profileId, v1.requestDigest, economicsVersion),
38
+ };
39
+ }
40
+ /**
41
+ * Economics versions encode the generation they were minted under. We treat the
42
+ * trailing numeric segment as the generation; if it is not numeric the row is
43
+ * considered tied to generation 0 (always live unless explicitly invalidated).
44
+ */
45
+ function generationFromEconomics(economicsVersion) {
46
+ const match = /(\d+)$/.exec(economicsVersion);
47
+ return match ? BigInt(match[1]) : 0n;
48
+ }
49
+ export function detectCollision(host) {
50
+ const byHash = new Map();
51
+ for (const v1 of host.v1Rows()) {
52
+ const row = deriveRequestHashRow(host, v1);
53
+ const prior = byHash.get(row.hash);
54
+ if (prior !== undefined &&
55
+ prior !== identity(v1.profileId, v1.requestDigest)) {
56
+ return true;
57
+ }
58
+ byHash.set(row.hash, identity(v1.profileId, v1.requestDigest));
59
+ }
60
+ return false;
61
+ }
62
+ export function isGenerationInvalidated(host, row) {
63
+ const session = host.sessionOf(row.profileId);
64
+ const live = host.liveGenerationOf(session);
65
+ const keyForLive = invalidationKey(session, live);
66
+ const keyForRow = invalidationKey(session, generationFromEconomics(row.economicsVersion));
67
+ return keyForLive !== keyForRow;
68
+ }
69
+ export function m5Copy(host) {
70
+ const existing = new Map(host.existingV2().map((r) => [identity(r.profileId, r.requestDigest), r]));
71
+ const wanted = [];
72
+ for (const v1 of host.v1Rows()) {
73
+ const fresh = deriveRequestHashRow(host, v1);
74
+ if (isGenerationInvalidated(host, fresh))
75
+ continue;
76
+ const stored = existing.get(identity(v1.profileId, v1.requestDigest));
77
+ if (stored !== undefined &&
78
+ stored.hash === fresh.hash &&
79
+ stored.economicsVersion === fresh.economicsVersion) {
80
+ continue;
81
+ }
82
+ wanted.push(fresh);
83
+ }
84
+ if (wanted.length > 0)
85
+ host.putV2(wanted);
86
+ return { written: wanted, all: [...host.existingV2()] };
87
+ }
88
+ function dedupe(codes) {
89
+ const out = [];
90
+ for (const c of codes)
91
+ if (!out.includes(c))
92
+ out.push(c);
93
+ return out;
94
+ }
95
+ export function m5Verify(host) {
96
+ const codes = [];
97
+ const stored = host.existingV2();
98
+ const v1Rows = host.v1Rows();
99
+ const counts = new Map();
100
+ for (const r of stored) {
101
+ const id = identity(r.profileId, r.requestDigest);
102
+ counts.set(id, (counts.get(id) ?? 0) + 1);
103
+ }
104
+ const expected = new Set();
105
+ for (const v1 of v1Rows) {
106
+ const id = identity(v1.profileId, v1.requestDigest);
107
+ expected.add(id);
108
+ const n = counts.get(id) ?? 0;
109
+ if (n === 0)
110
+ codes.push(M5_FAIL.COPY_PARTIAL);
111
+ if (n > 1)
112
+ codes.push(M5_FAIL.COUNT_MISMATCH);
113
+ }
114
+ const v1Digests = new Set(v1Rows.map((r) => identity(r.profileId, r.requestDigest)));
115
+ for (const r of stored) {
116
+ const fresh = deriveRequestHashV2(r.profileId, r.requestDigest, r.economicsVersion);
117
+ if (r.hash !== fresh)
118
+ codes.push(M5_FAIL.DIGEST_MISMATCH);
119
+ const id = identity(r.profileId, r.requestDigest);
120
+ if (!v1Digests.has(id)) {
121
+ codes.push(expected.size > 0 ? M5_FAIL.IDENTITY_DRIFT : M5_FAIL.COUNT_MISMATCH);
122
+ }
123
+ }
124
+ if (detectCollision(host))
125
+ codes.push(M5_FAIL.REQUEST_HASH_COLLISION);
126
+ return { ok: codes.length === 0, codes: dedupe(codes) };
127
+ }
128
+ export function m5Switch(host) {
129
+ if (host.activeVersion() !== REQUEST_HASH_LEGACY_VERSION) {
130
+ return { ok: false, codes: [M5_FAIL.NOT_ON_LEGACY] };
131
+ }
132
+ const verify = m5Verify(host);
133
+ if (!verify.ok)
134
+ return verify;
135
+ if (detectCollision(host))
136
+ return { ok: false, codes: [M5_FAIL.REQUEST_HASH_COLLISION] };
137
+ host.switchToV2();
138
+ return { ok: true, codes: [] };
139
+ }
140
+ export function migrateRequestHashV2(host) {
141
+ m5Copy(host);
142
+ return m5Switch(host);
143
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * request-hash-v2-types.ts — M5 request-hash-v2 migration types.
3
+ *
4
+ * Extracted from request-hash-v2.ts to keep the parent file under the 300-line
5
+ * soft limit (soft-as-hard gate). Pure type + constant definitions; no logic.
6
+ * PREVENT-002/011/PI-004 honored.
7
+ */
8
+ /** The active-version value the v2 pointer is switched to. */
9
+ export const REQUEST_HASH_V2_VERSION = 2;
10
+ /** The legacy (predecessor) active version. */
11
+ export const REQUEST_HASH_LEGACY_VERSION = 1;
12
+ /** M5 failure codes. */
13
+ export const M5_FAIL = {
14
+ COPY_PARTIAL: "M5_COPY_PARTIAL",
15
+ COUNT_MISMATCH: "M5_COUNT_MISMATCH",
16
+ DIGEST_MISMATCH: "M5_DIGEST_MISMATCH",
17
+ IDENTITY_DRIFT: "M5_IDENTITY_DRIFT",
18
+ /** Two distinct v1 rows map to the same v2 hash — blocks the switch. (VC7C) */
19
+ REQUEST_HASH_COLLISION: "M5_REQUEST_HASH_COLLISION",
20
+ /** The active pointer is not on v1; switching would be a no-op or a regression. */
21
+ NOT_ON_LEGACY: "M5_NOT_ON_LEGACY",
22
+ };
23
+ /**
24
+ * Registered M5 conformance IDs (M5-001..020). The acceptance test reads these
25
+ * rows from the v2 `migrations/` domain and asserts each returns its manifest
26
+ * bytes or exactly its listed failure code. Mirrors M6_IDS / M4_IDS.
27
+ */
28
+ export const M5_IDS = Array.from({ length: 20 }, (_v, i) => `M5-${String(i + 1).padStart(3, "0")}`);
29
+ /** Named M5 rows surfaced by the conformance corpus (mirrors M6_NAMED_IDS). */
30
+ export const M5_NAMED_IDS = ["M5-COLLIDE-002"];
@@ -0,0 +1,56 @@
1
+ /**
2
+ * vector-cortex/migrations/request-hash-v2.ts — M5 request-hash-v2 migration
3
+ * (COPY + VALIDATE + SWITCH).
4
+ *
5
+ * Delegate-shell: types + constants live in request-hash-v2-types.ts and the
6
+ * operational logic (copy/verify/switch/collision) lives in
7
+ * request-hash-v2-ops.ts. This file re-exports the public surface so callers
8
+ * import from a single module. Split to keep under the 300-line soft limit
9
+ * (soft-as-hard gate).
10
+ *
11
+ * M5 versions the canonical request hash: the predecessor hashed the outbound
12
+ * request under the v1 scheme; v2 folds in the provider profile's ECONOMICS
13
+ * version so a pricing/TTL/exclusion change cannot silently reuse a cache
14
+ * identity minted under different economics. Like M4/M6 it follows the
15
+ * copy/validate/switch contract:
16
+ *
17
+ * - copy: resumable per (profile, request) — an interrupted run resumes
18
+ * without duplicate rows or active-pointer drift.
19
+ * - validate: every v1 row has exactly one v2 row, every v2 digest re-hashes
20
+ * from its own declared fields, the migration is IDENTITY-PRESERVING
21
+ * (a v2 row carries the same `requestDigest` as its v1 source — v2
22
+ * changes how a CACHE KEY is derived, never what the request IS), and
23
+ * — the M5-specific invariant ADDED in VC7C — there are ZERO
24
+ * collisions: no two distinct v1 rows may map to one v2 hash. A
25
+ * collision (`M5_REQUEST_HASH_COLLISION`) means two different
26
+ * conversations would share a cache key, the most dangerous outcome
27
+ * in the subsystem, so it blocks the switch outright.
28
+ * - switch: ATOMICALLY flip the active pointer to v2 via `host.switchToV2()`.
29
+ * VC7B deferred this; VC7C performs it — but ONLY after re-validating
30
+ * against freshly-read host state at switch time.
31
+ *
32
+ * WHY THE COLLISION CHECK RUNS AT SWITCH TIME, NOT VALIDATE TIME. The brief's
33
+ * failure-injection contract is explicit: crash after M5 validation, inject a
34
+ * collision into host state, then resume — and the RESUMED run must detect
35
+ * `M5_REQUEST_HASH_COLLISION`. If the collision were detected only from the result
36
+ * of an earlier `m5Verify` call, the cached result would be replayed and the
37
+ * injected collision would be invisible. So `m5Switch` RE-READS the host (`v1Rows`,
38
+ * `existingV2`, `activeVersion`) and RE-RUNS the collision check against that live
39
+ * state. Validation is a precondition; the switch is the only place that proves the
40
+ * hazard is absent *right now*. This is the same resume-after-crash discipline as
41
+ * M4/M6: a migration that trusts a stale verification is a migration that loses
42
+ * data on restart.
43
+ *
44
+ * M6 INVALIDATION CONSUMPTION. A v2 request hash is only as trustworthy as the
45
+ * generation it was minted under. The switch consumes M6's structured invalidation
46
+ * keys via the REAL API (`invalidationKey` from `../topology/query.js`) rather than
47
+ * inventing one: when a v2 row's economics version maps to an invalidated router
48
+ * generation, that row cannot be promoted to active. We do not re-derive a
49
+ * generation here — topology is the authority on what generation is live — we only
50
+ * refuse to switch a row whose generation is dead. This keeps M5 from resurrecting
51
+ * cache identities tied to a generation the router has already invalidated.
52
+ *
53
+ * PREVENT-002/011/PI-004 honored.
54
+ */
55
+ export { REQUEST_HASH_V2_VERSION, REQUEST_HASH_LEGACY_VERSION, M5_FAIL, M5_IDS, M5_NAMED_IDS, } from "./request-hash-v2-types.js";
56
+ export { deriveRequestHashV2, deriveRequestHashRow, detectCollision, isGenerationInvalidated, m5Copy, m5Verify, m5Switch, migrateRequestHashV2, } from "./request-hash-v2-ops.js";
@@ -0,0 +1,29 @@
1
+ /**
2
+ * vector-cortex/provider/economics-ids.ts — VC7B conformance ID registrations.
3
+ *
4
+ * Extracted from economics.ts to keep that file under the 300-line soft limit
5
+ * (soft-as-hard gate). The ID ranges and named rows are pure data — splitting
6
+ * them out mirrors how vector-cortex-breakers.ts was extracted from
7
+ * vector-cortex.ts. economics.ts re-exports them so no consumer import path
8
+ * changes.
9
+ *
10
+ * Pi-agnostic, dependency-free (PREVENT-PI-004 / PREVENT-011).
11
+ */
12
+ /**
13
+ * Registered VC7B cache-economics conformance ID range (CACHE-001..015). The
14
+ * acceptance aggregator reads these rows from the v2 manifest and asserts each
15
+ * returns its manifest `ok`/`code`.
16
+ */
17
+ export const CACHE_IDS = Array.from({ length: 15 }, (_v, i) => `CACHE-${String(i + 1).padStart(3, "0")}`);
18
+ /**
19
+ * Registered VC7B provider-economics conformance rows (PRO-024..030), continuing
20
+ * VC7A's PRO-016..023. These pin the ECONOMICS half of a provider profile:
21
+ * pricing validity, the exclusion-proof rule, and TTL/min-prefix eligibility.
22
+ */
23
+ export const ECONOMICS_PROVIDER_IDS = Array.from({ length: 7 }, (_v, i) => `PRO-${String(i + 24).padStart(3, "0")}`);
24
+ /** Named VC7B conformance assertions (the sprint's headline rows). */
25
+ export const ECONOMICS_NAMED_IDS = [
26
+ "CACHE-COST-001",
27
+ "CACHE-EXCLUDE-002",
28
+ "CACHE-RANDOM-003",
29
+ ];
@@ -0,0 +1,176 @@
1
+ /**
2
+ * vector-cortex/provider/economics.ts — VC7B cache economics (ProviderProfileV1
3
+ * extension).
4
+ *
5
+ * VC7A proved a render can be FROZEN and reused. VC7B answers the question that
6
+ * immediately follows: is reusing it actually WORTH IT? Provider prompt caching
7
+ * is not free — a cache WRITE typically costs MORE than an uncached token, and a
8
+ * cache READ costs less. So a cache is profitable only when a written prefix is
9
+ * read back enough times, before its TTL expires, to repay the write premium.
10
+ * This file is that arithmetic and nothing else.
11
+ *
12
+ * THE NET-SAVINGS MODEL. For a prefix of `cachedTokens` tokens:
13
+ *
14
+ * baseline (no cache) = cachedTokens * basePrice * (writes + hits)
15
+ * actual (cached) = cachedTokens * (writePrice * writes + readPrice * hits)
16
+ * netSavings = baseline - actual
17
+ *
18
+ * A NEGATIVE `netSavings` is a real, expected, and important outcome: it means
19
+ * the cache LOST money (a prefix written once and never re-read always does, by
20
+ * exactly the write premium). We report it rather than clamping it at zero,
21
+ * because a floor at zero would make every rollout look free and would hide the
22
+ * single failure mode this sprint exists to detect.
23
+ *
24
+ * EXACT ARITHMETIC, NO FLOATS IN THE MONEY PATH. Prices are integer
25
+ * MICRO-UNITS per token (1e-6 of the provider's currency unit), never floating
26
+ * point. `0.1 + 0.2 !== 0.3` is not an acceptable property for a cost ledger, and
27
+ * accumulating float error across millions of tokens produces aggregates that
28
+ * silently disagree with the provider's own bill. All money is integer; only the
29
+ * derived RATIO is a float, and it is finite-guarded.
30
+ *
31
+ * EVERY EXCLUSION NEEDS A FIXTURE (the sprint's headline safety rule). A provider
32
+ * profile may declare that some request field does not affect cache identity —
33
+ * but an UNPROVEN exclusion is how you get silent cache poisoning: the renderer
34
+ * folds a field the provider actually keys on, two different requests collapse to
35
+ * one cache entry, and one conversation is served another's prefix. So an
36
+ * exclusion without a `fixtureId` (or with a blank one) is REJECTED here —
37
+ * `ECON_EXCLUSION_UNPROVEN` — rather than trusted. There is no override.
38
+ *
39
+ * ESTIMATE VS MEASURED. Every result is labeled. Only telemetry from a
40
+ * RANDOMIZED live assignment may be called `measured` and fed into a causal
41
+ * interval; shadow or non-randomized numbers are `estimate` and are excluded
42
+ * from causal aggregates (see `experiments.ts`). Mixing the two would let a
43
+ * self-selected population masquerade as a controlled experiment.
44
+ *
45
+ * PURE. No clock, no storage, no console, no network (PREVENT-PI-004 /
46
+ * PREVENT-011). Runs identically with `MEGACOMPACT_VC7B` on or off — the flag
47
+ * gates only the reporter/dashboard seam in `../cache/economics-emit.ts`.
48
+ */
49
+ /** A non-negative safe integer — the only shape money and counts may take. */
50
+ function isCount(n) {
51
+ return Number.isSafeInteger(n) && n >= 0;
52
+ }
53
+ /**
54
+ * Validate a profile's economics, enforcing the exclusion-proof rule.
55
+ *
56
+ * An exclusion claims "this field cannot affect provider cache identity". That
57
+ * claim is only as good as the fixture that proves it, so a profile carrying
58
+ * exclusions MUST name a `exclusionFixtureId`, and every individual exclusion
59
+ * must carry its own `fixtureId` too (VC5B already models that field; VC7B makes
60
+ * a blank one fatal instead of decorative). Returns deduplicated codes in a
61
+ * deterministic order.
62
+ */
63
+ export function validateEconomics(econ, exclusions) {
64
+ const codes = new Set();
65
+ for (const n of [econ.basePrice, econ.readPrice, econ.writePrice, econ.ttlMs, econ.minPrefix]) {
66
+ if (!isCount(n))
67
+ codes.add("ECON_PRICE_INVALID");
68
+ }
69
+ // The headline rule: exclusions without a proving fixture are never trusted.
70
+ if (exclusions.length > 0) {
71
+ const id = econ.exclusionFixtureId;
72
+ if (id === null || id.trim() === "")
73
+ codes.add("ECON_EXCLUSION_UNPROVEN");
74
+ for (const ex of exclusions) {
75
+ if (ex.fixtureId.trim() === "")
76
+ codes.add("ECON_EXCLUSION_UNPROVEN");
77
+ }
78
+ }
79
+ const order = ["ECON_EXCLUSION_UNPROVEN", "ECON_PRICE_INVALID"];
80
+ return order.filter((c) => codes.has(c));
81
+ }
82
+ /**
83
+ * Validate a profile + its economics together. Convenience over
84
+ * `validateEconomics` for callers holding a whole `ProviderProfileV1`: the
85
+ * exclusion list is read from the profile itself, so the two can never disagree.
86
+ */
87
+ export function validateProfileEconomics(profile, econ) {
88
+ return validateEconomics(econ, profile.excludedJsonPointers);
89
+ }
90
+ /**
91
+ * Hits required for ONE write to break even.
92
+ *
93
+ * One write costs `(writePrice - basePrice)` extra per token; each subsequent
94
+ * hit saves `(basePrice - readPrice)` per token. So break-even is the ceiling of
95
+ * premium/discount. Returns `null` when the cache can NEVER pay for itself
96
+ * (a read that costs at least as much as an uncached token) — reporting a huge
97
+ * number there would imply "just get more hits", which is false.
98
+ * Returns 0 when writing is already free or cheaper than not caching.
99
+ */
100
+ export function breakEvenHits(econ) {
101
+ const premium = econ.writePrice - econ.basePrice;
102
+ const discount = econ.basePrice - econ.readPrice;
103
+ if (premium <= 0)
104
+ return 0;
105
+ if (discount <= 0)
106
+ return null;
107
+ return Math.ceil(premium / discount);
108
+ }
109
+ /**
110
+ * Compute net cache savings for observed (or shadow) usage.
111
+ *
112
+ * Pure integer arithmetic in micro-units. The only float is `savingsRatio`, and
113
+ * it is zero-guarded so a zero baseline yields 0 rather than NaN/Infinity — the
114
+ * sprint invariant is that every reported aggregate is FINITE.
115
+ *
116
+ * `evidence` is supplied by the caller and simply carried through: this function
117
+ * cannot know whether its inputs came from a randomized arm, and guessing would
118
+ * be exactly the mislabeling the causal rules forbid.
119
+ */
120
+ export function computeEconomics(econ, usage, evidence) {
121
+ const codes = [];
122
+ for (const n of [econ.basePrice, econ.readPrice, econ.writePrice, econ.ttlMs, econ.minPrefix]) {
123
+ if (!isCount(n)) {
124
+ codes.push("ECON_PRICE_INVALID");
125
+ break;
126
+ }
127
+ }
128
+ for (const n of [usage.cachedTokens, usage.writeCount, usage.hitCount]) {
129
+ if (!isCount(n)) {
130
+ codes.push("ECON_USAGE_INVALID");
131
+ break;
132
+ }
133
+ }
134
+ if (codes.length > 0)
135
+ return { ok: false, codes };
136
+ const { cachedTokens, writeCount, hitCount } = usage;
137
+ const baselineCost = cachedTokens * econ.basePrice * (writeCount + hitCount);
138
+ const actualCost = cachedTokens * (econ.writePrice * writeCount + econ.readPrice * hitCount);
139
+ // Exactness is the whole point of the integer model: if any product leaves the
140
+ // safe-integer range the result is silently wrong, so we fail instead.
141
+ if (!Number.isSafeInteger(baselineCost) || !Number.isSafeInteger(actualCost)) {
142
+ return { ok: false, codes: ["ECON_OVERFLOW"] };
143
+ }
144
+ const netSavings = baselineCost - actualCost;
145
+ // Tokens served at the discounted read price — the cache's token-level benefit,
146
+ // independent of price (a hit re-reads the whole prefix).
147
+ const tokenSavings = cachedTokens * hitCount;
148
+ const savingsRatio = baselineCost === 0 ? 0 : netSavings / baselineCost;
149
+ return {
150
+ ok: true,
151
+ result: {
152
+ profileId: econ.profileId,
153
+ baselineCost,
154
+ actualCost,
155
+ netSavings,
156
+ tokenSavings,
157
+ savingsRatio,
158
+ breakEvenHits: breakEvenHits(econ),
159
+ evidence,
160
+ },
161
+ };
162
+ }
163
+ /**
164
+ * Whether a prefix is eligible to be cached at all: it must meet the profile's
165
+ * minimum prefix, and it must still be within TTL. A prefix below `minPrefix` is
166
+ * not "a small win", it is not cacheable by the provider at all.
167
+ */
168
+ export function isCacheEligible(econ, prefixTokens, ageMs) {
169
+ if (!isCount(prefixTokens) || !isCount(ageMs))
170
+ return false;
171
+ return prefixTokens >= econ.minPrefix && ageMs < econ.ttlMs;
172
+ }
173
+ // Conformance ID ranges + named rows extracted to economics-ids.ts to keep this
174
+ // file under the 300-line soft limit (soft-as-hard gate). Re-exported here so no
175
+ // consumer import path changes.
176
+ export { CACHE_IDS, ECONOMICS_PROVIDER_IDS, ECONOMICS_NAMED_IDS, } from "./economics-ids.js";
@@ -0,0 +1,166 @@
1
+ /**
2
+ * vector-cortex/provider/experiments.ts — VC7B session-level cache experiments.
3
+ *
4
+ * To claim a cache strategy CAUSED a saving you need a randomized comparison,
5
+ * not a before/after. This file assigns each session to an experiment arm and
6
+ * guarantees the two properties that make the resulting telemetry admissible as
7
+ * causal evidence.
8
+ *
9
+ * 1. STABLE, JOURNAL-FREE ASSIGNMENT. The arm is a pure function of
10
+ * `sha256(experimentId, sessionId)` — NOT a random draw recorded in a
11
+ * journal. So the assignment survives anything: process restart, a lost or
12
+ * corrupted journal, a different host, a replay months later. This is the
13
+ * sprint's unique failure-injection case (lose the journal after the first
14
+ * event, restart, and the same arm must come back), and a hash-derived arm
15
+ * passes it by construction rather than by careful recovery code. A journal
16
+ * can still be kept as an audit trail, but nothing DEPENDS on it.
17
+ *
18
+ * The corollary matters just as much: every event in one session shares one
19
+ * arm (CACHE-RANDOM-003). If a session could drift between arms mid-flight,
20
+ * its rows would appear in both arms of the comparison and the contrast would
21
+ * be measuring nothing.
22
+ *
23
+ * 2. RANDOMIZED ⇒ CAUSAL; EVERYTHING ELSE ⇒ ESTIMATE. Hashing a session id is
24
+ * randomization only when the id itself is unpredictable and every session is
25
+ * eligible. A FORCED arm (operator override), a SHADOW arm (computed but not
26
+ * served), and a non-randomized rollout are all labeled `estimate` and are
27
+ * excluded from causal intervals by `isCausallyAdmissible`. Shadow numbers are
28
+ * genuinely useful — they are just not evidence of an effect.
29
+ *
30
+ * WHY 10_000 BUCKETS. Bucket granularity bounds how finely traffic can be split;
31
+ * 10k gives 0.01% resolution, matching VC5C's rollout bucketing so the two
32
+ * subsystems partition traffic on the same scale rather than on quietly
33
+ * different ones.
34
+ *
35
+ * PURE. No clock, no storage, no console, no network (PREVENT-PI-004 /
36
+ * PREVENT-011). `assignedAt` is an INJECTED timestamp, never `Date.now()` read
37
+ * here, so assignment is fully reproducible in tests and replays. Runs
38
+ * identically with `MEGACOMPACT_VC7B` on or off.
39
+ */
40
+ import { createHash } from "node:crypto";
41
+ /** The registered arms, in canonical bucket order. */
42
+ export const EXPERIMENT_ARMS = ["A", "B", "C"];
43
+ /** Bucket space: 10k buckets = 0.01% resolution (matches VC5C rollout). */
44
+ export const EXPERIMENT_BUCKETS = 10_000;
45
+ /** Even three-way split (the default): 3334 / 3333 / 3333 = 10000. */
46
+ export const EVEN_SPLIT = { A: 3334, B: 3333, C: 3333 };
47
+ /**
48
+ * Length-prefixed field framing, identical in spirit to the crystal key encoder:
49
+ * `<byteLength>:<value>` makes the concatenation injective, so experiment
50
+ * `"a"` + session `"b:c"` cannot collide with experiment `"a:b"` + session `"c"`.
51
+ * Without it, two different (experiment, session) pairs could share a bucket and
52
+ * a session could appear to switch arms when an experiment is renamed.
53
+ */
54
+ function field(value) {
55
+ return `${Buffer.byteLength(value, "utf8")}:${value}`;
56
+ }
57
+ /**
58
+ * The stable bucket for a session: the low 32 bits of
59
+ * `sha256(experimentId, sessionId)`, modulo the bucket space.
60
+ *
61
+ * Deterministic and storage-free — this is what makes a lost assignment journal
62
+ * a non-event. Reading 4 bytes (rather than the whole digest) keeps the value in
63
+ * exact integer range; SHA-256's avalanche means any 32 bits are equidistributed.
64
+ */
65
+ export function experimentBucket(experimentId, sessionId) {
66
+ const h = createHash("sha256")
67
+ .update(field(experimentId) + field(sessionId), "utf8")
68
+ .digest();
69
+ return h.readUInt32BE(0) % EXPERIMENT_BUCKETS;
70
+ }
71
+ /** Validate that a split covers the bucket space exactly once. */
72
+ export function validateSplit(split) {
73
+ for (const n of [split.A, split.B, split.C]) {
74
+ if (!Number.isSafeInteger(n) || n < 0)
75
+ return false;
76
+ }
77
+ return split.A + split.B + split.C === EXPERIMENT_BUCKETS;
78
+ }
79
+ /**
80
+ * Map a bucket to an arm under a split. Arms occupy contiguous bucket ranges in
81
+ * the fixed order A, B, C, so the mapping is stable: widening arm C's share can
82
+ * never reshuffle a session already sitting in arm A.
83
+ */
84
+ export function armForBucket(bucket, split) {
85
+ if (bucket < split.A)
86
+ return "A";
87
+ if (bucket < split.A + split.B)
88
+ return "B";
89
+ return "C";
90
+ }
91
+ /**
92
+ * Assign a session to an experiment arm.
93
+ *
94
+ * The default path is `randomized`: bucket = stable hash, arm = bucket's range.
95
+ * Passing `forced` overrides the arm and downgrades the source (and therefore
96
+ * causal admissibility) — the bucket is still computed and reported so the
97
+ * override remains auditable against what the session WOULD have got.
98
+ *
99
+ * `assignedAt` is injected by the caller. Assignment is a pure function of its
100
+ * arguments, so the same session always yields the same arm no matter when, or
101
+ * how many times, it is asked.
102
+ */
103
+ export function assignExperiment(input) {
104
+ const codes = [];
105
+ if (input.experimentId.trim() === "" || input.sessionId.trim() === "") {
106
+ codes.push("EXP_ID_INVALID");
107
+ }
108
+ const split = input.split ?? EVEN_SPLIT;
109
+ if (!validateSplit(split))
110
+ codes.push("EXP_SPLIT_INVALID");
111
+ if (input.forced !== undefined && !EXPERIMENT_ARMS.includes(input.forced)) {
112
+ codes.push("EXP_ARM_UNKNOWN");
113
+ }
114
+ if (codes.length > 0)
115
+ return { ok: false, codes };
116
+ const bucket = experimentBucket(input.experimentId, input.sessionId);
117
+ const natural = armForBucket(bucket, split);
118
+ const arm = input.forced ?? natural;
119
+ // Precedence: a forced arm is self-selected, so it is never causal even when
120
+ // it happens to agree with the natural arm. Shadow is likewise non-causal.
121
+ const source = input.forced !== undefined ? "forced" : input.shadow === true ? "shadow" : "randomized";
122
+ return {
123
+ ok: true,
124
+ assignment: {
125
+ schema: "cache-experiment-v1",
126
+ experimentId: input.experimentId,
127
+ sessionId: input.sessionId,
128
+ arm,
129
+ bucket,
130
+ source,
131
+ assignedAt: input.assignedAt,
132
+ },
133
+ };
134
+ }
135
+ /**
136
+ * Whether an assignment's telemetry may enter a causal interval.
137
+ *
138
+ * ONLY `randomized`. This single predicate is what keeps forced and shadow rows
139
+ * out of the causal aggregate; every consumer computing an interval must filter
140
+ * through it rather than re-deriving the rule.
141
+ */
142
+ export function isCausallyAdmissible(a) {
143
+ return a.source === "randomized";
144
+ }
145
+ /**
146
+ * Keep only causally admissible assignments. The complement is not discarded by
147
+ * the caller — it is reported as `estimate` — but it never reaches an interval.
148
+ */
149
+ export function causalOnly(assignments) {
150
+ return assignments.filter(isCausallyAdmissible);
151
+ }
152
+ /**
153
+ * Whether every assignment for one session agrees on the arm (CACHE-RANDOM-003).
154
+ * A session that appears in two arms would contaminate both sides of the
155
+ * comparison, so this is asserted directly rather than assumed.
156
+ */
157
+ export function sessionArmsConsistent(assignments) {
158
+ const bySession = new Map();
159
+ for (const a of assignments) {
160
+ const seen = bySession.get(a.sessionId);
161
+ if (seen !== undefined && seen !== a.arm)
162
+ return false;
163
+ bySession.set(a.sessionId, a.arm);
164
+ }
165
+ return true;
166
+ }
@@ -1,2 +1,2 @@
1
- import{b as R,c as W,m as T,i as C,d as F,A as ie,e as B,h as q,j as oe,k as G,l as se,n as le,u as ue,o as K,G as ce,p as J,q as Q,D as fe,g as pe,X as he,Y as de,f as me}from"./generateCategoricalChart-B-IUoLd1.js";import{R as p,F as ee,r as ve}from"./index-Do749WlW.js";var ye=["layout","type","stroke","connectNulls","isRange","ref"],be=["key"],te;function M(e){"@babel/helpers - typeof";return M=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(t){return typeof t}:function(t){return t&&typeof Symbol=="function"&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},M(e)}function ae(e,t){if(e==null)return{};var r=Ae(e,t),a,n;if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)a=i[n],!(t.indexOf(a)>=0)&&Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}function Ae(e,t){if(e==null)return{};var r={};for(var a in e)if(Object.prototype.hasOwnProperty.call(e,a)){if(t.indexOf(a)>=0)continue;r[a]=e[a]}return r}function D(){return D=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var a in r)Object.prototype.hasOwnProperty.call(r,a)&&(e[a]=r[a])}return e},D.apply(this,arguments)}function U(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter(function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable})),r.push.apply(r,a)}return r}function S(e){for(var t=1;t<arguments.length;t++){var r=arguments[t]!=null?arguments[t]:{};t%2?U(Object(r),!0).forEach(function(a){E(e,a,r[a])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):U(Object(r)).forEach(function(a){Object.defineProperty(e,a,Object.getOwnPropertyDescriptor(r,a))})}return e}function ge(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function Z(e,t){for(var r=0;r<t.length;r++){var a=t[r];a.enumerable=a.enumerable||!1,a.configurable=!0,"value"in a&&(a.writable=!0),Object.defineProperty(e,ne(a.key),a)}}function xe(e,t,r){return t&&Z(e.prototype,t),r&&Z(e,r),Object.defineProperty(e,"prototype",{writable:!1}),e}function Pe(e,t,r){return t=$(t),Oe(e,re()?Reflect.construct(t,r||[],$(e).constructor):t.apply(e,r))}function Oe(e,t){if(t&&(M(t)==="object"||typeof t=="function"))return t;if(t!==void 0)throw new TypeError("Derived constructors may only return object or undefined");return Ee(e)}function Ee(e){if(e===void 0)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function re(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch{}return(re=function(){return!!e})()}function $(e){return $=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(r){return r.__proto__||Object.getPrototypeOf(r)},$(e)}function we(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,"prototype",{writable:!1}),t&&X(e,t)}function X(e,t){return X=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(a,n){return a.__proto__=n,a},X(e,t)}function E(e,t,r){return t=ne(t),t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function ne(e){var t=_e(e,"string");return M(t)=="symbol"?t:t+""}function _e(e,t){if(M(e)!="object"||!e)return e;var r=e[Symbol.toPrimitive];if(r!==void 0){var a=r.call(e,t);if(M(a)!="object")return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}var L=function(e){function t(){var r;ge(this,t);for(var a=arguments.length,n=new Array(a),i=0;i<a;i++)n[i]=arguments[i];return r=Pe(this,t,[].concat(n)),E(r,"state",{isAnimationFinished:!0}),E(r,"id",ue("recharts-area-")),E(r,"handleAnimationEnd",function(){var o=r.props.onAnimationEnd;r.setState({isAnimationFinished:!0}),K(o)&&o()}),E(r,"handleAnimationStart",function(){var o=r.props.onAnimationStart;r.setState({isAnimationFinished:!1}),K(o)&&o()}),r}return we(t,e),xe(t,[{key:"renderDots",value:function(a,n,i){var o=this.props.isAnimationActive,s=this.state.isAnimationFinished;if(o&&!s)return null;var u=this.props,l=u.dot,f=u.points,c=u.dataKey,h=R(this.props,!1),A=R(l,!0),g=f.map(function(v,O){var y=S(S(S({key:"dot-".concat(O),r:3},h),A),{},{index:O,cx:v.x,cy:v.y,dataKey:c,value:v.value,payload:v.payload,points:f});return t.renderDotItem(l,y)}),x={clipPath:a?"url(#clipPath-".concat(n?"":"dots-").concat(i,")"):null};return p.createElement(W,D({className:"recharts-area-dots"},x),g)}},{key:"renderHorizontalRect",value:function(a){var n=this.props,i=n.baseLine,o=n.points,s=n.strokeWidth,u=o[0].x,l=o[o.length-1].x,f=a*Math.abs(u-l),c=T(o.map(function(h){return h.y||0}));return C(i)&&typeof i=="number"?c=Math.max(i,c):i&&Array.isArray(i)&&i.length&&(c=Math.max(T(i.map(function(h){return h.y||0})),c)),C(c)?p.createElement("rect",{x:u<l?u:u-f,y:0,width:f,height:Math.floor(c+(s?parseInt("".concat(s),10):1))}):null}},{key:"renderVerticalRect",value:function(a){var n=this.props,i=n.baseLine,o=n.points,s=n.strokeWidth,u=o[0].y,l=o[o.length-1].y,f=a*Math.abs(u-l),c=T(o.map(function(h){return h.x||0}));return C(i)&&typeof i=="number"?c=Math.max(i,c):i&&Array.isArray(i)&&i.length&&(c=Math.max(T(i.map(function(h){return h.x||0})),c)),C(c)?p.createElement("rect",{x:0,y:u<l?u:u-f,width:c+(s?parseInt("".concat(s),10):1),height:Math.floor(f)}):null}},{key:"renderClipRect",value:function(a){var n=this.props.layout;return n==="vertical"?this.renderVerticalRect(a):this.renderHorizontalRect(a)}},{key:"renderAreaStatically",value:function(a,n,i,o){var s=this.props,u=s.layout,l=s.type,f=s.stroke,c=s.connectNulls,h=s.isRange;s.ref;var A=ae(s,ye);return p.createElement(W,{clipPath:i?"url(#clipPath-".concat(o,")"):null},p.createElement(F,D({},R(A,!0),{points:a,connectNulls:c,type:l,baseLine:n,layout:u,stroke:"none",className:"recharts-area-area"})),f!=="none"&&p.createElement(F,D({},R(this.props,!1),{className:"recharts-area-curve",layout:u,type:l,connectNulls:c,fill:"none",points:a})),f!=="none"&&h&&p.createElement(F,D({},R(this.props,!1),{className:"recharts-area-curve",layout:u,type:l,connectNulls:c,fill:"none",points:n})))}},{key:"renderAreaWithAnimation",value:function(a,n){var i=this,o=this.props,s=o.points,u=o.baseLine,l=o.isAnimationActive,f=o.animationBegin,c=o.animationDuration,h=o.animationEasing,A=o.animationId,g=this.state,x=g.prevPoints,v=g.prevBaseLine;return p.createElement(ie,{begin:f,duration:c,isActive:l,easing:h,from:{t:0},to:{t:1},key:"area-".concat(A),onAnimationEnd:this.handleAnimationEnd,onAnimationStart:this.handleAnimationStart},function(O){var y=O.t;if(x){var _=x.length/s.length,d=s.map(function(P,N){var k=Math.floor(N*_);if(x[k]){var j=x[k],I=B(j.x,P.x),V=B(j.y,P.y);return S(S({},P),{},{x:I(y),y:V(y)})}return P}),m;if(C(u)&&typeof u=="number"){var b=B(v,u);m=b(y)}else if(q(u)||oe(u)){var w=B(v,0);m=w(y)}else m=u.map(function(P,N){var k=Math.floor(N*_);if(v[k]){var j=v[k],I=B(j.x,P.x),V=B(j.y,P.y);return S(S({},P),{},{x:I(y),y:V(y)})}return P});return i.renderAreaStatically(d,m,a,n)}return p.createElement(W,null,p.createElement("defs",null,p.createElement("clipPath",{id:"animationClipPath-".concat(n)},i.renderClipRect(y))),p.createElement(W,{clipPath:"url(#animationClipPath-".concat(n,")")},i.renderAreaStatically(s,u,a,n)))})}},{key:"renderArea",value:function(a,n){var i=this.props,o=i.points,s=i.baseLine,u=i.isAnimationActive,l=this.state,f=l.prevPoints,c=l.prevBaseLine,h=l.totalLength;return u&&o&&o.length&&(!f&&h>0||!G(f,o)||!G(c,s))?this.renderAreaWithAnimation(a,n):this.renderAreaStatically(o,s,a,n)}},{key:"render",value:function(){var a,n=this.props,i=n.hide,o=n.dot,s=n.points,u=n.className,l=n.top,f=n.left,c=n.xAxis,h=n.yAxis,A=n.width,g=n.height,x=n.isAnimationActive,v=n.id;if(i||!s||!s.length)return null;var O=this.state.isAnimationFinished,y=s.length===1,_=ee("recharts-area",u),d=c&&c.allowDataOverflow,m=h&&h.allowDataOverflow,b=d||m,w=q(v)?this.id:v,P=(a=R(o,!1))!==null&&a!==void 0?a:{r:3,strokeWidth:2},N=P.r,k=N===void 0?3:N,j=P.strokeWidth,I=j===void 0?2:j,V=se(o)?o:{},Y=V.clipDot,H=Y===void 0?!0:Y,z=k*2+I;return p.createElement(W,{className:_},d||m?p.createElement("defs",null,p.createElement("clipPath",{id:"clipPath-".concat(w)},p.createElement("rect",{x:d?f:f-A/2,y:m?l:l-g/2,width:d?A:A*2,height:m?g:g*2})),!H&&p.createElement("clipPath",{id:"clipPath-dots-".concat(w)},p.createElement("rect",{x:f-z/2,y:l-z/2,width:A+z,height:g+z}))):null,y?null:this.renderArea(b,w),(o||y)&&this.renderDots(b,H,w),(!x||O)&&le.renderCallByParent(this.props,s))}}],[{key:"getDerivedStateFromProps",value:function(a,n){return a.animationId!==n.prevAnimationId?{prevAnimationId:a.animationId,curPoints:a.points,curBaseLine:a.baseLine,prevPoints:n.curPoints,prevBaseLine:n.curBaseLine}:a.points!==n.curPoints||a.baseLine!==n.curBaseLine?{curPoints:a.points,curBaseLine:a.baseLine}:null}}])}(ve.PureComponent);te=L;E(L,"displayName","Area");E(L,"defaultProps",{stroke:"#3182bd",fill:"#3182bd",fillOpacity:.6,xAxisId:0,yAxisId:0,legendType:"line",connectNulls:!1,points:[],dot:!1,activeDot:!0,hide:!1,isAnimationActive:!ce.isSsr,animationBegin:0,animationDuration:1500,animationEasing:"ease"});E(L,"getBaseValue",function(e,t,r,a){var n=e.layout,i=e.baseValue,o=t.props.baseValue,s=o??i;if(C(s)&&typeof s=="number")return s;var u=n==="horizontal"?a:r,l=u.scale.domain();if(u.type==="number"){var f=Math.max(l[0],l[1]),c=Math.min(l[0],l[1]);return s==="dataMin"?c:s==="dataMax"||f<0?f:Math.max(Math.min(l[0],l[1]),0)}return s==="dataMin"?l[0]:s==="dataMax"?l[1]:l[0]});E(L,"getComposedData",function(e){var t=e.props,r=e.item,a=e.xAxis,n=e.yAxis,i=e.xAxisTicks,o=e.yAxisTicks,s=e.bandSize,u=e.dataKey,l=e.stackedData,f=e.dataStartIndex,c=e.displayedData,h=e.offset,A=t.layout,g=l&&l.length,x=te.getBaseValue(t,r,a,n),v=A==="horizontal",O=!1,y=c.map(function(d,m){var b;g?b=l[f+m]:(b=J(d,u),Array.isArray(b)?O=!0:b=[x,b]);var w=b[1]==null||g&&J(d,u)==null;return v?{x:Q({axis:a,ticks:i,bandSize:s,entry:d,index:m}),y:w?null:n.scale(b[1]),value:b,payload:d}:{x:w?null:a.scale(b[1]),y:Q({axis:n,ticks:o,bandSize:s,entry:d,index:m}),value:b,payload:d}}),_;return g||O?_=y.map(function(d){var m=Array.isArray(d.value)?d.value[0]:null;return v?{x:d.x,y:m!=null&&d.y!=null?n.scale(m):null}:{x:m!=null?a.scale(m):null,y:d.y}}):_=v?n.scale(x):a.scale(x),S({points:y,baseLine:_,layout:A,isRange:O},h)});E(L,"renderDotItem",function(e,t){var r;if(p.isValidElement(e))r=p.cloneElement(e,t);else if(K(e))r=e(t);else{var a=ee("recharts-area-dot",typeof e!="boolean"?e.className:""),n=t.key,i=ae(t,be);r=p.createElement(fe,D({},i,{key:n,className:a}))}return r});var ke=pe({chartName:"AreaChart",GraphicalChild:L,axisComponents:[{axisType:"xAxis",AxisComp:he},{axisType:"yAxis",AxisComp:de}],formatAxisMap:me});export{ke as A,L as a};
2
- //# sourceMappingURL=AreaChart-CB-U7ViX.js.map
1
+ import{b as R,c as W,m as T,i as C,d as F,A as ie,e as B,h as q,j as oe,k as G,l as se,n as le,u as ue,o as K,G as ce,p as J,q as Q,D as fe,g as pe,X as he,Y as de,f as me}from"./generateCategoricalChart-CMmkuwj5.js";import{R as p,F as ee,r as ve}from"./index-Dz8GPBOE.js";var ye=["layout","type","stroke","connectNulls","isRange","ref"],be=["key"],te;function M(e){"@babel/helpers - typeof";return M=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(t){return typeof t}:function(t){return t&&typeof Symbol=="function"&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},M(e)}function ae(e,t){if(e==null)return{};var r=Ae(e,t),a,n;if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)a=i[n],!(t.indexOf(a)>=0)&&Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}function Ae(e,t){if(e==null)return{};var r={};for(var a in e)if(Object.prototype.hasOwnProperty.call(e,a)){if(t.indexOf(a)>=0)continue;r[a]=e[a]}return r}function D(){return D=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var a in r)Object.prototype.hasOwnProperty.call(r,a)&&(e[a]=r[a])}return e},D.apply(this,arguments)}function U(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter(function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable})),r.push.apply(r,a)}return r}function S(e){for(var t=1;t<arguments.length;t++){var r=arguments[t]!=null?arguments[t]:{};t%2?U(Object(r),!0).forEach(function(a){E(e,a,r[a])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):U(Object(r)).forEach(function(a){Object.defineProperty(e,a,Object.getOwnPropertyDescriptor(r,a))})}return e}function ge(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function Z(e,t){for(var r=0;r<t.length;r++){var a=t[r];a.enumerable=a.enumerable||!1,a.configurable=!0,"value"in a&&(a.writable=!0),Object.defineProperty(e,ne(a.key),a)}}function xe(e,t,r){return t&&Z(e.prototype,t),r&&Z(e,r),Object.defineProperty(e,"prototype",{writable:!1}),e}function Pe(e,t,r){return t=$(t),Oe(e,re()?Reflect.construct(t,r||[],$(e).constructor):t.apply(e,r))}function Oe(e,t){if(t&&(M(t)==="object"||typeof t=="function"))return t;if(t!==void 0)throw new TypeError("Derived constructors may only return object or undefined");return Ee(e)}function Ee(e){if(e===void 0)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function re(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch{}return(re=function(){return!!e})()}function $(e){return $=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(r){return r.__proto__||Object.getPrototypeOf(r)},$(e)}function we(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,"prototype",{writable:!1}),t&&X(e,t)}function X(e,t){return X=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(a,n){return a.__proto__=n,a},X(e,t)}function E(e,t,r){return t=ne(t),t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function ne(e){var t=_e(e,"string");return M(t)=="symbol"?t:t+""}function _e(e,t){if(M(e)!="object"||!e)return e;var r=e[Symbol.toPrimitive];if(r!==void 0){var a=r.call(e,t);if(M(a)!="object")return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}var L=function(e){function t(){var r;ge(this,t);for(var a=arguments.length,n=new Array(a),i=0;i<a;i++)n[i]=arguments[i];return r=Pe(this,t,[].concat(n)),E(r,"state",{isAnimationFinished:!0}),E(r,"id",ue("recharts-area-")),E(r,"handleAnimationEnd",function(){var o=r.props.onAnimationEnd;r.setState({isAnimationFinished:!0}),K(o)&&o()}),E(r,"handleAnimationStart",function(){var o=r.props.onAnimationStart;r.setState({isAnimationFinished:!1}),K(o)&&o()}),r}return we(t,e),xe(t,[{key:"renderDots",value:function(a,n,i){var o=this.props.isAnimationActive,s=this.state.isAnimationFinished;if(o&&!s)return null;var u=this.props,l=u.dot,f=u.points,c=u.dataKey,h=R(this.props,!1),A=R(l,!0),g=f.map(function(v,O){var y=S(S(S({key:"dot-".concat(O),r:3},h),A),{},{index:O,cx:v.x,cy:v.y,dataKey:c,value:v.value,payload:v.payload,points:f});return t.renderDotItem(l,y)}),x={clipPath:a?"url(#clipPath-".concat(n?"":"dots-").concat(i,")"):null};return p.createElement(W,D({className:"recharts-area-dots"},x),g)}},{key:"renderHorizontalRect",value:function(a){var n=this.props,i=n.baseLine,o=n.points,s=n.strokeWidth,u=o[0].x,l=o[o.length-1].x,f=a*Math.abs(u-l),c=T(o.map(function(h){return h.y||0}));return C(i)&&typeof i=="number"?c=Math.max(i,c):i&&Array.isArray(i)&&i.length&&(c=Math.max(T(i.map(function(h){return h.y||0})),c)),C(c)?p.createElement("rect",{x:u<l?u:u-f,y:0,width:f,height:Math.floor(c+(s?parseInt("".concat(s),10):1))}):null}},{key:"renderVerticalRect",value:function(a){var n=this.props,i=n.baseLine,o=n.points,s=n.strokeWidth,u=o[0].y,l=o[o.length-1].y,f=a*Math.abs(u-l),c=T(o.map(function(h){return h.x||0}));return C(i)&&typeof i=="number"?c=Math.max(i,c):i&&Array.isArray(i)&&i.length&&(c=Math.max(T(i.map(function(h){return h.x||0})),c)),C(c)?p.createElement("rect",{x:0,y:u<l?u:u-f,width:c+(s?parseInt("".concat(s),10):1),height:Math.floor(f)}):null}},{key:"renderClipRect",value:function(a){var n=this.props.layout;return n==="vertical"?this.renderVerticalRect(a):this.renderHorizontalRect(a)}},{key:"renderAreaStatically",value:function(a,n,i,o){var s=this.props,u=s.layout,l=s.type,f=s.stroke,c=s.connectNulls,h=s.isRange;s.ref;var A=ae(s,ye);return p.createElement(W,{clipPath:i?"url(#clipPath-".concat(o,")"):null},p.createElement(F,D({},R(A,!0),{points:a,connectNulls:c,type:l,baseLine:n,layout:u,stroke:"none",className:"recharts-area-area"})),f!=="none"&&p.createElement(F,D({},R(this.props,!1),{className:"recharts-area-curve",layout:u,type:l,connectNulls:c,fill:"none",points:a})),f!=="none"&&h&&p.createElement(F,D({},R(this.props,!1),{className:"recharts-area-curve",layout:u,type:l,connectNulls:c,fill:"none",points:n})))}},{key:"renderAreaWithAnimation",value:function(a,n){var i=this,o=this.props,s=o.points,u=o.baseLine,l=o.isAnimationActive,f=o.animationBegin,c=o.animationDuration,h=o.animationEasing,A=o.animationId,g=this.state,x=g.prevPoints,v=g.prevBaseLine;return p.createElement(ie,{begin:f,duration:c,isActive:l,easing:h,from:{t:0},to:{t:1},key:"area-".concat(A),onAnimationEnd:this.handleAnimationEnd,onAnimationStart:this.handleAnimationStart},function(O){var y=O.t;if(x){var _=x.length/s.length,d=s.map(function(P,N){var k=Math.floor(N*_);if(x[k]){var j=x[k],I=B(j.x,P.x),V=B(j.y,P.y);return S(S({},P),{},{x:I(y),y:V(y)})}return P}),m;if(C(u)&&typeof u=="number"){var b=B(v,u);m=b(y)}else if(q(u)||oe(u)){var w=B(v,0);m=w(y)}else m=u.map(function(P,N){var k=Math.floor(N*_);if(v[k]){var j=v[k],I=B(j.x,P.x),V=B(j.y,P.y);return S(S({},P),{},{x:I(y),y:V(y)})}return P});return i.renderAreaStatically(d,m,a,n)}return p.createElement(W,null,p.createElement("defs",null,p.createElement("clipPath",{id:"animationClipPath-".concat(n)},i.renderClipRect(y))),p.createElement(W,{clipPath:"url(#animationClipPath-".concat(n,")")},i.renderAreaStatically(s,u,a,n)))})}},{key:"renderArea",value:function(a,n){var i=this.props,o=i.points,s=i.baseLine,u=i.isAnimationActive,l=this.state,f=l.prevPoints,c=l.prevBaseLine,h=l.totalLength;return u&&o&&o.length&&(!f&&h>0||!G(f,o)||!G(c,s))?this.renderAreaWithAnimation(a,n):this.renderAreaStatically(o,s,a,n)}},{key:"render",value:function(){var a,n=this.props,i=n.hide,o=n.dot,s=n.points,u=n.className,l=n.top,f=n.left,c=n.xAxis,h=n.yAxis,A=n.width,g=n.height,x=n.isAnimationActive,v=n.id;if(i||!s||!s.length)return null;var O=this.state.isAnimationFinished,y=s.length===1,_=ee("recharts-area",u),d=c&&c.allowDataOverflow,m=h&&h.allowDataOverflow,b=d||m,w=q(v)?this.id:v,P=(a=R(o,!1))!==null&&a!==void 0?a:{r:3,strokeWidth:2},N=P.r,k=N===void 0?3:N,j=P.strokeWidth,I=j===void 0?2:j,V=se(o)?o:{},Y=V.clipDot,H=Y===void 0?!0:Y,z=k*2+I;return p.createElement(W,{className:_},d||m?p.createElement("defs",null,p.createElement("clipPath",{id:"clipPath-".concat(w)},p.createElement("rect",{x:d?f:f-A/2,y:m?l:l-g/2,width:d?A:A*2,height:m?g:g*2})),!H&&p.createElement("clipPath",{id:"clipPath-dots-".concat(w)},p.createElement("rect",{x:f-z/2,y:l-z/2,width:A+z,height:g+z}))):null,y?null:this.renderArea(b,w),(o||y)&&this.renderDots(b,H,w),(!x||O)&&le.renderCallByParent(this.props,s))}}],[{key:"getDerivedStateFromProps",value:function(a,n){return a.animationId!==n.prevAnimationId?{prevAnimationId:a.animationId,curPoints:a.points,curBaseLine:a.baseLine,prevPoints:n.curPoints,prevBaseLine:n.curBaseLine}:a.points!==n.curPoints||a.baseLine!==n.curBaseLine?{curPoints:a.points,curBaseLine:a.baseLine}:null}}])}(ve.PureComponent);te=L;E(L,"displayName","Area");E(L,"defaultProps",{stroke:"#3182bd",fill:"#3182bd",fillOpacity:.6,xAxisId:0,yAxisId:0,legendType:"line",connectNulls:!1,points:[],dot:!1,activeDot:!0,hide:!1,isAnimationActive:!ce.isSsr,animationBegin:0,animationDuration:1500,animationEasing:"ease"});E(L,"getBaseValue",function(e,t,r,a){var n=e.layout,i=e.baseValue,o=t.props.baseValue,s=o??i;if(C(s)&&typeof s=="number")return s;var u=n==="horizontal"?a:r,l=u.scale.domain();if(u.type==="number"){var f=Math.max(l[0],l[1]),c=Math.min(l[0],l[1]);return s==="dataMin"?c:s==="dataMax"||f<0?f:Math.max(Math.min(l[0],l[1]),0)}return s==="dataMin"?l[0]:s==="dataMax"?l[1]:l[0]});E(L,"getComposedData",function(e){var t=e.props,r=e.item,a=e.xAxis,n=e.yAxis,i=e.xAxisTicks,o=e.yAxisTicks,s=e.bandSize,u=e.dataKey,l=e.stackedData,f=e.dataStartIndex,c=e.displayedData,h=e.offset,A=t.layout,g=l&&l.length,x=te.getBaseValue(t,r,a,n),v=A==="horizontal",O=!1,y=c.map(function(d,m){var b;g?b=l[f+m]:(b=J(d,u),Array.isArray(b)?O=!0:b=[x,b]);var w=b[1]==null||g&&J(d,u)==null;return v?{x:Q({axis:a,ticks:i,bandSize:s,entry:d,index:m}),y:w?null:n.scale(b[1]),value:b,payload:d}:{x:w?null:a.scale(b[1]),y:Q({axis:n,ticks:o,bandSize:s,entry:d,index:m}),value:b,payload:d}}),_;return g||O?_=y.map(function(d){var m=Array.isArray(d.value)?d.value[0]:null;return v?{x:d.x,y:m!=null&&d.y!=null?n.scale(m):null}:{x:m!=null?a.scale(m):null,y:d.y}}):_=v?n.scale(x):a.scale(x),S({points:y,baseLine:_,layout:A,isRange:O},h)});E(L,"renderDotItem",function(e,t){var r;if(p.isValidElement(e))r=p.cloneElement(e,t);else if(K(e))r=e(t);else{var a=ee("recharts-area-dot",typeof e!="boolean"?e.className:""),n=t.key,i=ae(t,be);r=p.createElement(fe,D({},i,{key:n,className:a}))}return r});var ke=pe({chartName:"AreaChart",GraphicalChild:L,axisComponents:[{axisType:"xAxis",AxisComp:he},{axisType:"yAxis",AxisComp:de}],formatAxisMap:me});export{ke as A,L as a};
2
+ //# sourceMappingURL=AreaChart-CV8WqMmt.js.map