pi-mega-compact 0.20.39 → 0.20.40
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/dist/config/vector-cortex-ml5d.js +28 -0
- package/dist/config/vector-cortex.js +2 -2
- package/dist/config.js +1 -1
- package/dist/extensions/dashboard-server/api-contracts/cortex-improve.js +14 -0
- package/dist/extensions/dashboard-server/api-contracts/endpoints/registry-ext.js +13 -0
- package/dist/extensions/dashboard-server/route-dispatch.js +5 -1
- package/dist/extensions/dashboard-server/routes-cortex-improve.js +220 -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/extensions/mega-runtime/dashboard-snapshot.js +2 -2
- package/dist/src/config/vector-cortex-ml5d.js +28 -0
- package/dist/src/config/vector-cortex.js +2 -2
- package/dist/src/config.js +1 -1
- package/dist/src/vector-cortex/improve.js +24 -0
- package/dist/vector-cortex/improve.js +24 -0
- package/extensions/dashboard-client/dist/assets/{AreaChart-DjXp8u2Y.js → AreaChart-BT7YPcp7.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{AreaChart-DjXp8u2Y.js.map → AreaChart-BT7YPcp7.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{BarChart-BZbus-dR.js → BarChart-DceGcBUh.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{BarChart-BZbus-dR.js.map → BarChart-DceGcBUh.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{CacheTab-DQ2CjxVW.js → CacheTab-B9lCouRl.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{CacheTab-DQ2CjxVW.js.map → CacheTab-B9lCouRl.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{EventsTab-DUpnOV1p.js → EventsTab-oqJ11jY7.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{EventsTab-DUpnOV1p.js.map → EventsTab-oqJ11jY7.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{HealthTab-Bul_xjcn.js → HealthTab-Dbosf2Ik.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{HealthTab-Bul_xjcn.js.map → HealthTab-Dbosf2Ik.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-DLUjdKd3.js → MaintenanceTab-6TiApCVE.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-DLUjdKd3.js.map → MaintenanceTab-6TiApCVE.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/MemoryMapTab-cBsE4mTf.js +2 -0
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-BFy0hb6F.js.map → MemoryMapTab-cBsE4mTf.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MetricsTab-BpYuUkq3.js → MetricsTab-CX-X9hhy.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MetricsTab-BpYuUkq3.js.map → MetricsTab-CX-X9hhy.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{OverviewTab-z7yuT-uq.js → OverviewTab-CpPYaTJF.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{OverviewTab-z7yuT-uq.js.map → OverviewTab-CpPYaTJF.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{ReposTab-ClORoDy_.js → ReposTab-D_Ot4QbU.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{ReposTab-ClORoDy_.js.map → ReposTab-D_Ot4QbU.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SessionsTab-CUpehIt9.js → SessionsTab-BUzO3iGK.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SessionsTab-CUpehIt9.js.map → SessionsTab-BUzO3iGK.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SetupTab-Cii80Fdz.js → SetupTab-Be4w9v4j.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SetupTab-Cii80Fdz.js.map → SetupTab-Be4w9v4j.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-BV2iCSdV.js → TimeSavedCard-Cx-g6CXH.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-BV2iCSdV.js.map → TimeSavedCard-Cx-g6CXH.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TurnsTab-1T86rHnD.js → TurnsTab-CC_7T7ad.js} +3 -3
- package/extensions/dashboard-client/dist/assets/{TurnsTab-1T86rHnD.js.map → TurnsTab-CC_7T7ad.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{VcStatusBadge-DKPleja8.js → VcStatusBadge-ZTItXSiH.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{VcStatusBadge-DKPleja8.js.map → VcStatusBadge-ZTItXSiH.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-DgAUZ4Pg.js +2 -0
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-DgAUZ4Pg.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/WikiTab-DnKupXTv.js +2 -0
- package/extensions/dashboard-client/dist/assets/{WikiTab-DKTILa1M.js.map → WikiTab-DnKupXTv.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/button-CFt3e0yc.js +2 -0
- package/extensions/dashboard-client/dist/assets/{button-5fSU8BZj.js.map → button-CFt3e0yc.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{card-BFUnpXE_.js → card-C6ZjsHrl.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{card-BFUnpXE_.js.map → card-C6ZjsHrl.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/client-extra-DdEdGTIe.js +2 -0
- package/extensions/dashboard-client/dist/assets/client-extra-DdEdGTIe.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-xCzi6pWn.js → generateCategoricalChart-C9_fu2hc.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-xCzi6pWn.js.map → generateCategoricalChart-C9_fu2hc.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{index-DqjmZ88m.js → index-DY81TY4f.js} +11 -11
- package/extensions/dashboard-client/dist/assets/index-DY81TY4f.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{switch-CeZUPf_e.js → switch-BOqa1d6x.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{switch-CeZUPf_e.js.map → switch-BOqa1d6x.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{toggle-MQQwdkwD.js → toggle-DToFaIEd.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{toggle-MQQwdkwD.js.map → toggle-DToFaIEd.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{useSSE-BetS7QHN.js → useSSE-CZqkhU18.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{useSSE-BetS7QHN.js.map → useSSE-CZqkhU18.js.map} +1 -1
- package/extensions/dashboard-client/dist/index.html +1 -1
- package/extensions/dashboard-client/src/api/client-extra.ts +19 -1
- package/extensions/dashboard-client/src/components/ModelImprovementCard.tsx +141 -0
- package/extensions/dashboard-client/src/tabs/VectorCortexTab.tsx +6 -0
- package/extensions/dashboard-client/src/types/cortex-improve.ts +42 -0
- package/extensions/dashboard-server/api-contracts/cortex-improve.ts +82 -0
- package/extensions/dashboard-server/api-contracts/endpoints/registry-ext.ts +31 -0
- package/extensions/dashboard-server/api-contracts/index.ts +12 -0
- package/extensions/dashboard-server/route-dispatch.ts +4 -0
- package/extensions/dashboard-server/routes-cortex-improve.ts +256 -0
- package/extensions/dashboard-server/routes-rag-settings-vector-cortex.ts +6 -0
- package/extensions/dashboard-server/routes.ts +4 -0
- package/extensions/mega-runtime/dashboard-snapshot.ts +2 -2
- package/package.json +1 -1
- package/src/config/vector-cortex-ml5d.ts +30 -0
- package/src/config/vector-cortex.ts +2 -2
- package/src/config.ts +1 -0
- package/src/vector-cortex/improve.ts +28 -0
- package/extensions/dashboard-client/dist/assets/MemoryMapTab-BFy0hb6F.js +0 -2
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-BRzvd_pU.js +0 -2
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-BRzvd_pU.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/WikiTab-DKTILa1M.js +0 -2
- package/extensions/dashboard-client/dist/assets/button-5fSU8BZj.js +0 -2
- package/extensions/dashboard-client/dist/assets/client-extra-BZbw21wu.js +0 -2
- package/extensions/dashboard-client/dist/assets/client-extra-BZbw21wu.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/index-DqjmZ88m.js.map +0 -1
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dashboard-client/src/types/cortex-improve.ts — ML5-D Improve Cortex client types.
|
|
3
|
+
*
|
|
4
|
+
* Client-side mirrors of the server contract (extensions/dashboard-server/
|
|
5
|
+
* api-contracts/cortex-improve.ts), kept in lockstep so the ModelImprovementCard
|
|
6
|
+
* is fully typed end-to-end. The client bundle does not import the server tree,
|
|
7
|
+
* so these are redeclared here (PREVENT-011: no `any`; every type explicit).
|
|
8
|
+
* Aggregate values only — mode/verdict/digest/reason/progress, never payload
|
|
9
|
+
* bytes or corpus content (EVAL-REDACT-002).
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/** The five-head qualification verdict projected by an improve job. */
|
|
13
|
+
export interface QualificationV1 {
|
|
14
|
+
readonly mode: "A" | "B" | "C";
|
|
15
|
+
readonly assetDigestPrefix: string | null;
|
|
16
|
+
readonly verdict: "qualified" | "demoted";
|
|
17
|
+
readonly reasonCode?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Response body for POST /api/cortex/improve. */
|
|
21
|
+
export interface CortexImproveStart {
|
|
22
|
+
readonly status: "improving";
|
|
23
|
+
readonly jobId: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Response body for GET /api/cortex/improve/status/:jobId. */
|
|
27
|
+
export type CortexImproveStatus =
|
|
28
|
+
| {
|
|
29
|
+
readonly status: "improving";
|
|
30
|
+
readonly progress: number;
|
|
31
|
+
}
|
|
32
|
+
| {
|
|
33
|
+
readonly status: "qualified";
|
|
34
|
+
readonly progress: number;
|
|
35
|
+
readonly verdict: QualificationV1;
|
|
36
|
+
readonly assetDigest: string;
|
|
37
|
+
}
|
|
38
|
+
| {
|
|
39
|
+
readonly status: "demoted_to_B";
|
|
40
|
+
readonly progress: number;
|
|
41
|
+
readonly reason: string;
|
|
42
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* api-contracts/cortex-improve.ts — ML5-D "Improve Cortex" job API types.
|
|
3
|
+
*
|
|
4
|
+
* Types for POST /api/cortex/improve (launch a local ML5-A training job that
|
|
5
|
+
* re-qualifies the five heads against the latest local corpus) and GET
|
|
6
|
+
* /api/cortex/improve/status/:jobId (poll the in-process job state to a
|
|
7
|
+
* terminal qualified / demoted_to_B verdict). Local-only, aggregate surfaces:
|
|
8
|
+
* mode / verdict / digest / reason / progress — never message content or corpus
|
|
9
|
+
* rows (EVAL-REDACT-002).
|
|
10
|
+
*
|
|
11
|
+
* PREVENT-PI-004: type definitions only, no network code.
|
|
12
|
+
* PREVENT-011: no `any` type — all types are explicit.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The five-head qualification verdict projected from the improve job.
|
|
17
|
+
* Aggregate-only: current surrogate mode + asset digest prefix + a reason code
|
|
18
|
+
* when the asset failed to qualify (never weights or corpus content).
|
|
19
|
+
*/
|
|
20
|
+
export interface QualificationV1 {
|
|
21
|
+
/** Surrogate encoder mode the improve job would promote to on success. */
|
|
22
|
+
readonly mode: "A" | "B" | "C";
|
|
23
|
+
/** First 12 hex chars of the produced asset manifest digest, or null. */
|
|
24
|
+
readonly assetDigestPrefix: string | null;
|
|
25
|
+
/** Terminal verdict: qualified when the heads fit within gate, else demoted. */
|
|
26
|
+
readonly verdict: "qualified" | "demoted";
|
|
27
|
+
/** A stable reason code when verdict is "demoted" (e.g. ENC_ASSET_UNREADABLE). */
|
|
28
|
+
readonly reasonCode?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Response body for POST /api/cortex/improve (confirmation-gated). */
|
|
32
|
+
export interface CortexImproveStart {
|
|
33
|
+
/** Always "improving" immediately after the job is spawned. */
|
|
34
|
+
readonly status: "improving";
|
|
35
|
+
/** Opaque job token (sha256 of ts+random, hex-sliced), pollable via status. */
|
|
36
|
+
readonly jobId: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Lifecycle status of a Cortex improve job (in-process, restart-scoped). */
|
|
40
|
+
export type CortexImproveJobStatus =
|
|
41
|
+
| "improving"
|
|
42
|
+
| "qualified"
|
|
43
|
+
| "demoted_to_B";
|
|
44
|
+
|
|
45
|
+
/** Progressing (non-terminal) response for GET /api/cortex/improve/status/:jobId. */
|
|
46
|
+
export interface CortexImproveProgress {
|
|
47
|
+
readonly status: "improving";
|
|
48
|
+
/** 0..1 progress through the local ML5-A training run. */
|
|
49
|
+
readonly progress: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Terminal success: the five heads re-qualified under mode A. */
|
|
53
|
+
export interface CortexImproveQualified {
|
|
54
|
+
readonly status: "qualified";
|
|
55
|
+
readonly progress: number;
|
|
56
|
+
readonly verdict: QualificationV1;
|
|
57
|
+
readonly assetDigest: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Terminal demotion: the re-trained heads failed to qualify — stay mode B. */
|
|
61
|
+
export interface CortexImproveDemoted {
|
|
62
|
+
readonly status: "demoted_to_B";
|
|
63
|
+
readonly progress: number;
|
|
64
|
+
readonly reason: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Response body for GET /api/cortex/improve/status/:jobId. */
|
|
68
|
+
export type CortexImproveStatus =
|
|
69
|
+
| CortexImproveProgress
|
|
70
|
+
| CortexImproveQualified
|
|
71
|
+
| CortexImproveDemoted;
|
|
72
|
+
|
|
73
|
+
/** Error body returned when the improve surface is disabled (flag off). */
|
|
74
|
+
export interface CortexImproveDisabled {
|
|
75
|
+
readonly error: "disabled";
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Request body for POST /api/cortex/improve. `confirm:true` is the server-side hard requirement. */
|
|
79
|
+
export interface CortexImproveStartRequest {
|
|
80
|
+
/** Required explicit confirmation. Absent/false → 400 confirmation_required. */
|
|
81
|
+
readonly confirm: boolean;
|
|
82
|
+
}
|
|
@@ -25,6 +25,11 @@ import type {
|
|
|
25
25
|
SetupCortexActionLogResponse,
|
|
26
26
|
} from "../setup-cortex.js";
|
|
27
27
|
import type { PrefixStabilityResponse } from "../prefix-stability.js";
|
|
28
|
+
import type {
|
|
29
|
+
CortexImproveStartRequest,
|
|
30
|
+
CortexImproveStart,
|
|
31
|
+
CortexImproveStatus,
|
|
32
|
+
} from "../cortex-improve.js";
|
|
28
33
|
|
|
29
34
|
/** Additive endpoint entries spread into the ENDPOINTS registry. */
|
|
30
35
|
export const EXTRA_ENDPOINTS = {
|
|
@@ -123,4 +128,30 @@ export const EXTRA_ENDPOINTS = {
|
|
|
123
128
|
undefined,
|
|
124
129
|
PrefixStabilityResponse
|
|
125
130
|
>,
|
|
131
|
+
|
|
132
|
+
// ─── ML5-D Improve Cortex (dashboard Vector Cortex tab) ───────────
|
|
133
|
+
|
|
134
|
+
/** POST /api/cortex/improve — launch a local ML5-A training job. */
|
|
135
|
+
improveCortex: {
|
|
136
|
+
method: "POST",
|
|
137
|
+
path: "/api/cortex/improve",
|
|
138
|
+
description:
|
|
139
|
+
"Launch a local ML5-A training job that re-qualifies the five heads against the latest local corpus and returns an opaque jobId. Requires confirm:true; flag-off returns 404. Local-only — never fetches anything.",
|
|
140
|
+
} as const satisfies EndpointDef<
|
|
141
|
+
"POST",
|
|
142
|
+
CortexImproveStartRequest,
|
|
143
|
+
CortexImproveStart
|
|
144
|
+
>,
|
|
145
|
+
|
|
146
|
+
/** GET /api/cortex/improve/status/:jobId — poll an improve job. */
|
|
147
|
+
improveCortexStatus: {
|
|
148
|
+
method: "GET",
|
|
149
|
+
path: "/api/cortex/improve/status/:jobId",
|
|
150
|
+
description:
|
|
151
|
+
"Poll an in-process Cortex improve job to terminal qualified / demoted_to_B. Unknown jobId or flag-off returns 404. Read-only, in-memory job state.",
|
|
152
|
+
} as const satisfies EndpointDef<
|
|
153
|
+
"GET",
|
|
154
|
+
undefined,
|
|
155
|
+
CortexImproveStatus
|
|
156
|
+
>,
|
|
126
157
|
} as const;
|
|
@@ -323,3 +323,15 @@ export type {
|
|
|
323
323
|
ModelThresholdDeleteResponse,
|
|
324
324
|
ModelThresholdsError,
|
|
325
325
|
} from "./model-thresholds.js";
|
|
326
|
+
|
|
327
|
+
// ML5-D — dashboard "Improve Cortex" job API
|
|
328
|
+
export type {
|
|
329
|
+
QualificationV1,
|
|
330
|
+
CortexImproveStart,
|
|
331
|
+
CortexImproveStatus,
|
|
332
|
+
CortexImproveProgress,
|
|
333
|
+
CortexImproveQualified,
|
|
334
|
+
CortexImproveDemoted,
|
|
335
|
+
CortexImproveDisabled,
|
|
336
|
+
CortexImproveStartRequest,
|
|
337
|
+
} from "./cortex-improve.js";
|
|
@@ -60,6 +60,8 @@ import {
|
|
|
60
60
|
handleSetupCortexStatus,
|
|
61
61
|
handleSetupCortexAction,
|
|
62
62
|
handleSetupCortexActionLog,
|
|
63
|
+
handleImproveCortex,
|
|
64
|
+
handleImproveCortexStatus,
|
|
63
65
|
} from "./routes.js";
|
|
64
66
|
// VC6C repair lives in its own module (routes-vector-cortex-repair.ts) so the
|
|
65
67
|
// heal route file stays well under the 400-line extension soft limit.
|
|
@@ -154,5 +156,7 @@ export function dispatchRoutes(
|
|
|
154
156
|
if (handleSetupCortexStatus(req, res, ctx)) return true;
|
|
155
157
|
if (handleSetupCortexAction(req, res, ctx)) return true;
|
|
156
158
|
if (handleSetupCortexActionLog(req, res, ctx)) return true;
|
|
159
|
+
if (handleImproveCortex(req, res, ctx)) return true;
|
|
160
|
+
if (handleImproveCortexStatus(req, res, ctx)) return true;
|
|
157
161
|
return false;
|
|
158
162
|
}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dashboard-server/routes-cortex-improve.ts — ML5-D "Improve Cortex" job routes.
|
|
3
|
+
*
|
|
4
|
+
* POST /api/cortex/improve — confirmation-gated local ML5-A training
|
|
5
|
+
* GET /api/cortex/improve/status/:jobId — poll an in-process job to terminal
|
|
6
|
+
*
|
|
7
|
+
* The Improve action launches the committed ML5-A training pipeline
|
|
8
|
+
* (training/vector-cortex/train.py) as a background child_process against the
|
|
9
|
+
* latest local corpus, then re-qualifies the five heads. Job state is kept
|
|
10
|
+
* in-process in a Map<jobId, JobState> on this module; nothing is persisted
|
|
11
|
+
* across restarts (the status endpoint is read-only, in-memory).
|
|
12
|
+
*
|
|
13
|
+
* LOCAL ONLY (PREVENT-PI-004): the job spawns a local python process and reads
|
|
14
|
+
* local files — never a fetch. The `onnxruntime-node` native path is attempted
|
|
15
|
+
* only when MEGACOMPACT_ENCODER_NATIVE=1 (default OFF); otherwise the harness
|
|
16
|
+
* uses the WASM/trigram fallback. The status payload surfaces mode/verdict/
|
|
17
|
+
* digest/reason/progress only — never message or corpus content (EVAL-REDACT-002).
|
|
18
|
+
*
|
|
19
|
+
* Guardrails: PREVENT-011 (no `any`), PREVENT-001 (guarded JSON.parse via
|
|
20
|
+
* readJsonBody), flag-off byte-identical (no card + endpoints 404).
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
24
|
+
import { spawn } from "node:child_process";
|
|
25
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
26
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
27
|
+
import { join, dirname } from "node:path";
|
|
28
|
+
import { fileURLToPath } from "node:url";
|
|
29
|
+
import type { RouteContext } from "./routes-core.js";
|
|
30
|
+
import { sendJson, readJsonBody } from "./routes-vector-cortex-shared.js";
|
|
31
|
+
import { ML5D_ENABLED } from "../../src/config.js";
|
|
32
|
+
import { qualifyDecision } from "../../src/vector-cortex/improve.js";
|
|
33
|
+
import type {
|
|
34
|
+
CortexImproveStart,
|
|
35
|
+
CortexImproveStatus,
|
|
36
|
+
QualificationV1,
|
|
37
|
+
} from "./api-contracts/cortex-improve.js";
|
|
38
|
+
|
|
39
|
+
/** Resolve the committed training entry by walking up to the repo root. */
|
|
40
|
+
function trainingScript(): string | null {
|
|
41
|
+
let dir = dirname(fileURLToPath(import.meta.url));
|
|
42
|
+
const rel = join("training", "vector-cortex", "train.py");
|
|
43
|
+
for (let i = 0; i < 8; i++) {
|
|
44
|
+
// guardrails-allow PREVENT-PI-004: local script read (loopback)
|
|
45
|
+
const candidate = join(dir, rel);
|
|
46
|
+
if (existsSync(candidate)) return candidate;
|
|
47
|
+
const next = dirname(dir);
|
|
48
|
+
if (next === dir) break;
|
|
49
|
+
dir = next;
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** An in-process improve job (restart-scoped, never persisted). */
|
|
55
|
+
interface JobState {
|
|
56
|
+
status: "improving" | "qualified" | "demoted_to_B";
|
|
57
|
+
progress: number;
|
|
58
|
+
verdict?: QualificationV1;
|
|
59
|
+
assetDigest?: string;
|
|
60
|
+
reason?: string;
|
|
61
|
+
updatedAt: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** In-process job registry; nothing survives a server restart. */
|
|
65
|
+
const JOBS = new Map<string, JobState>();
|
|
66
|
+
|
|
67
|
+
/** Opaque job token: sha256(ts+random) hex-sliced. */
|
|
68
|
+
function newJobId(): string {
|
|
69
|
+
return createHash("sha256")
|
|
70
|
+
.update(`${Date.now()}:${randomBytes(16).toString("hex")}`)
|
|
71
|
+
.digest("hex")
|
|
72
|
+
.slice(0, 24);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Spawn the ML5-A training pipeline in the background and drive the job state
|
|
77
|
+
* to a terminal qualified / demoted_to_B verdict. Honest: an empty corpus (the
|
|
78
|
+
* host state) makes train.py no-op and the job ends demoted_to_B.
|
|
79
|
+
*/
|
|
80
|
+
function startJob(jobId: string): void {
|
|
81
|
+
const script = trainingScript();
|
|
82
|
+
const boot = Date.now();
|
|
83
|
+
JOBS.set(jobId, { status: "improving", progress: 0, updatedAt: new Date().toISOString() });
|
|
84
|
+
|
|
85
|
+
if (script === null) {
|
|
86
|
+
settle(jobId, { status: "demoted_to_B", reason: "ENC_TRAIN_PIPELINE_ABSENT", progress: 1 });
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const env = { ...process.env };
|
|
91
|
+
const proc = spawn("python3", [script], {
|
|
92
|
+
env,
|
|
93
|
+
cwd: join(dirname(script), "..", ".."),
|
|
94
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
let output = "";
|
|
98
|
+
const step = () => {
|
|
99
|
+
const pct = Math.min(0.9, 0.1 + ((Date.now() - boot) / 60000) * 0.6);
|
|
100
|
+
const cur = JOBS.get(jobId);
|
|
101
|
+
if (cur && cur.status === "improving" && pct > cur.progress) {
|
|
102
|
+
JOBS.set(jobId, { ...cur, progress: pct, updatedAt: new Date().toISOString() });
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
const timer = setInterval(step, 2000);
|
|
106
|
+
const stop = () => clearInterval(timer);
|
|
107
|
+
|
|
108
|
+
proc.stdout?.on("data", (d: Buffer) => {
|
|
109
|
+
output += d.toString();
|
|
110
|
+
});
|
|
111
|
+
proc.stderr?.on("data", (d: Buffer) => {
|
|
112
|
+
output += d.toString();
|
|
113
|
+
});
|
|
114
|
+
proc.on("error", (err) => {
|
|
115
|
+
stop();
|
|
116
|
+
settle(jobId, {
|
|
117
|
+
status: "demoted_to_B",
|
|
118
|
+
reason: `ENC_TRAIN_SPAWN_FAILED:${err.message}`,
|
|
119
|
+
progress: 1,
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
proc.on("close", (code) => {
|
|
123
|
+
stop();
|
|
124
|
+
// Read the produced trained-heads artifact digest. The report line includes
|
|
125
|
+
// `trainedHeadsPath`; verify the file exists after a successful run.
|
|
126
|
+
const match = /trainedHeadsPath":\s*"([^"]+)"/.exec(output);
|
|
127
|
+
const assetPath = match?.[1];
|
|
128
|
+
let digest: string | null = null;
|
|
129
|
+
if (assetPath) {
|
|
130
|
+
// guardrails-allow PREVENT-PI-004: local artifact read (loopback)
|
|
131
|
+
try {
|
|
132
|
+
digest = createHash("sha256")
|
|
133
|
+
.update(readFileSync(assetPath))
|
|
134
|
+
.digest("hex")
|
|
135
|
+
.slice(0, 12);
|
|
136
|
+
} catch {
|
|
137
|
+
digest = null;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const decision = qualifyDecision(code ?? -1, digest);
|
|
141
|
+
if (decision === "qualified") {
|
|
142
|
+
settle(jobId, {
|
|
143
|
+
status: "qualified",
|
|
144
|
+
progress: 1,
|
|
145
|
+
assetDigest: digest ?? undefined,
|
|
146
|
+
verdict: { mode: "A", assetDigestPrefix: digest ?? null, verdict: "qualified" },
|
|
147
|
+
});
|
|
148
|
+
} else {
|
|
149
|
+
settle(jobId, {
|
|
150
|
+
status: "demoted_to_B",
|
|
151
|
+
reason: assetPath
|
|
152
|
+
? "trained asset did not verify — demoted to mode B"
|
|
153
|
+
: "empty corpus (no groups) — no qualified asset emitted",
|
|
154
|
+
progress: 1,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** Write a terminal job state (idempotent — only advances from improving). */
|
|
161
|
+
function settle(
|
|
162
|
+
jobId: string,
|
|
163
|
+
terminal: { status: "qualified" | "demoted_to_B"; progress: number; verdict?: QualificationV1; assetDigest?: string; reason?: string },
|
|
164
|
+
): void {
|
|
165
|
+
const cur = JOBS.get(jobId);
|
|
166
|
+
if (cur && cur.status !== "improving") return;
|
|
167
|
+
JOBS.set(jobId, { ...terminal, updatedAt: new Date().toISOString() });
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** Flag-off response, byte-identical regardless of request (ML5-D absent). */
|
|
171
|
+
function sendDisabled(res: ServerResponse): void {
|
|
172
|
+
sendJson(res, 404, { error: "disabled" });
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* POST /api/cortex/improve (ML5-D). Returns true when it claims the request.
|
|
177
|
+
* Requires `confirm:true` server-side (mirrors the client window.confirm).
|
|
178
|
+
*/
|
|
179
|
+
export function handleImproveCortex(
|
|
180
|
+
req: IncomingMessage,
|
|
181
|
+
res: ServerResponse,
|
|
182
|
+
_ctx: RouteContext,
|
|
183
|
+
): boolean {
|
|
184
|
+
const url = req.url ?? "";
|
|
185
|
+
if (url !== "/api/cortex/improve") return false;
|
|
186
|
+
if (req.method !== "POST") {
|
|
187
|
+
sendJson(res, 405, { error: "method_not_allowed" });
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
if (!ML5D_ENABLED()) {
|
|
191
|
+
sendDisabled(res);
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
readJsonBody(req, (parsed) => {
|
|
195
|
+
if (!parsed.ok) {
|
|
196
|
+
sendJson(res, 400, { error: "invalid_body" });
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
if (parsed.value.confirm !== true) {
|
|
200
|
+
sendJson(res, 400, { error: "confirmation_required" });
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const jobId = newJobId();
|
|
204
|
+
startJob(jobId);
|
|
205
|
+
const body: CortexImproveStart = { status: "improving", jobId };
|
|
206
|
+
sendJson(res, 200, body);
|
|
207
|
+
});
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* GET /api/cortex/improve/status/:jobId (ML5-D). Returns true when it claims the
|
|
213
|
+
* request. Flag-off or unknown jobId → 404. Read-only in-memory.
|
|
214
|
+
*/
|
|
215
|
+
export function handleImproveCortexStatus(
|
|
216
|
+
req: IncomingMessage,
|
|
217
|
+
res: ServerResponse,
|
|
218
|
+
_ctx: RouteContext,
|
|
219
|
+
): boolean {
|
|
220
|
+
const url = req.url ?? "";
|
|
221
|
+
const match = /^\/api\/cortex\/improve\/status\/([A-Za-z0-9]+)$/.exec(url);
|
|
222
|
+
if (!match) return false;
|
|
223
|
+
if (req.method !== "GET") {
|
|
224
|
+
sendJson(res, 405, { error: "method_not_allowed" });
|
|
225
|
+
return true;
|
|
226
|
+
}
|
|
227
|
+
if (!ML5D_ENABLED()) {
|
|
228
|
+
sendDisabled(res);
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
231
|
+
const job = JOBS.get(match[1]);
|
|
232
|
+
if (!job) {
|
|
233
|
+
sendJson(res, 404, { error: "job_not_found" });
|
|
234
|
+
return true;
|
|
235
|
+
}
|
|
236
|
+
// Narrow job.status into the discriminated CortexImproveStatus variant. The
|
|
237
|
+
// terminal shapes require their payload fields, so construct per-state.
|
|
238
|
+
const body: CortexImproveStatus =
|
|
239
|
+
job.status === "improving"
|
|
240
|
+
? { status: "improving", progress: job.progress }
|
|
241
|
+
: job.status === "qualified"
|
|
242
|
+
? {
|
|
243
|
+
status: "qualified",
|
|
244
|
+
progress: job.progress,
|
|
245
|
+
verdict:
|
|
246
|
+
job.verdict ?? { mode: "A", assetDigestPrefix: null, verdict: "qualified" },
|
|
247
|
+
assetDigest: job.assetDigest ?? "",
|
|
248
|
+
}
|
|
249
|
+
: {
|
|
250
|
+
status: "demoted_to_B",
|
|
251
|
+
progress: job.progress,
|
|
252
|
+
reason: job.reason ?? "UNKNOWN_TERMINAL",
|
|
253
|
+
};
|
|
254
|
+
sendJson(res, 200, body);
|
|
255
|
+
return true;
|
|
256
|
+
}
|
|
@@ -234,5 +234,11 @@ export const VECTOR_CORTEX_SETTINGS: SettingGroup = {
|
|
|
234
234
|
"ML5-C runtime backend selection (WASM vs native): selects the ONNX runtime backend based on the ML5-B bench record and platform support. ON (default) = the runtime-selection dispatch runs and emits vector_cortex_runtime_selected. OFF = no selection runs — encoder serves mode B trigram, byte-identical to ML5-B.",
|
|
235
235
|
true,
|
|
236
236
|
),
|
|
237
|
+
boolDirect(
|
|
238
|
+
"MEGACOMPACT_ML5_D",
|
|
239
|
+
"ML5-D Dashboard Improve Cortex",
|
|
240
|
+
"ML5-D dashboard 'Improve Cortex' surface: the ModelImprovementCard + POST /api/cortex/improve + GET /api/cortex/improve/status/:jobId. ON (default) = the card renders and Improve launches a local ML5-A training job. OFF = both improve endpoints return 404 and VectorCortexTab omits the card, byte-identical to ML5-C.",
|
|
241
|
+
true,
|
|
242
|
+
),
|
|
237
243
|
],
|
|
238
244
|
};
|
|
@@ -159,8 +159,8 @@ export function buildDashboardSnapshot(ctx: SnapshotBuildContext): DashboardSnap
|
|
|
159
159
|
// per-session in rt and there's no cumulative counter yet.
|
|
160
160
|
total: ctx.repo.dedupCollapsed,
|
|
161
161
|
sessionTokensSaved: ctx.rt.cacheHitTokens,
|
|
162
|
-
// Cumulative tokens saved across all sessions in this repo
|
|
163
|
-
//
|
|
162
|
+
// Cumulative tokens saved across all sessions in this repo = the
|
|
163
|
+
// real repo counter (audit Table 1 stub 8 closed — no rolled-up math).
|
|
164
164
|
totalTokensSaved: ctx.repo.tokensSaved,
|
|
165
165
|
},
|
|
166
166
|
compacts: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-mega-compact",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.40",
|
|
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",
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* config/vector-cortex-ml5d.ts — ML5-D dashboard "Improve Cortex" flag.
|
|
3
|
+
*
|
|
4
|
+
* Sibling extract mirroring vector-cortex-ml5a.ts / vector-cortex-ml5b.ts /
|
|
5
|
+
* vector-cortex-ml5c.ts, so vector-cortex.ts stays under its 300-line soft
|
|
6
|
+
* limit (soft-as-hard gate). This is the dashboard "Improve Cortex" surface +
|
|
7
|
+
* promote workflow sprint flag.
|
|
8
|
+
* vector-cortex.ts re-exports the ENUM below and root src/config.ts re-exports
|
|
9
|
+
* it, so no consumer import path changes.
|
|
10
|
+
*
|
|
11
|
+
* ML5-D adds the dashboard ModelImprovementCard + the POST /api/cortex/improve
|
|
12
|
+
* and GET /api/cortex/improve/status/:jobId endpoints. The flag gates that
|
|
13
|
+
* surface only; when OFF the endpoints return 404/disabled and VectorCortexTab
|
|
14
|
+
* renders exactly as before (byte-identical to the ML5-C-era tab — no
|
|
15
|
+
* ModelImprovementCard, no improve job is ever spawned).
|
|
16
|
+
*
|
|
17
|
+
* Pi-agnostic, dependency-free (PREVENT-PI-004 / PREVENT-011).
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { sprintFlag } from "./vector-cortex-flag.js";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* ML5-D — dashboard "Improve Cortex" surface + promote workflow. Default ON.
|
|
24
|
+
* `MEGACOMPACT_ML5_D=0` disables and is byte-identical to the ML5-C survivor:
|
|
25
|
+
* both `/api/cortex/improve*` endpoints return 404 and VectorCortexTab omits the
|
|
26
|
+
* ModelImprovementCard. The flag gates the dashboard surface only; it does not
|
|
27
|
+
* gate the underlying ML5-A training pipeline or the encoder's mode-A/B/C
|
|
28
|
+
* selection (those are governed by ML5-A and the encoder independently).
|
|
29
|
+
*/
|
|
30
|
+
export const ML5D_ENABLED = (): boolean => sprintFlag("MEGACOMPACT_ML5_D");
|
|
@@ -269,8 +269,7 @@ export const VC8A_ENABLED = (): boolean => sprintFlag("MEGACOMPACT_VC8A");
|
|
|
269
269
|
*/
|
|
270
270
|
export const VC8B_ENABLED = (): boolean => sprintFlag("MEGACOMPACT_VC8B");
|
|
271
271
|
|
|
272
|
-
// VC8C (canary selection + Rust parity) extracted to vector-cortex-vc8c.ts;
|
|
273
|
-
// re-exported so existing `./config/vector-cortex.js` imports keep resolving.
|
|
272
|
+
// VC8C (canary selection + Rust parity) extracted to vector-cortex-vc8c.ts; re-exported so existing imports keep resolving.
|
|
274
273
|
export { VC8C_ENABLED } from "./vector-cortex-vc8c.js";
|
|
275
274
|
// Sibling extracts to stay under the 300-line soft limit.
|
|
276
275
|
export { VC9A_ENABLED } from "./vector-cortex-vc9a.js";
|
|
@@ -281,6 +280,7 @@ export { PCC_ENABLED } from "./vector-cortex-pcc.js";
|
|
|
281
280
|
export { ML5A_ENABLED } from "./vector-cortex-ml5a.js";
|
|
282
281
|
export { ML5B_ENABLED } from "./vector-cortex-ml5b.js";
|
|
283
282
|
export { ML5C_ENABLED } from "./vector-cortex-ml5c.js";
|
|
283
|
+
export { ML5D_ENABLED } from "./vector-cortex-ml5d.js";
|
|
284
284
|
|
|
285
285
|
// Breaker constants (TRIAD_RESILIENCE.md §breaker) extracted to vector-cortex-breakers.ts.
|
|
286
286
|
export {
|
package/src/config.ts
CHANGED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vector-cortex/improve.ts — ML5-D "Improve Cortex" pure decision rule.
|
|
3
|
+
*
|
|
4
|
+
* The single pure decision of the improve job harness: given the training
|
|
5
|
+
* process exit code and whether a readable produced-asset digest exists,
|
|
6
|
+
* decide whether the five heads qualify (promote) or are demoted to mode B.
|
|
7
|
+
*
|
|
8
|
+
* Lives under src/ so both the dashboard-server route (routes-cortex-improve.ts)
|
|
9
|
+
* and the ML5-D acceptance aggregator (dist/vector-cortex/ml5d-acceptance.test.js)
|
|
10
|
+
* can import it — the mirrored dist/vector-cortex/ subtree carries this file via
|
|
11
|
+
* the publish-acceptance copyTree, so the acceptance suite needs no real
|
|
12
|
+
* training run.
|
|
13
|
+
*
|
|
14
|
+
* Pure, total over its inputs, zero I/O (PREVENT-PI-004 / PREVENT-011).
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Terminal decision for an improve job: qualified only when the training
|
|
19
|
+
* process exited 0 AND a readable produced-asset digest exists; otherwise the
|
|
20
|
+
* job is demoted to mode B (honest degradation — an empty corpus or a failed
|
|
21
|
+
* train never fabricates a promotion).
|
|
22
|
+
*/
|
|
23
|
+
export function qualifyDecision(
|
|
24
|
+
exitCode: number,
|
|
25
|
+
assetDigest: string | null,
|
|
26
|
+
): "qualified" | "demoted_to_B" {
|
|
27
|
+
return exitCode === 0 && assetDigest !== null ? "qualified" : "demoted_to_B";
|
|
28
|
+
}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{j as e,r as u,a1 as V,a2 as z}from"./index-DqjmZ88m.js";import{T as P}from"./toggle-MQQwdkwD.js";const S={checkpoint:"#6366f1",turn:"#58a6ff","turn-content":"#22c55e",memory:"#f59e0b"},U={checkpoint:"Checkpoint",turn:"Turn","turn-content":"Turn Content",memory:"Memory"};function Y(t,s){return`M 0,-${s} L ${t},0 L 0,${s} L -${t},0 Z`}function Q(t){return!t||t==="active"?1:.5}function X(t,s,l,h,n,p,c){const x=p?S[h]??"#6366f1":"#d1d5db",i=n?"#ef4444":"none",m=Q(c);switch(h){case"checkpoint":return e.jsx("circle",{cx:t,cy:s,r:n?l+3:l,fill:x,opacity:m,stroke:i,strokeWidth:n?2:0});case"turn":return e.jsx("circle",{cx:t,cy:s,r:n?l+3:l,fill:"none",stroke:x,strokeWidth:2.5,opacity:m});case"turn-content":return e.jsxs("g",{children:[e.jsx("circle",{cx:t,cy:s,r:n?l+3:l,fill:"none",stroke:x,strokeWidth:2.5,opacity:m}),e.jsx("circle",{cx:t,cy:s,r:Math.max(3,l*.3),fill:x,opacity:m})]});case"memory":const d=l*.85,g=l*.85;return e.jsx("path",{d:Y(d,g),transform:`translate(${t}, ${s})`,fill:x,opacity:m,stroke:i,strokeWidth:n?2:0})}}const Z=5e3,O=.005,D=.01,_=.9,J=.1,L=50;function K(t){const s=t.nodes.map((n,p)=>{const c=2*Math.PI*p/Math.max(t.nodes.length,1),x=200;return{...n,pos:{x:Math.cos(c)*x+300,y:Math.sin(c)*x+200},vx:0,vy:0,pinned:!1}}),l=new Map;s.forEach((n,p)=>l.set(n.id,p));const h=t.edges.map(n=>{const p=l.get(n.source),c=l.get(n.target);return p===void 0||c===void 0||p===c?null:{source:p,target:c,weight:n.weight,type:n.type}}).filter(n=>n!==null);return{nodes:s,edges:h}}function ee(t){const{nodes:s,edges:l}=t,h=s.length;if(h!==0)for(let n=0;n<h;n++){if(s[n].pinned)continue;let p=0,c=0;for(let i=0;i<h;i++){if(n===i)continue;const m=s[n].pos.x-s[i].pos.x,d=s[n].pos.y-s[i].pos.y,g=m*m+d*d||1,v=Z/g,y=Math.sqrt(g);p+=m/y*v,c+=d/y*v}for(const i of l){let m;if(i.source===n)m=i.target;else if(i.target===n)m=i.source;else continue;const d=s[m].pos.x-s[n].pos.x,g=s[m].pos.y-s[n].pos.y;p+=d*O*i.weight,c+=g*O*i.weight}p-=s[n].pos.x*D,c-=s[n].pos.y*D,s[n].vx=(s[n].vx+p)*_,s[n].vy=(s[n].vy+c)*_;const x=Math.sqrt(s[n].vx*s[n].vx+s[n].vy*s[n].vy);x>L&&(s[n].vx=s[n].vx/x*L,s[n].vy=s[n].vy/x*L),x>J&&(s[n].pos.x+=s[n].vx,s[n].pos.y+=s[n].vy)}}const te=300,re=.3,k=900,w=600,f=40;function M(t){switch(t){case"temporal":return"#6366f1";case"semantic":return"#22c55e";case"raptor_parent":return"#f59e0b"}}const N=({color:t,shape:s,label:l})=>{const h={display:"inline-block",width:"10px",height:"10px",verticalAlign:"middle",marginRight:"3px",borderRadius:s.startsWith("hollow")||s==="filled-circle"?"50%":void 0};let n;return s==="line"?e.jsx("span",{style:{color:t,marginRight:"6px"},children:l}):(s==="filled-circle"?n=e.jsx("span",{style:{...h,backgroundColor:t}}):s==="hollow-circle"?n=e.jsx("span",{style:{...h,border:`2px solid ${t}`,backgroundColor:"transparent"}}):s==="hollow-ring"?n=e.jsx("span",{style:{...h,border:`2px solid ${t}`,backgroundColor:"transparent",position:"relative"},children:e.jsx("span",{style:{display:"block",width:"4px",height:"4px",borderRadius:"50%",backgroundColor:t,margin:"2px auto"}})}):n=e.jsx("span",{style:{...h,clipPath:"polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)",backgroundColor:t}}),e.jsxs(e.Fragment,{children:[e.jsxs("span",{className:"memory-map-legend-item",children:[n,l]})," "]}))},se=()=>{const[t,s]=u.useState(null),[l,h]=u.useState(!0),[n,p]=u.useState(null),[c,x]=u.useState(null),[i,m]=u.useState(""),[d]=u.useState(""),[g,v]=u.useState(0),y=u.useRef(null),T=u.useRef(0);u.useEffect(()=>{let r=!1;const o=new URLSearchParams;return d&&o.set("sessionId",d),o.set("threshold","0.7"),o.set("maxEdgesPerNode","4"),h(!0),p(null),fetch(`/api/memory-map?${o.toString()}`).then(a=>{if(!a.ok)throw new Error(`HTTP ${a.status}`);return a.json()}).then(a=>{r||(s(a),y.current=K(a),v(1),h(!1))}).catch(a=>{r||(p(a instanceof Error?a.message:"Unknown error"),h(!1))}),()=>{r=!0,cancelAnimationFrame(T.current)}},[d]),u.useEffect(()=>{if(!y.current||g===0)return;const r=y.current;let o=0;const a=()=>{o>=te||(ee(r),o++,v(o),T.current=requestAnimationFrame(a))};return T.current=requestAnimationFrame(a),()=>cancelAnimationFrame(T.current)},[g]);const F=u.useCallback((r,o)=>{const a=y.current;a&&(a.nodes[o].pinned=!a.nodes[o].pinned,a.nodes[o].pinned||(a.nodes[o].vx=0,a.nodes[o].vy=0),x(b=>b?.id===r.id?null:r),v(b=>b+1))},[]),A=u.useMemo(()=>{const r=y.current;if(!r||!i)return null;const o=i.toLowerCase();return new Set(r.nodes.map((a,b)=>a.summaryTruncated.toLowerCase().includes(o)||a.label.toLowerCase().includes(o)?b:-1).filter(a=>a>=0))},[i]),C=u.useMemo(()=>{const r=t?.validation;return r?r.gatesPassed<r.gatesRun?{level:"red",label:"Gate failure"}:r.warnings.length>0?{level:"yellow",label:`${r.warnings.length} warning(s)`}:{level:"green",label:"Healthy"}:{level:"yellow",label:"No validation"}},[t?.validation]),W={green:"#22c55e",yellow:"#eab308",red:"#ef4444"},H=u.useMemo(()=>{const r=t?.validation;if(!r)return`${t?.metadata.totalNodes??0} nodes`;const o=[];return r.sources.checkpoint>0&&o.push(`${r.sources.checkpoint} checkpoints`),r.sources.turn>0&&o.push(`${r.sources.turn} turns`),r.sources.turnContent>0&&o.push(`${r.sources.turnContent} turn-content`),r.sources.memory>0&&o.push(`${r.sources.memory} memories`),o.length===0&&o.push(`${t?.metadata.totalNodes??0} nodes`),o.join(" · ")},[t?.validation,t?.metadata.totalNodes]),I=u.useMemo(()=>{const r=t?.validation;if(!r)return"";const o=[];return o.push(r.sources.checkpoint>0?"✓ checkpoints":"✗ checkpoints"),o.push(r.sources.turn>0?"✓ turns":"✗ turns"),o.push(r.sources.turnContent>0?"✓ turn-content":"✗ turn-content"),o.push(r.sources.memory>0?"✓ memories":"✗ memories"),o.join(" | ")},[t?.validation]),B=u.useMemo(()=>{const r=t?.validation;return r?r.sources.checkpoint===0&&r.sources.turn===0&&r.sources.turnContent===0&&r.sources.memory===0:t?.metadata.totalNodes===0},[t?.validation,t?.metadata.totalNodes]);if(l)return e.jsx("div",{className:"rounded-lg border border-border bg-bg-card p-6 text-center text-sm text-muted-foreground",children:"Loading memory graph..."});if(n)return e.jsxs("div",{className:"rounded-lg border border-border bg-bg-card p-6 text-center text-sm",children:[e.jsxs("p",{className:"text-red-400",children:["Failed to load memory map: ",n]}),e.jsx("button",{className:"mt-3 rounded-md border border-border px-3 py-1.5 text-sm transition-colors hover:bg-bg-elevated hover:text-foreground",onClick:()=>v(r=>r+1),children:"Retry"})]});if(!t||!y.current||B)return e.jsx("div",{className:"rounded-lg border border-border bg-bg-card p-6 text-sm text-muted-foreground",children:e.jsx("p",{children:"Memories appear after your first compaction. The graph shows checkpoints (compaction summaries) linked by semantic similarity and time. Run a longer session or lower the compaction tier to see it sooner."})});const j=y.current;return e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsx("input",{type:"text",placeholder:"Search memories...",value:i,onInput:r=>m(r.target.value),className:"w-56 rounded-md border border-border bg-bg-elevated/50 px-3 py-2 text-sm outline-none transition-colors focus:border-primary"}),e.jsxs("span",{className:"text-xs text-muted-foreground",children:[e.jsx("span",{children:H})," · ",e.jsxs("span",{children:[t.edges.length," edges"]})]}),e.jsx("span",{className:"ml-auto rounded-full px-2 py-1 text-[11px] font-semibold text-white",style:{backgroundColor:W[C.level]??"#6b7280"},title:`Validation: ${C.label}`,children:C.level==="green"?"Healthy":C.level==="yellow"?"Warnings":"Critical"})]}),I?e.jsx("div",{className:"text-[11px] text-muted-foreground",children:I}):null,e.jsxs("div",{className:"flex flex-wrap items-center gap-x-4 gap-y-1 rounded-lg border border-border/60 bg-bg-card px-3 py-2 text-xs",children:[e.jsx("span",{className:"font-semibold text-muted-foreground",children:"Nodes:"}),e.jsx(N,{type:"node",color:S.checkpoint,shape:"filled-circle",label:"Checkpoint"}),e.jsx(N,{type:"node",color:S.turn,shape:"hollow-circle",label:"Turn"}),e.jsx(N,{type:"node",color:S["turn-content"],shape:"hollow-ring",label:"Turn Content"}),e.jsx(N,{type:"node",color:S.memory,shape:"diamond",label:"Memory"}),e.jsx("span",{className:"font-semibold text-muted-foreground",children:"Edges:"}),e.jsx(N,{type:"edge",color:M("semantic"),shape:"line",label:"Semantic"}),e.jsx(N,{type:"edge",color:M("temporal"),shape:"line",label:"Temporal"}),e.jsx(N,{type:"edge",color:M("raptor_parent"),shape:"line",label:"Raptor"})]}),e.jsxs("svg",{width:k,height:w,viewBox:`0 0 ${k} ${w}`,className:"memory-map-svg",children:[j.edges.map((r,o)=>{const a=j.nodes[r.source],b=j.nodes[r.target],R=M(r.type),E=Math.max(1,r.weight*2.5);return e.jsx("line",{x1:f+a.pos.x/(j.nodes.length||1)*(k-2*f),y1:f+a.pos.y/(j.nodes.length||1)*(w-2*f),x2:f+b.pos.x/(j.nodes.length||1)*(k-2*f),y2:f+b.pos.y/(j.nodes.length||1)*(w-2*f),stroke:R,strokeWidth:E,opacity:re},`edge-${o}`)}),j.nodes.map((r,o)=>{const a=f+r.pos.x/(j.nodes.length||1)*(k-2*f),b=f+r.pos.y/(j.nodes.length||1)*(w-2*f),R=Math.min(20,8+r.tokenEstimate/500),E=A?A.has(o):!0,G=c?.id===r.id,q=r.label.length>20?r.label.slice(0,18)+"...":r.label;return e.jsxs("g",{className:"memory-map-node-group",onClick:()=>F(r,o),style:{cursor:"pointer"},children:[X(a,b,R,r.nodeType,G,E,r.dedupStatus),e.jsx("text",{x:a,y:b+R+12,textAnchor:"middle",fontSize:"9px",fill:"#374151",className:"memory-map-label",children:q})]},`node-${o}`)})]}),c?e.jsxs("div",{className:"rounded-lg border border-border/60 bg-bg-card p-4 text-sm",children:[e.jsxs("h3",{className:"font-heading text-base font-semibold",children:[e.jsx("span",{className:"mr-1.5 text-xs font-normal text-muted-foreground",children:U[c.nodeType]}),c.label]}),e.jsx("p",{className:"mt-1",children:c.summaryTruncated}),c.topicSummary?e.jsxs("p",{className:"mt-1",children:["Topic: ",c.topicSummary]}):null,e.jsxs("p",{className:"mt-1",children:["Tokens: ",c.tokenEstimate," | Decisions: ",c.decisionCount]}),e.jsxs("p",{children:["Session: ",c.sessionId]}),e.jsxs("p",{children:["Raptor Level: ",c.raptorLevel]}),e.jsx("p",{className:"mt-1 text-muted-foreground",children:c.textSnippet})]}):null]})};function ne(t){return t===0?"#d4a017":t===1?"#3b82f6":"#14b8a6"}function $(t){return t?new Date(t).toLocaleString():"—"}function oe({node:t}){const s=ne(t.level),l=t.children.length>0?`${t.children.length} child${t.children.length===1?"":"ren"}`:"leaf";return e.jsxs("div",{style:{background:"#14142b",border:`1px solid ${s}`,borderRadius:"8px",padding:"0.75rem 1rem",marginBottom:"0.6rem",marginLeft:t.level*24,maxWidth:"90%"},children:[e.jsxs("div",{style:{display:"flex",gap:"0.75rem",alignItems:"center",marginBottom:"0.35rem"},children:[e.jsxs("span",{style:{display:"inline-block",background:s,color:"#fff",borderRadius:"10px",padding:"1px 8px",fontSize:"11px",fontWeight:600},children:["L",t.level]}),e.jsxs("span",{style:{fontSize:"12px",color:"#6b7280"},children:[l," · ",t.tokenEstimate," tok · ",t.qualityMarker]}),e.jsx("span",{style:{fontSize:"12px",color:"#6b7280",marginLeft:"auto"},children:$(t.builtAt)})]}),e.jsx("div",{style:{fontSize:"0.92rem",color:"#e5e7eb"},children:t.summary})]})}function le(){const[t,s]=u.useState(null),[l,h]=u.useState(null),[n,p]=u.useState(!0),[c,x]=u.useState(null);if(u.useEffect(()=>{let d=!1;return p(!0),x(null),Promise.all([V(),z()]).then(([g,v])=>{d||(s(g),h(v),p(!1))}).catch(g=>{d||(x(g instanceof Error?g.message:"Unknown error"),p(!1))}),()=>{d=!0}},[]),n)return e.jsx("div",{className:"rounded-lg border border-border bg-bg-card p-6 text-center text-sm text-muted-foreground",children:"Loading RAPTOR tree..."});if(c)return e.jsx("div",{className:"rounded-lg border border-dashed border-border bg-bg-card p-8 text-center text-sm",children:e.jsxs("p",{className:"text-red-400",children:["Failed to load RAPTOR tree: ",c]})});if(!t||t.empty||t.nodes.length===0)return e.jsx("div",{className:"rounded-lg border border-dashed border-border bg-bg-card p-8 text-center text-sm text-muted-foreground",children:e.jsx("p",{children:"No RAPTOR tree built yet — run a compaction (the tree builds during compaction)."})});const i=l&&!l.empty?l.builds[0]:null,m=i?.coherenceScore!=null?Math.round(i.coherenceScore*100):null;return e.jsxs("div",{className:"w-full p-4",children:[e.jsxs("div",{className:"mb-4 flex items-center gap-6 text-sm text-muted-foreground",children:[e.jsxs("span",{children:[e.jsx("strong",{children:t.nodes.length})," nodes"]}),e.jsxs("span",{children:[e.jsx("strong",{children:t.levels+1})," levels"]}),e.jsxs("span",{children:["Built ",$(t.builtAt??0)]}),i&&e.jsxs(e.Fragment,{children:[e.jsxs("span",{children:["Coherence:"," ",e.jsx("strong",{style:{color:m!=null&&m>=70?"#22c55e":"#f59e0b"},children:m!=null?`${m}%`:"—"})]}),e.jsxs("span",{children:["Leaves: ",e.jsx("strong",{children:i.leafCount})]}),e.jsxs("span",{children:["Depth: ",e.jsx("strong",{children:i.depth})]}),i.timedOut&&e.jsx("span",{style:{color:"#ef4444"},children:"budget timeout"})]})]}),l&&!l.empty&&l.builds.length>1&&e.jsxs("details",{className:"mb-4",children:[e.jsxs("summary",{className:"cursor-pointer text-xs text-muted-foreground",children:["Build history (",l.builds.length," builds)"]}),e.jsx("div",{className:"mt-2 space-y-1",children:l.builds.slice(0,10).map(d=>e.jsxs("div",{className:"flex items-center gap-4 text-xs text-muted-foreground",children:[e.jsx("span",{children:$(d.completedAt)}),e.jsxs("span",{children:[d.nodeCount," nodes"]}),e.jsxs("span",{children:[d.leafCount," leaves"]}),e.jsxs("span",{children:["depth ",d.depth]}),e.jsxs("span",{children:["coherence"," ",d.coherenceScore!=null?`${Math.round(d.coherenceScore*100)}%`:"—"]}),d.timedOut&&e.jsx("span",{style:{color:"#ef4444"},children:"timeout"})]},d.buildId))})]}),t.nodes.map(d=>e.jsx(oe,{node:d},d.id))]})}const ie=()=>{const[t,s]=u.useState("map");return e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("nav",{className:"flex gap-2 border-b border-border pb-2 pt-2","aria-label":"Memory map sections",children:[e.jsx(P,{pressed:t==="map",onClick:()=>s("map"),"aria-label":"Memory Map view",children:"Memory Map"}),e.jsx(P,{pressed:t==="raptor",onClick:()=>s("raptor"),"aria-label":"RAPTOR Tree view",children:"RAPTOR Tree"})]}),t==="map"&&e.jsx(se,{}),t==="raptor"&&e.jsx(le,{})]})};export{ie as default};
|
|
2
|
-
//# sourceMappingURL=MemoryMapTab-BFy0hb6F.js.map
|