pi-mega-compact 0.20.53 → 0.20.55
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 +1 -1
- package/dist/config/vector-cortex-cosfp.js +31 -0
- package/dist/config/vector-cortex.js +2 -0
- package/dist/config.js +1 -1
- package/dist/extensions/dashboard-server/api-contracts/cosine-fp.js +8 -0
- package/dist/extensions/dashboard-server/api-contracts/endpoints/registry-ext.js +7 -0
- package/dist/extensions/dashboard-server/route-dispatch.js +3 -1
- package/dist/extensions/dashboard-server/routes-cosine-fp.js +261 -0
- package/dist/extensions/dashboard-server/routes-rag-settings-helpers.js +8 -0
- package/dist/extensions/dashboard-server/routes-rag-settings-vector-cortex.js +1 -0
- package/dist/extensions/dashboard-server/routes.js +1 -0
- package/dist/src/config/dedup.js +11 -0
- package/dist/src/config/vector-cortex-cosfp.js +31 -0
- package/dist/src/config/vector-cortex.js +2 -0
- package/dist/src/config.js +1 -1
- package/extensions/dashboard-client/dist/assets/{AreaChart-COjQ_jJm.js → AreaChart-DlndN0p2.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{AreaChart-COjQ_jJm.js.map → AreaChart-DlndN0p2.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{BarChart-eAIpwb8c.js → BarChart-DH6rZ60s.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{BarChart-eAIpwb8c.js.map → BarChart-DH6rZ60s.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/CacheTab-Qj_NYKw3.js +2 -0
- package/extensions/dashboard-client/dist/assets/{CacheTab-BS_G9_YV.js.map → CacheTab-Qj_NYKw3.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{EventsTab-CDFk5d3P.js → EventsTab-3QlIPMFj.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{EventsTab-CDFk5d3P.js.map → EventsTab-3QlIPMFj.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{HealthTab-zFyPJb5b.js → HealthTab-DTwitpIb.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{HealthTab-zFyPJb5b.js.map → HealthTab-DTwitpIb.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-DxJX4lXh.js → MaintenanceTab-DkVlBnp7.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-DxJX4lXh.js.map → MaintenanceTab-DkVlBnp7.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/MemoryMapTab-B-pHH85r.js +2 -0
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-CRy5I6mg.js.map → MemoryMapTab-B-pHH85r.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MetricsTab-K4kPea0Q.js → MetricsTab-C8VpwhJN.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MetricsTab-K4kPea0Q.js.map → MetricsTab-C8VpwhJN.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{OverviewTab-BZoJ1oOv.js → OverviewTab-C_JZlM_Q.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{OverviewTab-BZoJ1oOv.js.map → OverviewTab-C_JZlM_Q.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{ReposTab-uMFKxT0a.js → ReposTab-rRMlub-E.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{ReposTab-uMFKxT0a.js.map → ReposTab-rRMlub-E.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SessionsTab-DDzmcCuH.js → SessionsTab-CL6S094G.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SessionsTab-DDzmcCuH.js.map → SessionsTab-CL6S094G.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/SetupTab-C6b8YuBK.js +3 -0
- package/extensions/dashboard-client/dist/assets/SetupTab-C6b8YuBK.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-D_mBYAzE.js → TimeSavedCard-B-8NCvzd.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-D_mBYAzE.js.map → TimeSavedCard-B-8NCvzd.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TurnsTab-C6xr2lsO.js → TurnsTab-C2MVgG4N.js} +3 -3
- package/extensions/dashboard-client/dist/assets/{TurnsTab-C6xr2lsO.js.map → TurnsTab-C2MVgG4N.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{VcStatusBadge-J0DVlxH0.js → VcStatusBadge-CvlS_fvh.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{VcStatusBadge-J0DVlxH0.js.map → VcStatusBadge-CvlS_fvh.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{VectorCortexTab-AvL73DpJ.js → VectorCortexTab-BXCAzwQm.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{VectorCortexTab-AvL73DpJ.js.map → VectorCortexTab-BXCAzwQm.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{WikiTab-DVcIWjLT.js → WikiTab-DUivYmJ5.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{WikiTab-DVcIWjLT.js.map → WikiTab-DUivYmJ5.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{button-Cl_gFaIf.js → button-dTpuinxr.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{button-Cl_gFaIf.js.map → button-dTpuinxr.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{card-DMzHffVs.js → card-DNwZ7dSg.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{card-DMzHffVs.js.map → card-DNwZ7dSg.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/client-extra-CQuCpjyO.js +2 -0
- package/extensions/dashboard-client/dist/assets/{client-extra-Dkkppa5C.js.map → client-extra-CQuCpjyO.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-Bi8zQmZN.js → generateCategoricalChart-D1HV4d79.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-Bi8zQmZN.js.map → generateCategoricalChart-D1HV4d79.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{index-mZRDesSq.js → index-Bi5YNsLx.js} +11 -11
- package/extensions/dashboard-client/dist/assets/index-Bi5YNsLx.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{switch-K_lsOl6x.js → switch-DiKc2q4n.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{switch-K_lsOl6x.js.map → switch-DiKc2q4n.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{toggle-67IU2JLn.js → toggle-BBYD10JO.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{toggle-67IU2JLn.js.map → toggle-BBYD10JO.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{useSSE-DiLgyP7C.js → useSSE-CWUSDhIb.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{useSSE-DiLgyP7C.js.map → useSSE-CWUSDhIb.js.map} +1 -1
- package/extensions/dashboard-client/dist/index.html +1 -1
- package/extensions/dashboard-client/src/tabs/SetupTab/CortexSetup.tsx +2 -0
- package/extensions/dashboard-client/src/tabs/SetupTab/VectorCortexCosineFpCard.tsx +130 -0
- package/extensions/dashboard-server/api-contracts/cosine-fp.ts +81 -0
- package/extensions/dashboard-server/api-contracts/endpoints/registry-ext.ts +11 -0
- package/extensions/dashboard-server/api-contracts/index.ts +14 -0
- package/extensions/dashboard-server/assets/cosine-fp-report.json +1 -0
- package/extensions/dashboard-server/route-dispatch.ts +2 -0
- package/extensions/dashboard-server/routes-cosine-fp.ts +288 -0
- package/extensions/dashboard-server/routes-rag-settings-helpers.ts +8 -0
- package/extensions/dashboard-server/routes-rag-settings-vector-cortex.ts +6 -0
- package/extensions/dashboard-server/routes.ts +1 -0
- package/package.json +1 -1
- package/src/config/dedup.ts +17 -0
- package/src/config/vector-cortex-cosfp.ts +34 -0
- package/src/config/vector-cortex.ts +2 -0
- package/src/config.ts +1 -0
- package/extensions/dashboard-client/dist/assets/CacheTab-BS_G9_YV.js +0 -2
- package/extensions/dashboard-client/dist/assets/MemoryMapTab-CRy5I6mg.js +0 -2
- package/extensions/dashboard-client/dist/assets/SetupTab-KLTE-VKV.js +0 -3
- package/extensions/dashboard-client/dist/assets/SetupTab-KLTE-VKV.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/client-extra-Dkkppa5C.js +0 -2
- package/extensions/dashboard-client/dist/assets/index-mZRDesSq.js.map +0 -1
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* api-contracts/cosine-fp.ts — cosine-FP report API contract (COS-FP-A).
|
|
3
|
+
*
|
|
4
|
+
* Reader-only shape for GET /api/cosine-fp-report: the last written synthetic
|
|
5
|
+
* bench aggregate + report digest + recommendation. The bench emits counts +
|
|
6
|
+
* fractions + digests ONLY (EVAL-REDACT-002) — never template text. No `any`.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** Derived endpoint status (from vc-status.ts). */
|
|
10
|
+
export type CosineFpStatus = "live" | "awaiting_data" | "deferred" | "structural" | "off";
|
|
11
|
+
|
|
12
|
+
/** The bench aggregate's own outcome label. */
|
|
13
|
+
export type CosineFpBenchStatus = "ok" | "no_data" | "off" | "awaiting_data";
|
|
14
|
+
|
|
15
|
+
export interface CosineFpGrid {
|
|
16
|
+
readonly lo: number;
|
|
17
|
+
readonly hi: number;
|
|
18
|
+
readonly step: number;
|
|
19
|
+
readonly points: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface CosineFpPerTypeCounts {
|
|
23
|
+
readonly items: number;
|
|
24
|
+
readonly dup: number;
|
|
25
|
+
readonly near: number;
|
|
26
|
+
readonly clean: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface CosineFpPerTypeResult {
|
|
30
|
+
readonly fp: number;
|
|
31
|
+
readonly fpRate: number | null;
|
|
32
|
+
readonly fn: number;
|
|
33
|
+
readonly fnRate: number | null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface CosineFpPerTypeRow {
|
|
37
|
+
readonly code: CosineFpPerTypeResult;
|
|
38
|
+
readonly prose: CosineFpPerTypeResult;
|
|
39
|
+
readonly mixed: CosineFpPerTypeResult;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface CosineFpRow {
|
|
43
|
+
readonly threshold: number;
|
|
44
|
+
readonly overallFpRate: number | null;
|
|
45
|
+
readonly overallFnRate: number | null;
|
|
46
|
+
readonly overallF1: number | null;
|
|
47
|
+
readonly perType: CosineFpPerTypeRow;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface CosineFpCorpusSummary {
|
|
51
|
+
readonly items: number;
|
|
52
|
+
readonly pairs: number;
|
|
53
|
+
readonly types: string[];
|
|
54
|
+
readonly perType: Readonly<Record<string, CosineFpPerTypeCounts>>;
|
|
55
|
+
readonly digest: string | null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface CosineFpOverrides {
|
|
59
|
+
readonly code: number | null;
|
|
60
|
+
readonly prose: number | null;
|
|
61
|
+
readonly mixed: number | null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Response body for GET /api/cosine-fp-report. */
|
|
65
|
+
export interface CosineFpReportV1 {
|
|
66
|
+
/** Derived endpoint status (deriveVcStatus): off (flag) / awaiting_data (no run). */
|
|
67
|
+
readonly status: CosineFpStatus;
|
|
68
|
+
/** Outcome the bench itself recorded: ok / no_data / off / awaiting_data. */
|
|
69
|
+
readonly benchStatus: CosineFpBenchStatus;
|
|
70
|
+
readonly seed: number | null;
|
|
71
|
+
readonly grid: CosineFpGrid | null;
|
|
72
|
+
readonly corpusSummary: CosineFpCorpusSummary | null;
|
|
73
|
+
readonly rows: CosineFpRow[] | null;
|
|
74
|
+
readonly recommendedDefault: number | null;
|
|
75
|
+
readonly shippedDefault: number;
|
|
76
|
+
readonly overrides: CosineFpOverrides | null;
|
|
77
|
+
readonly fpBudget: number | null;
|
|
78
|
+
readonly digest: string | null;
|
|
79
|
+
/** mtime (epoch ms) of the bench-run aggregate file backing this response. */
|
|
80
|
+
readonly reportFileMtime: number | null;
|
|
81
|
+
}
|
|
@@ -31,6 +31,7 @@ import type {
|
|
|
31
31
|
CortexImproveStatus,
|
|
32
32
|
} from "../cortex-improve.js";
|
|
33
33
|
import type { DedupTierAttributionResponse } from "../dedup-attribution.js";
|
|
34
|
+
import type { CosineFpReportV1 } from "../cosine-fp.js";
|
|
34
35
|
|
|
35
36
|
/** Additive endpoint entries spread into the ENDPOINTS registry. */
|
|
36
37
|
export const EXTRA_ENDPOINTS = {
|
|
@@ -169,4 +170,14 @@ export const EXTRA_ENDPOINTS = {
|
|
|
169
170
|
undefined,
|
|
170
171
|
DedupTierAttributionResponse
|
|
171
172
|
>,
|
|
173
|
+
|
|
174
|
+
// ─── COS-FP-A cosine threshold report ────────────────────────────
|
|
175
|
+
|
|
176
|
+
/** GET /api/cosine-fp-report — reader-only synthetic FP bench recommendation. */
|
|
177
|
+
cosineFpReport: {
|
|
178
|
+
method: "GET",
|
|
179
|
+
path: "/api/cosine-fp-report",
|
|
180
|
+
description:
|
|
181
|
+
"Reader-only cosine-FP report (COS-FP-A): the last written synthetic bench aggregate — grid summary, per-content-type FP/FN/F1, recommended default, report digest. Counts + fractions + digests only, never template text. Missing report → awaiting_data; flag-off returns 404.",
|
|
182
|
+
} as const satisfies EndpointDef<"GET", undefined, CosineFpReportV1>,
|
|
172
183
|
} as const;
|
|
@@ -343,3 +343,17 @@ export type {
|
|
|
343
343
|
DedupTierAccumulator,
|
|
344
344
|
DedupTierAttributionResponse,
|
|
345
345
|
} from "./dedup-attribution.js";
|
|
346
|
+
|
|
347
|
+
// COS-FP-A — synthetic cosine threshold report
|
|
348
|
+
export type {
|
|
349
|
+
CosineFpStatus,
|
|
350
|
+
CosineFpBenchStatus,
|
|
351
|
+
CosineFpGrid,
|
|
352
|
+
CosineFpPerTypeCounts,
|
|
353
|
+
CosineFpPerTypeResult,
|
|
354
|
+
CosineFpPerTypeRow,
|
|
355
|
+
CosineFpRow,
|
|
356
|
+
CosineFpCorpusSummary,
|
|
357
|
+
CosineFpOverrides,
|
|
358
|
+
CosineFpReportV1,
|
|
359
|
+
} from "./cosine-fp.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"corpusSummary":{"digest":"53f87630c2fa1ee5c4020d025fda56caae5020110bb12521e6c9a85981e180c5","items":72,"pairs":2556,"perType":{"code":{"clean":8,"dup":8,"items":24,"near":8},"mixed":{"clean":8,"dup":8,"items":24,"near":8},"prose":{"clean":8,"dup":8,"items":24,"near":8}},"types":["code","prose","mixed"]},"digest":"2312c120c43c75ff46db9fc8f362c25df879a54862790d8d2cbac2e88466d646","fpBudget":0.05,"grid":{"hi":0.98,"lo":0.8,"points":37,"step":0.005},"overrides":{"code":0.915,"mixed":0.955,"prose":0.95},"recommendedDefault":0.815,"rows":[{"overallF1":0.1279,"overallFnRate":0.9314,"overallFpRate":0.0612,"perType":{"code":{"fn":128,"fnRate":0.8205,"fp":23,"fpRate":0.1917},"mixed":{"fn":135,"fnRate":0.8654,"fp":13,"fpRate":0.1083},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.8},{"overallF1":0.1255,"overallFnRate":0.9328,"overallFpRate":0.0576,"perType":{"code":{"fn":128,"fnRate":0.8205,"fp":22,"fpRate":0.1833},"mixed":{"fn":135,"fnRate":0.8654,"fp":12,"fpRate":0.1},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.805},{"overallF1":0.1182,"overallFnRate":0.937,"overallFpRate":0.0532,"perType":{"code":{"fn":131,"fnRate":0.8397,"fp":21,"fpRate":0.175},"mixed":{"fn":136,"fnRate":0.8718,"fp":10,"fpRate":0.0833},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.81},{"overallF1":0.1133,"overallFnRate":0.9398,"overallFpRate":0.0488,"perType":{"code":{"fn":131,"fnRate":0.8397,"fp":18,"fpRate":0.15},"mixed":{"fn":139,"fnRate":0.891,"fp":9,"fpRate":0.075},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.815},{"overallF1":0.112,"overallFnRate":0.9405,"overallFpRate":0.0488,"perType":{"code":{"fn":131,"fnRate":0.8397,"fp":18,"fpRate":0.15},"mixed":{"fn":139,"fnRate":0.891,"fp":9,"fpRate":0.075},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.82},{"overallF1":0.1108,"overallFnRate":0.9412,"overallFpRate":0.0479,"perType":{"code":{"fn":132,"fnRate":0.8462,"fp":18,"fpRate":0.15},"mixed":{"fn":139,"fnRate":0.891,"fp":9,"fpRate":0.075},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.825},{"overallF1":0.1096,"overallFnRate":0.9419,"overallFpRate":0.0461,"perType":{"code":{"fn":132,"fnRate":0.8462,"fp":17,"fpRate":0.1417},"mixed":{"fn":139,"fnRate":0.891,"fp":9,"fpRate":0.075},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.83},{"overallF1":0.0945,"overallFnRate":0.9503,"overallFpRate":0.0399,"perType":{"code":{"fn":136,"fnRate":0.8718,"fp":15,"fpRate":0.125},"mixed":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.835},{"overallF1":0.0844,"overallFnRate":0.9559,"overallFpRate":0.0337,"perType":{"code":{"fn":139,"fnRate":0.891,"fp":13,"fpRate":0.1083},"mixed":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.84},{"overallF1":0.0805,"overallFnRate":0.958,"overallFpRate":0.0301,"perType":{"code":{"fn":140,"fnRate":0.8974,"fp":10,"fpRate":0.0833},"mixed":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.845},{"overallF1":0.0805,"overallFnRate":0.958,"overallFpRate":0.0293,"perType":{"code":{"fn":140,"fnRate":0.8974,"fp":10,"fpRate":0.0833},"mixed":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.85},{"overallF1":0.078,"overallFnRate":0.9594,"overallFpRate":0.0284,"perType":{"code":{"fn":140,"fnRate":0.8974,"fp":9,"fpRate":0.075},"mixed":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.855},{"overallF1":0.0728,"overallFnRate":0.9622,"overallFpRate":0.0248,"perType":{"code":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"mixed":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.86},{"overallF1":0.0728,"overallFnRate":0.9622,"overallFpRate":0.0239,"perType":{"code":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"mixed":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.865},{"overallF1":0.0689,"overallFnRate":0.9643,"overallFpRate":0.023,"perType":{"code":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"mixed":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.87},{"overallF1":0.0689,"overallFnRate":0.9643,"overallFpRate":0.0222,"perType":{"code":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"mixed":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.875},{"overallF1":0.0689,"overallFnRate":0.9643,"overallFpRate":0.0222,"perType":{"code":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"mixed":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.88},{"overallF1":0.0689,"overallFnRate":0.9643,"overallFpRate":0.0222,"perType":{"code":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"mixed":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.885},{"overallF1":0.065,"overallFnRate":0.9664,"overallFpRate":0.0213,"perType":{"code":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"mixed":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.89},{"overallF1":0.065,"overallFnRate":0.9664,"overallFpRate":0.0213,"perType":{"code":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"mixed":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.895},{"overallF1":0.065,"overallFnRate":0.9664,"overallFpRate":0.0213,"perType":{"code":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"mixed":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.9},{"overallF1":0.0637,"overallFnRate":0.9671,"overallFpRate":0.0204,"perType":{"code":{"fn":141,"fnRate":0.9038,"fp":7,"fpRate":0.0583},"mixed":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.905},{"overallF1":0.0624,"overallFnRate":0.9678,"overallFpRate":0.0204,"perType":{"code":{"fn":142,"fnRate":0.9103,"fp":7,"fpRate":0.0583},"mixed":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.91},{"overallF1":0.0624,"overallFnRate":0.9678,"overallFpRate":0.0195,"perType":{"code":{"fn":142,"fnRate":0.9103,"fp":6,"fpRate":0.05},"mixed":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.915},{"overallF1":0.0611,"overallFnRate":0.9685,"overallFpRate":0.0186,"perType":{"code":{"fn":143,"fnRate":0.9167,"fp":5,"fpRate":0.0417},"mixed":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.92},{"overallF1":0.0611,"overallFnRate":0.9685,"overallFpRate":0.0186,"perType":{"code":{"fn":143,"fnRate":0.9167,"fp":5,"fpRate":0.0417},"mixed":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.925},{"overallF1":0.0611,"overallFnRate":0.9685,"overallFpRate":0.0186,"perType":{"code":{"fn":143,"fnRate":0.9167,"fp":5,"fpRate":0.0417},"mixed":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.93},{"overallF1":0.0598,"overallFnRate":0.9692,"overallFpRate":0.0177,"perType":{"code":{"fn":144,"fnRate":0.9231,"fp":4,"fpRate":0.0333},"mixed":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.935},{"overallF1":0.0598,"overallFnRate":0.9692,"overallFpRate":0.0177,"perType":{"code":{"fn":144,"fnRate":0.9231,"fp":4,"fpRate":0.0333},"mixed":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.94},{"overallF1":0.0558,"overallFnRate":0.9713,"overallFpRate":0.0151,"perType":{"code":{"fn":146,"fnRate":0.9359,"fp":2,"fpRate":0.0167},"mixed":{"fn":141,"fnRate":0.9038,"fp":7,"fpRate":0.0583},"prose":{"fn":140,"fnRate":0.8974,"fp":8,"fpRate":0.0667}},"threshold":0.945},{"overallF1":0.0505,"overallFnRate":0.9741,"overallFpRate":0.0115,"perType":{"code":{"fn":148,"fnRate":0.9487,"fp":0,"fpRate":0},"mixed":{"fn":141,"fnRate":0.9038,"fp":7,"fpRate":0.0583},"prose":{"fn":142,"fnRate":0.9103,"fp":6,"fpRate":0.05}},"threshold":0.95},{"overallF1":0.0465,"overallFnRate":0.9762,"overallFpRate":0.0089,"perType":{"code":{"fn":148,"fnRate":0.9487,"fp":0,"fpRate":0},"mixed":{"fn":143,"fnRate":0.9167,"fp":5,"fpRate":0.0417},"prose":{"fn":143,"fnRate":0.9167,"fp":5,"fpRate":0.0417}},"threshold":0.955},{"overallF1":0.0438,"overallFnRate":0.9776,"overallFpRate":0.0071,"perType":{"code":{"fn":148,"fnRate":0.9487,"fp":0,"fpRate":0},"mixed":{"fn":143,"fnRate":0.9167,"fp":5,"fpRate":0.0417},"prose":{"fn":145,"fnRate":0.9295,"fp":3,"fpRate":0.025}},"threshold":0.96},{"overallF1":0.0411,"overallFnRate":0.979,"overallFpRate":0.0053,"perType":{"code":{"fn":148,"fnRate":0.9487,"fp":0,"fpRate":0},"mixed":{"fn":144,"fnRate":0.9231,"fp":4,"fpRate":0.0333},"prose":{"fn":146,"fnRate":0.9359,"fp":2,"fpRate":0.0167}},"threshold":0.965},{"overallF1":0.0385,"overallFnRate":0.9804,"overallFpRate":0.0035,"perType":{"code":{"fn":148,"fnRate":0.9487,"fp":0,"fpRate":0},"mixed":{"fn":145,"fnRate":0.9295,"fp":3,"fpRate":0.025},"prose":{"fn":147,"fnRate":0.9423,"fp":1,"fpRate":0.0083}},"threshold":0.97},{"overallF1":0.0344,"overallFnRate":0.9825,"overallFpRate":0.0009,"perType":{"code":{"fn":148,"fnRate":0.9487,"fp":0,"fpRate":0},"mixed":{"fn":148,"fnRate":0.9487,"fp":0,"fpRate":0},"prose":{"fn":147,"fnRate":0.9423,"fp":1,"fpRate":0.0083}},"threshold":0.975},{"overallF1":0.0331,"overallFnRate":0.9832,"overallFpRate":0,"perType":{"code":{"fn":148,"fnRate":0.9487,"fp":0,"fpRate":0},"mixed":{"fn":148,"fnRate":0.9487,"fp":0,"fpRate":0},"prose":{"fn":148,"fnRate":0.9487,"fp":0,"fpRate":0}},"threshold":0.98}],"seed":20260806,"shippedDefault":0.85,"status":"ok"}
|
|
@@ -63,6 +63,7 @@ import {
|
|
|
63
63
|
handleImproveCortex,
|
|
64
64
|
handleImproveCortexStatus,
|
|
65
65
|
handleDedupTierAttribution,
|
|
66
|
+
handleCosineFpReport,
|
|
66
67
|
} from "./routes.js";
|
|
67
68
|
// VC6C repair lives in its own module (routes-vector-cortex-repair.ts) so the
|
|
68
69
|
// heal route file stays well under the 400-line extension soft limit.
|
|
@@ -160,5 +161,6 @@ export function dispatchRoutes(
|
|
|
160
161
|
if (handleImproveCortex(req, res, ctx)) return true;
|
|
161
162
|
if (handleImproveCortexStatus(req, res, ctx)) return true;
|
|
162
163
|
if (handleDedupTierAttribution(req, res, ctx)) return true;
|
|
164
|
+
if (handleCosineFpReport(req, res, ctx)) return true;
|
|
163
165
|
return false;
|
|
164
166
|
}
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dashboard-server/routes-cosine-fp.ts — COS-FP-A cosine-FP report route.
|
|
3
|
+
*
|
|
4
|
+
* GET /api/cosine-fp-report — reader-only aggregate answering "what did the last
|
|
5
|
+
* synthetic bench recommend for the L2 cosine threshold?". Reads the last
|
|
6
|
+
* written bench-run aggregate (scripts/cosine-fp/bench-run/cosine-fp-report.json,
|
|
7
|
+
* located by walking up to the repo root) + its mtime, memoized by
|
|
8
|
+
* {mtime,size} (mirrors routes-vector-cortex-health.ts memoized-facts), and
|
|
9
|
+
* serves the report digest + recommendation + grid summary. Reader-only: emits
|
|
10
|
+
* counts + fractions + digests, never template text (EVAL-REDACT-002).
|
|
11
|
+
*
|
|
12
|
+
* Flag-off (MEGACOMPACT_COSINE_FP_BENCH=0) returns 404 — byte-identical
|
|
13
|
+
* predecessor. Missing report file is reported as `awaiting_data` with
|
|
14
|
+
* benchStatus awaiting_data — never a fabricated zero row (COS-FP-A-003).
|
|
15
|
+
*
|
|
16
|
+
* Guardrails: PREVENT-PI-004 (local filesystem read only), PREVENT-001
|
|
17
|
+
* (JSON.parse guarded), PREVENT-011 (no `any`).
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
21
|
+
import { readFileSync, statSync } from "node:fs";
|
|
22
|
+
import { join, dirname } from "node:path";
|
|
23
|
+
import { fileURLToPath } from "node:url";
|
|
24
|
+
import type { RouteContext } from "./routes-core.js";
|
|
25
|
+
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
26
|
+
import { COSINE_FP_BENCH_ENABLED } from "../../src/config.js";
|
|
27
|
+
import { deriveVcStatus } from "./vc-status.js";
|
|
28
|
+
import type {
|
|
29
|
+
CosineFpReportV1,
|
|
30
|
+
CosineFpBenchStatus,
|
|
31
|
+
CosineFpPerTypeCounts,
|
|
32
|
+
} from "./api-contracts/cosine-fp.js";
|
|
33
|
+
|
|
34
|
+
const MEMO_TTL_MS = 5000; // ≤5s per file state
|
|
35
|
+
const REPORT_FILENAME = "cosine-fp-report.json";
|
|
36
|
+
|
|
37
|
+
interface MemoEntry {
|
|
38
|
+
key: string;
|
|
39
|
+
at: number;
|
|
40
|
+
body: CosineFpReportV1;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let memo: MemoEntry | null = null;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Resolve the dir containing the cosine-fp-report.json aggregate. Two locations
|
|
47
|
+
* are probed in order:
|
|
48
|
+
*
|
|
49
|
+
* 1. The bundled asset `extensions/dashboard-server/assets/cosine-fp-report.json`.
|
|
50
|
+
* This is the PRODUCTION path: the `extensions/` source tree ships at the
|
|
51
|
+
* npm package root, so `/api/cosine-fp-report` serves the recommendation on
|
|
52
|
+
* an installed package (PREVENT-DIST-001). tsc does NOT copy `.json` assets
|
|
53
|
+
* into `dist/`, so the compiled module probes both the co-located
|
|
54
|
+
* `assets/` (source tree) and the repo-root `extensions/.../assets/`
|
|
55
|
+
* (reached from `dist/extensions/dashboard-server/`). Without the bundled
|
|
56
|
+
* asset the endpoint would always return `awaiting_data` on devices,
|
|
57
|
+
* because `scripts/` (the bench-run path) is NOT shipped.
|
|
58
|
+
*
|
|
59
|
+
* 2. The git-checkout bench-run dir (`scripts/cosine-fp/bench-run/`) for dev
|
|
60
|
+
* use, walked up to from this module — this is where `bench.mjs` writes the
|
|
61
|
+
* report.
|
|
62
|
+
*
|
|
63
|
+
* The test seam MEGACOMPACT_COSINE_FP_BENCH_RUN_DIR (read lazily so a test can
|
|
64
|
+
* set it post-import) overrides BOTH so route tests can point at a temp dir
|
|
65
|
+
* without touching the repo or the bundled asset.
|
|
66
|
+
*/
|
|
67
|
+
export function benchRunDir(): string | null {
|
|
68
|
+
const testRunDir = process.env.MEGACOMPACT_COSINE_FP_BENCH_RUN_DIR;
|
|
69
|
+
if (testRunDir) return testRunDir;
|
|
70
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
71
|
+
// 1. Bundled asset candidates — the PRODUCTION path (PREVENT-DIST-001). tsc
|
|
72
|
+
// does NOT copy `.json` assets into dist/, and the `extensions/` source
|
|
73
|
+
// tree ships at the package root next to `dist/`. Probe both relative to
|
|
74
|
+
// this module's location (mirrors server.ts clientDist candidates):
|
|
75
|
+
// here = extensions/dashboard-server (source tree, dev run)
|
|
76
|
+
// here = dist/extensions/dashboard-server (compiled, published)
|
|
77
|
+
const bundledCandidates = [
|
|
78
|
+
join(here, "assets"), // source tree / co-located
|
|
79
|
+
join(here, "..", "..", "..", "extensions", "dashboard-server", "assets"), // repo-root source from compiled dist/
|
|
80
|
+
];
|
|
81
|
+
for (const bundled of bundledCandidates) {
|
|
82
|
+
try {
|
|
83
|
+
// guardrails-allow PREVENT-PI-004: local bundled report stat (loopback)
|
|
84
|
+
statSync(join(bundled, REPORT_FILENAME));
|
|
85
|
+
return bundled;
|
|
86
|
+
} catch {
|
|
87
|
+
/* try next candidate, then fall through to git-checkout walk */
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// 2. Git-checkout bench-run dir — dev path only.
|
|
91
|
+
let dir = here;
|
|
92
|
+
const rel = join("scripts", "cosine-fp", "bench-run");
|
|
93
|
+
for (let i = 0; i < 8; i++) {
|
|
94
|
+
const candidate = join(dir, rel);
|
|
95
|
+
try {
|
|
96
|
+
// guardrails-allow PREVENT-PI-004: local bench-run dir stat (loopback)
|
|
97
|
+
statSync(candidate);
|
|
98
|
+
return candidate;
|
|
99
|
+
} catch {
|
|
100
|
+
/* keep walking */
|
|
101
|
+
}
|
|
102
|
+
const next = dirname(dir);
|
|
103
|
+
if (next === dir) break;
|
|
104
|
+
dir = next;
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Read + minimally validate the aggregate JSON (PREVENT-001). Returns null on
|
|
110
|
+
* any parse/shape failure — the caller treats that as awaiting_data, never as
|
|
111
|
+
* a fabricated zero row. */
|
|
112
|
+
function readAggregate(runDir: string): Record<string, unknown> | null {
|
|
113
|
+
const p = join(runDir, "cosine-fp-report.json");
|
|
114
|
+
let raw: string;
|
|
115
|
+
try {
|
|
116
|
+
raw = readFileSync(p, "utf8"); // guardrails-allow PREVENT-PI-004: local bench-run report read (loopback)
|
|
117
|
+
} catch {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
let parsed: unknown;
|
|
121
|
+
try {
|
|
122
|
+
parsed = JSON.parse(raw);
|
|
123
|
+
} catch {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
|
|
127
|
+
return parsed as Record<string, unknown>;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function toNum(v: unknown): number | null {
|
|
131
|
+
return typeof v === "number" && Number.isFinite(v) ? v : null;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** Project per-content-type count entries into the contract shape (PREVENT-011). */
|
|
135
|
+
function projectPerType(
|
|
136
|
+
raw: unknown,
|
|
137
|
+
): Readonly<Record<string, CosineFpPerTypeCounts>> {
|
|
138
|
+
const out: Record<string, CosineFpPerTypeCounts> = {};
|
|
139
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return out;
|
|
140
|
+
for (const [key, v] of Object.entries(raw as Record<string, unknown>)) {
|
|
141
|
+
if (!v || typeof v !== "object" || Array.isArray(v)) continue;
|
|
142
|
+
const o = v as Record<string, unknown>;
|
|
143
|
+
out[key] = {
|
|
144
|
+
items: toNum(o.items) ?? 0,
|
|
145
|
+
dup: toNum(o.dup) ?? 0,
|
|
146
|
+
near: toNum(o.near) ?? 0,
|
|
147
|
+
clean: toNum(o.clean) ?? 0,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
return out;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** Project the raw aggregate into the full CosineFpReportV1 (reader-only). */
|
|
154
|
+
function buildBody(runDir: string, aggregate: Record<string, unknown>): CosineFpReportV1 {
|
|
155
|
+
let mtime: number | null = null;
|
|
156
|
+
try {
|
|
157
|
+
const s = statSync(join(runDir, "cosine-fp-report.json")); // guardrails-allow PREVENT-PI-004: local stat (loopback)
|
|
158
|
+
mtime = s.mtimeMs;
|
|
159
|
+
} catch {
|
|
160
|
+
mtime = null;
|
|
161
|
+
}
|
|
162
|
+
const benchStatus: CosineFpBenchStatus = aggregate.status === "ok" ? "ok" : "no_data";
|
|
163
|
+
const hasData = benchStatus === "ok";
|
|
164
|
+
const status = deriveVcStatus({ enabled: true, hasData, structuralOnly: false });
|
|
165
|
+
|
|
166
|
+
const grid = aggregate.grid;
|
|
167
|
+
const overrides = aggregate.overrides;
|
|
168
|
+
const corpus = aggregate.corpusSummary;
|
|
169
|
+
const rows = aggregate.rows;
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
status,
|
|
173
|
+
benchStatus,
|
|
174
|
+
seed: toNum(aggregate.seed),
|
|
175
|
+
grid:
|
|
176
|
+
grid && typeof grid === "object"
|
|
177
|
+
? {
|
|
178
|
+
lo: toNum((grid as Record<string, unknown>).lo) ?? 0,
|
|
179
|
+
hi: toNum((grid as Record<string, unknown>).hi) ?? 0,
|
|
180
|
+
step: toNum((grid as Record<string, unknown>).step) ?? 0,
|
|
181
|
+
points: toNum((grid as Record<string, unknown>).points) ?? 0,
|
|
182
|
+
}
|
|
183
|
+
: null,
|
|
184
|
+
corpusSummary:
|
|
185
|
+
corpus && typeof corpus === "object"
|
|
186
|
+
? {
|
|
187
|
+
items: toNum((corpus as Record<string, unknown>).items) ?? 0,
|
|
188
|
+
pairs: toNum((corpus as Record<string, unknown>).pairs) ?? 0,
|
|
189
|
+
types: Array.isArray((corpus as Record<string, unknown>).types)
|
|
190
|
+
? ((corpus as Record<string, unknown>).types as string[])
|
|
191
|
+
: [],
|
|
192
|
+
perType: projectPerType((corpus as Record<string, unknown>).perType),
|
|
193
|
+
digest:
|
|
194
|
+
typeof (corpus as Record<string, unknown>).digest === "string"
|
|
195
|
+
? ((corpus as Record<string, unknown>).digest as string)
|
|
196
|
+
: null,
|
|
197
|
+
}
|
|
198
|
+
: null,
|
|
199
|
+
rows: Array.isArray(rows) ? (rows as CosineFpReportV1["rows"]) : null,
|
|
200
|
+
recommendedDefault: toNum(aggregate.recommendedDefault),
|
|
201
|
+
shippedDefault: toNum(aggregate.shippedDefault) ?? 0.85,
|
|
202
|
+
overrides:
|
|
203
|
+
overrides && typeof overrides === "object"
|
|
204
|
+
? {
|
|
205
|
+
code: toNum((overrides as Record<string, unknown>).code),
|
|
206
|
+
prose: toNum((overrides as Record<string, unknown>).prose),
|
|
207
|
+
mixed: toNum((overrides as Record<string, unknown>).mixed),
|
|
208
|
+
}
|
|
209
|
+
: null,
|
|
210
|
+
fpBudget: toNum(aggregate.fpBudget),
|
|
211
|
+
digest: typeof aggregate.digest === "string" ? (aggregate.digest as string) : null,
|
|
212
|
+
reportFileMtime: mtime,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function awaitingDataBody(reason: "flag" | "missing"): CosineFpReportV1 {
|
|
217
|
+
const status = deriveVcStatus({
|
|
218
|
+
enabled: reason !== "flag",
|
|
219
|
+
hasData: false,
|
|
220
|
+
structuralOnly: false,
|
|
221
|
+
});
|
|
222
|
+
return {
|
|
223
|
+
status,
|
|
224
|
+
benchStatus: reason === "flag" ? "off" : "awaiting_data",
|
|
225
|
+
seed: null,
|
|
226
|
+
grid: null,
|
|
227
|
+
corpusSummary: null,
|
|
228
|
+
rows: null,
|
|
229
|
+
recommendedDefault: null,
|
|
230
|
+
shippedDefault: 0.85,
|
|
231
|
+
overrides: null,
|
|
232
|
+
fpBudget: null,
|
|
233
|
+
digest: null,
|
|
234
|
+
reportFileMtime: null,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export function handleCosineFpReport(
|
|
239
|
+
req: IncomingMessage,
|
|
240
|
+
res: ServerResponse,
|
|
241
|
+
_ctx: RouteContext,
|
|
242
|
+
): boolean {
|
|
243
|
+
const url = req.url ?? "";
|
|
244
|
+
if (url !== "/api/cosine-fp-report") return false;
|
|
245
|
+
if (req.method !== "GET") {
|
|
246
|
+
sendJson(res, 405, { error: "method_not_allowed" });
|
|
247
|
+
return true;
|
|
248
|
+
}
|
|
249
|
+
if (!COSINE_FP_BENCH_ENABLED()) {
|
|
250
|
+
// Flag-off: 404 — byte-identical predecessor.
|
|
251
|
+
sendJson(res, 404, { error: "not_found" });
|
|
252
|
+
return true;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const runDir = benchRunDir();
|
|
256
|
+
if (runDir === null) {
|
|
257
|
+
sendJson(res, 200, awaitingDataBody("missing"));
|
|
258
|
+
return true;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Memoized-facts pattern: serve a still-fresh entry keyed on {mtime,size}.
|
|
262
|
+
let size = 0;
|
|
263
|
+
let mtime = 0;
|
|
264
|
+
try {
|
|
265
|
+
const s = statSync(join(runDir, "cosine-fp-report.json")); // guardrails-allow PREVENT-PI-004: local stat (loopback)
|
|
266
|
+
size = s.size;
|
|
267
|
+
mtime = s.mtimeMs;
|
|
268
|
+
} catch {
|
|
269
|
+
// no report on disk yet
|
|
270
|
+
}
|
|
271
|
+
if (size === 0 && mtime === 0) {
|
|
272
|
+
sendJson(res, 200, awaitingDataBody("missing"));
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const key = `${mtime}:${size}`;
|
|
277
|
+
const now = Date.now();
|
|
278
|
+
if (memo !== null && memo.key === key && now - memo.at <= MEMO_TTL_MS) {
|
|
279
|
+
sendJson(res, 200, memo.body);
|
|
280
|
+
return true;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const aggregate = readAggregate(runDir);
|
|
284
|
+
const body = aggregate === null ? awaitingDataBody("missing") : buildBody(runDir, aggregate);
|
|
285
|
+
memo = { key, at: now, body };
|
|
286
|
+
sendJson(res, 200, body);
|
|
287
|
+
return true;
|
|
288
|
+
}
|
|
@@ -331,4 +331,12 @@ export const EXCLUDED_SETTINGS: readonly string[] = [
|
|
|
331
331
|
"MEGACOMPACT_RAPTOR_LEVEL_WEIGHTS",
|
|
332
332
|
// Internal calibration, not user-facing.
|
|
333
333
|
"MEGACOMPACT_FTS5_MAX_BM25",
|
|
334
|
+
// COS-FP-A: per-content-type L2 override landing slots. Null/unset by
|
|
335
|
+
// default and NOT wired into the live L2 decision this sprint — the
|
|
336
|
+
// top-level MEGACOMPACT_L2_THRESHOLD is the single runtime firing point. A
|
|
337
|
+
// default-OFF numeric slot is not yet an adjustable firing knob, so it is
|
|
338
|
+
// excluded (the report carries the recommendation; adoption is a separate
|
|
339
|
+
// gated sprint).
|
|
340
|
+
"MEGACOMPACT_L2_THRESHOLD_CODE",
|
|
341
|
+
"MEGACOMPACT_L2_THRESHOLD_PROSE",
|
|
334
342
|
];
|
|
@@ -312,5 +312,11 @@ export const VECTOR_CORTEX_SETTINGS: SettingGroup = {
|
|
|
312
312
|
"ENC-2a exposes the runtime operator knob MEGACOMPACT_NATIVE_ORT_BUDGET_MIB (default 300 MiB, clamp 8192) as a dashboard Settings field. The knob gates budgetOk in the encoder runtime decision (decision.ts installBudgetMib + runtime-select.ts selectRuntimeBackend). Persisted to the per-repo .mega-compact.env via the setup-configure writer branch; the GET status route surfaces the persisted value AND the effective integer installBudgetMib() resolves to (so the dashboard shows the runtime's actual operand). OFF = no new GET fields, no writer branch, no new Settings rows (byte-identical ENC-1b predecessor).",
|
|
313
313
|
true,
|
|
314
314
|
),
|
|
315
|
+
boolDirect(
|
|
316
|
+
"MEGACOMPACT_COSINE_FP_BENCH",
|
|
317
|
+
"COS-FP-A Synthetic FP Bench",
|
|
318
|
+
"Synthetic FP harness + L2 cosine threshold calibration (COS-FP-A): drives the deterministic synthetic-corpus grid sweep (scripts/cosine-fp/bench.mjs) that measures L2 cosine false-positive rates and emits a recommended default, and serves the reader-only GET /api/cosine-fp-report. Synthetic-corpus-only — never reads real session/ledger bytes. OFF = bench inert, endpoint 404s, no report write, L2_COSINE plain MEGACOMPACT_L2_THRESHOLD (byte-identical predecessor).",
|
|
319
|
+
true,
|
|
320
|
+
),
|
|
315
321
|
],
|
|
316
322
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-mega-compact",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.55",
|
|
4
4
|
"description": "Layered, local, vector-backed context compressor for pi — supersede/collapse/cluster compaction with deduped inline recall.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "BSD-3-Clause",
|
package/src/config/dedup.ts
CHANGED
|
@@ -28,6 +28,15 @@ function envNum(name: string, def: number): number {
|
|
|
28
28
|
return Number.isFinite(n) ? n : def;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
/** COS-FP-A: numeric env var that is `null` when unset ("off") — a dormant
|
|
32
|
+
* override whose absence must mean "no behavior change". */
|
|
33
|
+
function envNumOrNull(name: string): number | null {
|
|
34
|
+
const v = process.env[name];
|
|
35
|
+
if (v === undefined || v === "off" || v === "") return null;
|
|
36
|
+
const n = Number(v);
|
|
37
|
+
return Number.isFinite(n) ? n : null;
|
|
38
|
+
}
|
|
39
|
+
|
|
31
40
|
/** S42B: parse a comma-separated numeric env var (e.g. "1.0,0.9,0.8"). */
|
|
32
41
|
function envNumArray(name: string, def: number[]): number[] {
|
|
33
42
|
const v = process.env[name];
|
|
@@ -50,6 +59,12 @@ export interface DedupConfigShape {
|
|
|
50
59
|
MINILM_EMBEDDER: boolean;
|
|
51
60
|
// Thresholds.
|
|
52
61
|
L2_COSINE: number; // semantic dedup firing point
|
|
62
|
+
/** COS-FP-A: optional per-content-type L2 override — null when unset (the
|
|
63
|
+
* top-level L2_COSINE remains the single runtime firing point; these are a
|
|
64
|
+
* default-OFF landing slot for the compliance report's recommendation, NOT
|
|
65
|
+
* wired into the live L2 decision this sprint). */
|
|
66
|
+
L2_COSINE_CODE: number | null;
|
|
67
|
+
L2_COSINE_PROSE: number | null;
|
|
53
68
|
L1_JACCARD: number; // MinHash/LSH near-dup verification
|
|
54
69
|
DEDUP_SIM: number; // legacy content-similarity fallback
|
|
55
70
|
MMR_LAMBDA: number; // retrieval diversity
|
|
@@ -105,6 +120,8 @@ export function loadDedupConfig(): DedupConfigShape {
|
|
|
105
120
|
MARK_ONLY_L2: envBool("MEGACOMPACT_MARK_ONLY_L2", false),
|
|
106
121
|
MINILM_EMBEDDER: envBool("MEGACOMPACT_MINILM", false),
|
|
107
122
|
L2_COSINE: envNum("MEGACOMPACT_L2_THRESHOLD", 0.85),
|
|
123
|
+
L2_COSINE_CODE: envNumOrNull("MEGACOMPACT_L2_THRESHOLD_CODE"),
|
|
124
|
+
L2_COSINE_PROSE: envNumOrNull("MEGACOMPACT_L2_THRESHOLD_PROSE"),
|
|
108
125
|
L1_JACCARD: envNum("MEGACOMPACT_L1_JACCARD", 0.8),
|
|
109
126
|
DEDUP_SIM: envNum("MEGACOMPACT_DEDUP_SIM", 0.9),
|
|
110
127
|
MMR_LAMBDA: envNum("MEGACOMPACT_MMR_LAMBDA", 0.5),
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* config/vector-cortex-cosfp.ts — COS-FP-A synthetic FP harness sprint flag.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from vector-cortex.ts so that barrel stays under the 300-line soft
|
|
5
|
+
* limit (soft-as-hard gate), exactly as vector-cortex-vc9a.ts and the other
|
|
6
|
+
* per-sprint flag siblings were. Gating the synthetic cosine false-positive
|
|
7
|
+
* harness: the corpus/bench scripts, the derived report, and the reader-only
|
|
8
|
+
* GET /api/cosine-fp-report endpoint. A pure-local, synthetic-corpus-only tool
|
|
9
|
+
* (EVAL-REDACT-002) — it never reads real session/ledger bytes.
|
|
10
|
+
*
|
|
11
|
+
* The split is mechanical: COSINE_FP_BENCH_ENABLED is byte-identical in name,
|
|
12
|
+
* semantics, and default to the sibling flag convention (positive, default ON),
|
|
13
|
+
* and vector-cortex.ts re-exports it so every existing
|
|
14
|
+
* `from "./config/vector-cortex.js"` import keeps resolving unchanged.
|
|
15
|
+
*
|
|
16
|
+
* Pi-agnostic, dependency-free (PREVENT-PI-004 / PREVENT-011).
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { sprintFlag } from "./vector-cortex-flag.js";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* COS-FP-A — synthetic FP harness + L2 cosine threshold calibration.
|
|
23
|
+
* Default ON. `MEGACOMPACT_COSINE_FP_BENCH=0` disables and is byte-identical to
|
|
24
|
+
* the predecessor: `scripts/cosine-fp/bench.mjs` is inert (gates report
|
|
25
|
+
* emission + the endpoint to 404/absent), no report is (re)written, and
|
|
26
|
+
* `L2_COSINE` continues to be plain `MEGACOMPACT_L2_THRESHOLD`. The two
|
|
27
|
+
* content-type override fields added to config/dedup.ts are null when unset and
|
|
28
|
+
* are NOT wired into the live L2 decision this sprint (a declared landing slot
|
|
29
|
+
* for the report's per-content-type recommendation). This flag MUST also be a
|
|
30
|
+
* dashboard SETTINGS toggle (visible in config UI, never in EXCLUDED_SETTINGS).
|
|
31
|
+
* The harness + endpoint perform only local filesystem reads (PREVENT-PI-004).
|
|
32
|
+
*/
|
|
33
|
+
export const COSINE_FP_BENCH_ENABLED = (): boolean =>
|
|
34
|
+
sprintFlag("MEGACOMPACT_COSINE_FP_BENCH");
|
|
@@ -62,6 +62,8 @@ export { ENC_0D_ENABLED } from "./vector-cortex-enc0d.js";
|
|
|
62
62
|
export { ENC_0E_ENABLED } from "./vector-cortex-enc0e.js";
|
|
63
63
|
export { ENC_0F_ENABLED } from "./vector-cortex-enc0f.js";
|
|
64
64
|
export { ENC_0G_ENABLED } from "./vector-cortex-enc0g.js";
|
|
65
|
+
// COS-FP-A synthetic FP harness flag extracted to vector-cortex-cosfp.ts.
|
|
66
|
+
export { COSINE_FP_BENCH_ENABLED } from "./vector-cortex-cosfp.js";
|
|
65
67
|
export { ENC_1A_ENABLED } from "./vector-cortex-enc1a.js";
|
|
66
68
|
export {
|
|
67
69
|
ENC_1B_ENABLED,
|
package/src/config.ts
CHANGED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{j as e,r as h,u as m,x as I,y as k,w,l as D}from"./index-mZRDesSq.js";import{C as W,T as F}from"./TimeSavedCard-D_mBYAzE.js";import{b as u,c as v,d as _,e as O,f as x}from"./format-COjDIVGj.js";import{l as G}from"./pricing-DkYp8-vi.js";import{C as f,a as C,b as S,c as N}from"./card-DMzHffVs.js";import{B}from"./button-Cl_gFaIf.js";import{a as K}from"./client-extra-Dkkppa5C.js";function L(t){return t>=80?"ov-stat-value-green":t>=50?"ov-stat-value-yellow":"ov-stat-value-red"}function U(t){return t==null?"":t>=0?"ov-stat-value-green":"ov-stat-value-red"}function n({label:t,value:a,className:s,title:l}){return e.jsxs("div",{className:"flex items-baseline justify-between border-b border-border py-1 text-sm",children:[e.jsx("span",{className:"text-xs text-muted-foreground",title:l,children:t}),e.jsx("span",{className:`font-semibold${s?` ${s}`:""}`,children:a})]})}function V(t){return e.jsxs(f,{className:"electric-hover",children:[e.jsx(C,{children:e.jsx(S,{children:"Provider Prompt Cache"})}),e.jsxs(N,{children:[e.jsx(n,{label:"Cache Hit Rate",value:`${t.hitPct.toFixed(1)}%`,className:L(t.hitPct)}),e.jsx(n,{label:"Turns Recorded",value:String(t.turnCount)}),e.jsx(n,{label:"Cache Read Tokens",value:u(t.totalCacheRead)}),e.jsx(n,{label:"Cache Write Tokens",value:u(t.totalCacheWrite)}),e.jsx(n,{label:"Input Tokens",value:u(t.totalInput)}),e.jsx(n,{label:"$ Saved (reads)",value:v(t.cacheReadSaved)}),e.jsx(n,{label:"Write Investment",value:v(t.cacheWriteCost)}),e.jsx(n,{label:"Net Saved",value:v(t.netSaved),className:U(t.netSaved)}),e.jsx(n,{label:"Model",value:t.modelLabel??"—"}),e.jsx(n,{label:"Tracked Since",value:_(t.firstTurnAt)}),e.jsx(n,{label:"Last Updated",value:O(t.latestTurnAt)}),t.byModel.length>0&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"mt-2 text-xs font-semibold text-muted-foreground",children:"Per Model"}),t.byModel.map(a=>{const s=G(a.model),l=s!=null?a.totalCacheRead/1e6*s:null,r=s!=null?a.totalCacheWrite/1e6*s:null;return e.jsxs("div",{className:"mt-2",children:[e.jsx(n,{label:"Model",value:a.model}),e.jsx(n,{label:"Hit Rate",value:`${a.hitPct.toFixed(1)}%`,className:L(a.hitPct)}),e.jsx(n,{label:"Cache Read",value:u(a.totalCacheRead)}),e.jsx(n,{label:"Cache Write",value:u(a.totalCacheWrite)}),e.jsx(n,{label:"Samples",value:String(a.sampleCount)}),e.jsx(n,{label:"$ Saved (reads)",value:l!=null?v(l):"—"}),e.jsx(n,{label:"Write Investment",value:r!=null?v(r):"—"})]},a.model)})]})]})]})}const q=["ov-bar-green","ov-bar-blue","ov-bar-teal","ov-bar-yellow","ov-bar-gray"],z=["Permanent","Epoch","Topic","Thread","Volatile"],J={good:"ov-text-green",fair:"ov-text-yellow",degraded:"ov-text-orange",poor:"ov-text-red"};function Q({data:t}){const a=Math.max(...t.buckets.map(l=>l.count),1),s=J[t.health.label]??"ov-text-gray";return e.jsxs("div",{className:"ov-card",children:[e.jsx("h3",{className:"ov-card-title",children:"Cache Stripe Distribution"}),e.jsxs("div",{className:"ov-stripe-health-summary",children:[e.jsx("span",{className:`ov-stripe-health-badge ${s}`,children:t.health.label}),e.jsx("span",{className:"ov-stripe-health-score",children:x(t.health.score)}),e.jsxs("span",{className:"ov-stripe-churn",children:["Churn: ",x(t.health.churnRate)]}),e.jsxs("span",{className:"ov-stripe-total",children:[t.totalChunks," total chunks"]})]}),e.jsx("div",{className:"ov-stripe-bars",children:t.buckets.map(l=>{const r=a>0?Math.max(0,Math.min(100,l.count/a*100)):0,i=q[l.stripe]??"ov-bar-gray",o=l.label||(z[l.stripe]??`Stripe ${l.stripe}`);return e.jsxs("div",{className:"ov-stripe-row",children:[e.jsx("span",{className:"ov-stripe-label",title:o,children:o}),e.jsx("div",{className:"ov-bar-track",children:e.jsx("div",{className:`ov-bar-fill ${i}`,style:{width:`${r}%`}})}),e.jsx("span",{className:"ov-stripe-count",children:l.count}),e.jsx("span",{className:"ov-stripe-stability",title:`min ${x(l.minStability)} / max ${x(l.maxStability)}`,children:x(l.avgStability)})]},l.stripe)})}),e.jsxs("div",{className:"ov-stripe-footer",children:["Epoch: ",t.epochId??"—","· Dominant tier: ",x(t.health.dominantTier)]})]})}function g(t){return`${t.toFixed(1)}%`}function X(t){return t>=80?"ov-bar-green":t>=60?"ov-bar-teal":t>=40?"ov-bar-yellow":t>=20?"ov-bar-orange":"ov-bar-red"}const Y=({perf:t})=>{const{cache_hit_pct:a}=t,s=a.samples&&a.samples.length>0?a.samples:[];return e.jsxs(f,{className:"electric-hover",children:[e.jsx(C,{children:e.jsx(S,{children:"Cache Hit-Rate Trend"})}),e.jsxs(N,{children:[e.jsxs("div",{className:"mb-3 flex gap-4 text-sm text-muted-foreground",children:[e.jsxs("div",{children:["Avg: ",e.jsx("strong",{className:"text-foreground",children:g(a.avg)})]}),e.jsxs("div",{children:["Latest: ",e.jsx("strong",{className:"text-foreground",children:g(a.latest)})]}),e.jsxs("div",{children:["Samples: ",e.jsx("strong",{className:"text-foreground",children:a.n})]})]}),s.length>0?e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"ov-sparkline",role:"img","aria-label":`Cache hit rate trend: ${a.n} samples, average ${g(a.avg)}, latest ${g(a.latest)}`,children:s.map((l,r)=>{const i=Math.max(2,Math.round(l.pct*.6)),o=X(l.pct),c=r===s.length-1;return e.jsx("div",{className:`ov-sparkline-bar ${o}${c?" ov-bar-latest":""}`,style:{height:`${i}px`},title:`${g(l.pct)} at ${new Date(l.ts).toLocaleTimeString()}`},r)})}),e.jsxs("div",{className:"mt-1 text-xs text-muted-foreground",children:[s.length," sample",s.length!==1?"s":""," over"," ",s.length>1?`${Math.round((s[s.length-1].ts-s[0].ts)/1e3)}s`:"latest turn"]})]}):e.jsx("div",{className:"text-sm text-muted-foreground",children:"No cache-hit samples yet"})]})]})};function T(t){return`${(t*100).toFixed(1)}%`}function Z(t){const a=t*100;return a>=80?"ov-bar-green":a>=60?"ov-bar-teal":a>=40?"ov-bar-yellow":a>=20?"ov-bar-orange":"ov-bar-red"}const A={improving:"Improving",stable:"Stable",degrading:"Degrading"},ee=({data:t})=>{const{turns:a,avgRatio:s,trend:l}=t;return e.jsxs(f,{className:"electric-hover",children:[e.jsx(C,{children:e.jsx(S,{children:"Per-Turn Stable Prefix"})}),e.jsxs(N,{children:[e.jsxs("div",{className:"mb-3 flex gap-4 text-sm text-muted-foreground",children:[e.jsxs("div",{children:["Avg:"," ",e.jsx("strong",{className:"text-foreground",children:T(s)})]}),e.jsxs("div",{children:["Trend:"," ",e.jsx("strong",{className:"text-foreground",children:A[l]})]}),e.jsxs("div",{children:["Turns: ",e.jsx("strong",{className:"text-foreground",children:a.length})]})]}),a.length>0?e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"ov-sparkline",role:"img","aria-label":`Per-turn stable-prefix ratio trend: ${a.length} turns, average ${T(s)}, trend ${A[l]}`,children:a.map((r,i)=>{const o=Math.max(2,Math.round(r.ratio*60)),c=Z(r.ratio),p=i===a.length-1;return e.jsx("div",{className:`ov-sparkline-bar ${c}${p?" ov-bar-latest":""}`,style:{height:`${o}px`},title:`Turn ${r.turnIndex}: ${T(r.ratio)} (${r.stablePrefix}/${r.totalMessages} msg) @ ${new Date(r.timestamp).toLocaleTimeString()}`},i)})}),e.jsx("div",{className:"mt-1 text-xs text-muted-foreground",children:"Shared prompt-cache prefix ratio per turn — higher is better."})]}):e.jsx("div",{className:"text-sm text-muted-foreground",children:"No stable-prefix samples yet"})]})]})};function oe(){const[t,a]=h.useState(!1),{data:s,loading:l,error:r}=m(h.useCallback(()=>I(),[]),{pollInterval:5e3}),{data:i,loading:o,error:c}=m(h.useCallback(()=>k(),[]),{pollInterval:15e3}),{data:p,loading:E,error:y}=m(h.useCallback(()=>w({minutes:30}),[]),{pollInterval:15e3}),{data:P,loading:M}=m(h.useCallback(()=>K(50),[]),{pollInterval:15e3}),{data:d,loading:H,error:$}=m(h.useCallback(()=>D(),[]),{pollInterval:5e3});return e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{children:[e.jsx(B,{type:"button",variant:"outline",onClick:()=>a(!t),children:t?"Hide Guidance":"Show Cache-Friendly Prompt Ordering Guidance"}),t&&e.jsxs(f,{className:"mt-3",children:[e.jsx(C,{children:e.jsx(S,{children:"Cache-Friendly Prompt Ordering"})}),e.jsxs(N,{children:[e.jsxs("ul",{className:"list-disc space-y-1 pl-5",children:[e.jsx("li",{children:"Keep system prompts and stable context at the top of your conversation — the provider caches the leading prefix."}),e.jsxs("li",{children:["Tool results and volatile content are automatically moved to the tail by message separation (",e.jsx("code",{children:"MEGACOMPACT_MESSAGE_SEPARATION"}),") so they don't invalidate the cache prefix."]}),e.jsxs("li",{children:["Cache striping (",e.jsx("code",{children:"MEGACOMPACT_CACHE_STRIPING"}),") further orders stable context by a stability score so the most durable chunks lead."]}),e.jsx("li",{children:"Avoid inserting new instructions mid-conversation — prepend them instead."})]}),d&&e.jsxs("div",{className:"mt-2 text-sm",children:[e.jsx("strong",{children:"Status:"})," ",d.config.auto?"Auto-compaction Enabled":"Auto-compaction Disabled"," |"," ","fast-gate ",d.config.fastGatePct,"% / threshold"," ",d.config.thresholdTokens.toLocaleString()," tokens"]})]})]})]}),e.jsx("h2",{className:"font-heading text-lg font-semibold",children:"Provider Prompt Cache"}),l?e.jsx("p",{className:"tab-stub",children:"Loading..."}):r?e.jsxs("p",{className:"tab-stub",children:["Provider cache unavailable: ",r.message]}):s?e.jsx(V,{hitPct:s.cache.avgHitPct,turnCount:s.cache.turnCount,totalCacheRead:s.cache.totalCacheRead,totalCacheWrite:s.cache.totalCacheWrite,totalInput:s.cache.totalInput,cacheReadSaved:s.savings?.cacheReadSaved??null,cacheWriteCost:s.savings?.cacheWriteCost??null,netSaved:s.savings?.netSaved??null,modelLabel:s.savings?.model??null,firstTurnAt:s.cache.firstTurnAt,latestTurnAt:s.cache.latestTurnAt,byModel:s.cache.byModel??[]}):null,e.jsx("h2",{className:"font-heading text-lg font-semibold",children:"Cache Stripe Distribution"}),o?e.jsx("p",{className:"tab-stub",children:"Loading..."}):c?e.jsxs("p",{className:"tab-stub",children:["Cache stripe data unavailable: ",c.message]}):i?e.jsx(Q,{data:i}):null,e.jsx("h2",{className:"font-heading text-lg font-semibold",children:"Cache Hit-Rate Trend"}),E?e.jsx("p",{className:"tab-stub",children:"Loading..."}):y?e.jsxs("p",{className:"tab-stub",children:["Hit-rate trend unavailable: ",y.message]}):p?e.jsx(Y,{perf:p}):null,P&&!M?e.jsxs("div",{children:[e.jsx("h2",{className:"font-heading text-lg font-semibold",children:"Per-Turn Stable Prefix"}),e.jsx(ee,{data:P})]}):null,e.jsx("h2",{className:"font-heading text-lg font-semibold",children:"Mega-Compact Dedup Cache"}),H?e.jsx("p",{className:"tab-stub",children:"Loading..."}):$?e.jsxs("p",{className:"tab-stub",children:["Snapshot unavailable: ",$.message]}):d&&(()=>{const{cacheHits:b,compacts:R,timeSaved:j}=d;return e.jsxs("div",{className:"grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3",children:[e.jsx(W,{cacheHitsSession:b.session,cacheHitsTotal:b.total,tokensSavedSession:b.sessionTokensSaved,tokensSavedTotal:b.totalTokensSaved,compactionsSession:R.session,compactionsTotal:R.total}),e.jsx(F,{compactSessionSec:j.compact.sessionSec,compactTotalSec:j.compact.totalSec,cacheHitSessionSec:j.cacheHit.sessionSec,cacheHitTotalSec:j.cacheHit.totalSec})]})})()]})}export{oe as default};
|
|
2
|
-
//# sourceMappingURL=CacheTab-BS_G9_YV.js.map
|