pi-mega-compact 0.11.5 → 0.11.6
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/extensions/dashboard-server/api-contracts/cache-stripes.js +8 -0
- package/dist/extensions/dashboard-server/api-contracts/endpoints.js +13 -0
- package/dist/extensions/dashboard-server/api-contracts/memory-map.js +1 -0
- package/dist/extensions/dashboard-server/routes-cache.js +28 -0
- package/dist/extensions/dashboard-server/routes-game.js +3 -0
- package/dist/extensions/dashboard-server/routes-memory-map.js +50 -0
- package/dist/extensions/dashboard-server/routes-setup.js +105 -0
- package/dist/extensions/dashboard-server/routes.js +3 -1
- package/dist/extensions/dashboard-server/server.js +7 -1
- package/dist/extensions/mega-compact.js +5 -0
- package/dist/extensions/mega-config.js +5 -0
- package/dist/extensions/mega-events/context-handler.js +10 -2
- package/dist/extensions/mega-events/perf-handler.js +83 -1
- package/dist/extensions/mega-events/separated-prompt.js +248 -0
- package/dist/extensions/mega-runtime/env-loader.js +56 -0
- package/dist/extensions/mega-runtime/reset-runtime.js +1 -0
- package/dist/extensions/mega-runtime/runtime-snapshot.js +1 -0
- package/dist/extensions/mega-runtime/runtime.js +1 -0
- package/dist/extensions/mega-runtime/snapshot.js +1 -0
- package/dist/extensions/mega-runtime/widget.js +5 -0
- package/dist/src/cache-stripe-impl.js +288 -0
- package/dist/src/cache-stripe.js +11 -0
- package/dist/src/config/stopwords.js +24 -0
- package/dist/src/config.js +17 -0
- package/dist/src/memoryGraph.js +299 -0
- package/dist/src/monitoring.js +13 -0
- package/dist/src/queryExpansion.js +163 -0
- package/dist/src/queryReformulation/cache.js +123 -0
- package/dist/src/queryReformulation/rrf.js +29 -0
- package/dist/src/queryReformulation/tfidf.js +61 -0
- package/dist/src/queryReformulation/vagueness.js +33 -0
- package/dist/src/queryReformulation.js +225 -0
- package/dist/src/recallMetrics.js +258 -0
- package/dist/src/store/sqlite/cache-stripes.js +133 -0
- package/dist/src/store/sqlite/fts5-search.js +68 -0
- package/dist/src/store/sqlite/perf-samples.js +1 -0
- package/dist/src/store/sqlite/schema.js +60 -1
- package/dist/src/store/sqlite.js +1 -0
- package/dist/src/store/vectorIndex.js +29 -5
- package/dist/src/tiered-router/types.js +18 -0
- package/dist/src/tieredRouter.js +421 -0
- package/dist/src/vectorStore.js +8 -6
- package/extensions/dashboard-client/dist/assets/{AchievementTiles-BoL7qBOJ.js → AchievementTiles-DR9cLGDL.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{AchievementTiles-BoL7qBOJ.js.map → AchievementTiles-DR9cLGDL.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{AchievementsTab-BFDE3HYc.js → AchievementsTab-svNUgJ1e.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{AchievementsTab-BFDE3HYc.js.map → AchievementsTab-svNUgJ1e.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/CacheTab-ASwhOMjR.js +2 -0
- package/extensions/dashboard-client/dist/assets/CacheTab-ASwhOMjR.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{ConfigTab-DDFE-ckA.js → ConfigTab-CmmWheuW.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{ConfigTab-DDFE-ckA.js.map → ConfigTab-CmmWheuW.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{EventsTab-B6UxZ7PM.js → EventsTab-CFE7jLsa.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{EventsTab-B6UxZ7PM.js.map → EventsTab-CFE7jLsa.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/GameTab-CJAX_th_.js +2 -0
- package/extensions/dashboard-client/dist/assets/{GameTab-DehUX-KE.js.map → GameTab-CJAX_th_.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-0GWRt4wn.js → MaintenanceTab-P4SUsvMf.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-0GWRt4wn.js.map → MaintenanceTab-P4SUsvMf.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/MemoryMapTab-BBiH76eF.js +2 -0
- package/extensions/dashboard-client/dist/assets/MemoryMapTab-BBiH76eF.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{MetricsTab-C3rwMVsN.js → MetricsTab-CHQscixy.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MetricsTab-C3rwMVsN.js.map → MetricsTab-CHQscixy.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{OverviewTab-39O9_x5j.js → OverviewTab-DBs4DJdd.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{OverviewTab-39O9_x5j.js.map → OverviewTab-DBs4DJdd.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{ReposTab-Cfj6Q5sH.js → ReposTab-DeFz76L5.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{ReposTab-Cfj6Q5sH.js.map → ReposTab-DeFz76L5.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SessionsTab-DXDTCi3r.js → SessionsTab-BWNsj1OB.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SessionsTab-DXDTCi3r.js.map → SessionsTab-BWNsj1OB.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/SetupTab-uS6A0xmw.js +2 -0
- package/extensions/dashboard-client/dist/assets/SetupTab-uS6A0xmw.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-Cw1dJ4e9.js → TimeSavedCard-CiqCOQuL.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-Cw1dJ4e9.js.map → TimeSavedCard-CiqCOQuL.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TopicsTab-BAw972BV.js → TopicsTab-BWWQxltv.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TopicsTab-BAw972BV.js.map → TopicsTab-BWWQxltv.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TurnsTab-Cf5mGIdl.js → TurnsTab-CVz4f4-o.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TurnsTab-Cf5mGIdl.js.map → TurnsTab-CVz4f4-o.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/index-CUNn22iV.css +1 -0
- package/extensions/dashboard-client/dist/assets/{index-4gQ7auad.js → index-DrktNOoT.js} +11 -11
- package/extensions/dashboard-client/dist/assets/index-DrktNOoT.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{useSSE-DNgMuyP6.js → useSSE-Bf5LOLSi.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{useSSE-DNgMuyP6.js.map → useSSE-Bf5LOLSi.js.map} +1 -1
- package/extensions/dashboard-client/dist/index.html +2 -2
- package/extensions/dashboard-client/src/App.tsx +24 -8
- package/extensions/dashboard-client/src/api/client.ts +15 -0
- package/extensions/dashboard-client/src/components/CacheHitRateTrendCard.tsx +100 -0
- package/extensions/dashboard-client/src/components/StripeDistributionCard.tsx +110 -0
- package/extensions/dashboard-client/src/components/TabBar.tsx +49 -4
- package/extensions/dashboard-client/src/main.tsx +1 -0
- package/extensions/dashboard-client/src/styles/base.css +30 -0
- package/extensions/dashboard-client/src/styles/cache.css +167 -0
- package/extensions/dashboard-client/src/tabs/CacheTab.tsx +75 -13
- package/extensions/dashboard-client/src/tabs/MemoryMapTab.tsx +440 -0
- package/extensions/dashboard-client/src/tabs/SetupTab.tsx +65 -2
- package/extensions/dashboard-server/api-contracts/cache-stripes.ts +49 -0
- package/extensions/dashboard-server/api-contracts/endpoints.ts +31 -1
- package/extensions/dashboard-server/api-contracts/index.ts +16 -1
- package/extensions/dashboard-server/api-contracts/memory-map.ts +50 -0
- package/extensions/dashboard-server/api-contracts/setup.ts +22 -0
- package/extensions/dashboard-server/routes-cache.ts +36 -1
- package/extensions/dashboard-server/routes-game.ts +3 -0
- package/extensions/dashboard-server/routes-memory-map.ts +105 -0
- package/extensions/dashboard-server/routes-setup.ts +112 -0
- package/extensions/dashboard-server/routes.ts +3 -1
- package/extensions/dashboard-server/server.ts +6 -0
- package/extensions/mega-compact.ts +5 -0
- package/extensions/mega-config.ts +17 -0
- package/extensions/mega-events/context-handler.ts +10 -2
- package/extensions/mega-events/perf-handler.ts +111 -1
- package/extensions/mega-events/separated-prompt.ts +329 -0
- package/extensions/mega-runtime/env-loader.ts +55 -0
- package/extensions/mega-runtime/helpers.ts +2 -0
- package/extensions/mega-runtime/reset-runtime.ts +1 -0
- package/extensions/mega-runtime/runtime-snapshot.ts +1 -0
- package/extensions/mega-runtime/runtime.ts +1 -0
- package/extensions/mega-runtime/snapshot.ts +6 -0
- package/extensions/mega-runtime/widget-types.ts +3 -0
- package/extensions/mega-runtime/widget.ts +5 -0
- package/package.json +1 -1
- package/src/cache-stripe-impl.ts +385 -0
- package/src/cache-stripe.ts +18 -0
- package/src/config/stopwords.ts +25 -0
- package/src/config.ts +26 -0
- package/src/memoryGraph.ts +438 -0
- package/src/monitoring.ts +35 -0
- package/src/queryExpansion.ts +206 -0
- package/src/queryReformulation/cache.ts +169 -0
- package/src/queryReformulation/rrf.ts +51 -0
- package/src/queryReformulation/tfidf.ts +79 -0
- package/src/queryReformulation/vagueness.ts +38 -0
- package/src/queryReformulation.ts +355 -0
- package/src/recallMetrics.ts +388 -0
- package/src/store/sqlite/cache-stripes.ts +196 -0
- package/src/store/sqlite/fts5-search.ts +90 -0
- package/src/store/sqlite/perf-samples.ts +3 -1
- package/src/store/sqlite/schema.ts +60 -1
- package/src/store/sqlite.ts +1 -0
- package/src/store/vectorIndex.ts +38 -7
- package/src/tiered-router/types.ts +64 -0
- package/src/tieredRouter.ts +489 -0
- package/src/vectorStore.ts +9 -5
- package/extensions/dashboard-client/dist/assets/CacheTab-eKVc-NV1.js +0 -2
- package/extensions/dashboard-client/dist/assets/CacheTab-eKVc-NV1.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/GameTab-DehUX-KE.js +0 -2
- package/extensions/dashboard-client/dist/assets/SetupTab-mMlfunJa.js +0 -2
- package/extensions/dashboard-client/dist/assets/SetupTab-mMlfunJa.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/index-4gQ7auad.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/index-BEdKlpAB.css +0 -1
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* api-contracts/cache-stripes.ts — Cache stripe API contract (A3, PLAN_V2 Phase 4).
|
|
3
|
+
*
|
|
4
|
+
* Response shape for GET /api/cache-stripes: per-stripe distribution counts,
|
|
5
|
+
* average stability, and a top-level health score. Loopback-only data;
|
|
6
|
+
* zero network (PREVENT-PI-004).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** A single stripe bucket with aggregate metadata. */
|
|
10
|
+
export interface StripeBucket {
|
|
11
|
+
/** Stripe index 0–4 (0=permanent, 1=epoch, 2=topic, 3=thread, 4=volatile). */
|
|
12
|
+
readonly stripe: number;
|
|
13
|
+
/** Human-readable label for this stripe. */
|
|
14
|
+
readonly label: string;
|
|
15
|
+
/** Number of chunks assigned to this stripe. */
|
|
16
|
+
readonly count: number;
|
|
17
|
+
/** Average stability score (0.0–1.0) within this stripe. */
|
|
18
|
+
readonly avgStability: number;
|
|
19
|
+
/** Minimum stability in this stripe. */
|
|
20
|
+
readonly minStability: number;
|
|
21
|
+
/** Maximum stability in this stripe. */
|
|
22
|
+
readonly maxStability: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Overall cache health assessment. */
|
|
26
|
+
export interface CacheHealthScore {
|
|
27
|
+
/** Composite health score 0.0–1.0 (1.0 = perfect). */
|
|
28
|
+
readonly score: number;
|
|
29
|
+
/** Human-readable label: "good" | "fair" | "degraded" | "poor". */
|
|
30
|
+
readonly label: string;
|
|
31
|
+
/** Dominant stability tier fraction. */
|
|
32
|
+
readonly dominantTier: number;
|
|
33
|
+
/** Stripe churn rate (0.0–1.0) — fraction of assignments changed since last epoch. */
|
|
34
|
+
readonly churnRate: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Response body for GET /api/cache-stripes. */
|
|
38
|
+
export interface CacheStripesResponse {
|
|
39
|
+
/** Per-stripe bucket arrays (always 5 entries, stripes 0–4). */
|
|
40
|
+
readonly buckets: StripeBucket[];
|
|
41
|
+
/** Overall health assessment. */
|
|
42
|
+
readonly health: CacheHealthScore;
|
|
43
|
+
/** Epoch id these assignments belong to. */
|
|
44
|
+
readonly epochId: string | null;
|
|
45
|
+
/** Timestamp (epoch ms) of the last refresh. */
|
|
46
|
+
readonly lastRefreshAt: number;
|
|
47
|
+
/** Total chunk count across all stripes. */
|
|
48
|
+
readonly totalChunks: number;
|
|
49
|
+
}
|
|
@@ -16,7 +16,7 @@ import type { GameStateResponse } from "./game.js";
|
|
|
16
16
|
import type { SseEvent } from "./index.js";
|
|
17
17
|
import type { ProviderCacheResponse } from "./provider-cache.js";
|
|
18
18
|
import type { MemoryStatusResponse } from "./memory.js";
|
|
19
|
-
import type { SetupStatusResponse, SetupDetectResponse } from "./setup.js";
|
|
19
|
+
import type { SetupStatusResponse, SetupDetectResponse, SetupConfigureRequest, SetupConfigureResponse } from "./setup.js";
|
|
20
20
|
import type {
|
|
21
21
|
TurnsResponse,
|
|
22
22
|
ConversationTurnsResponse,
|
|
@@ -36,6 +36,8 @@ import type {
|
|
|
36
36
|
SchemaHealthResponse,
|
|
37
37
|
} from "./maintenance.js";
|
|
38
38
|
|
|
39
|
+
import type { CacheStripesResponse } from "./cache-stripes.js";
|
|
40
|
+
|
|
39
41
|
import type {
|
|
40
42
|
GameScoreRow,
|
|
41
43
|
GameScoresQuery,
|
|
@@ -300,6 +302,14 @@ export interface PerfLatest {
|
|
|
300
302
|
readonly n: number;
|
|
301
303
|
}
|
|
302
304
|
|
|
305
|
+
/** A single cache hit rate sample with timestamp. */
|
|
306
|
+
export interface CacheHitSample {
|
|
307
|
+
/** Cache hit percentage (0–100). */
|
|
308
|
+
readonly pct: number;
|
|
309
|
+
/** Epoch ms timestamp of the sample. */
|
|
310
|
+
readonly ts: number;
|
|
311
|
+
}
|
|
312
|
+
|
|
303
313
|
/** Average + latest statistics for cache hit percentage. */
|
|
304
314
|
export interface PerfCacheHit {
|
|
305
315
|
/** Average cache hit percentage (0–100). */
|
|
@@ -308,6 +318,8 @@ export interface PerfCacheHit {
|
|
|
308
318
|
readonly latest: number;
|
|
309
319
|
/** Number of samples in the window. */
|
|
310
320
|
readonly n: number;
|
|
321
|
+
/** Raw cache hit samples with timestamps for time-series charting. */
|
|
322
|
+
readonly samples: CacheHitSample[];
|
|
311
323
|
}
|
|
312
324
|
|
|
313
325
|
/** Diagnostic counters from the live dashboard snapshot. */
|
|
@@ -614,6 +626,16 @@ export const ENDPOINTS = {
|
|
|
614
626
|
"Lifetime provider prompt cache hit-rate aggregates + dollar savings estimate.",
|
|
615
627
|
} as const satisfies EndpointDef<"GET", undefined, ProviderCacheResponse>,
|
|
616
628
|
|
|
629
|
+
|
|
630
|
+
// ─── A3 Cache Stripes (PLAN_V2 Phase 4) ───────────────────────────
|
|
631
|
+
|
|
632
|
+
/** GET /api/cache-stripes — Per-stripe distribution + health score. */
|
|
633
|
+
cacheStripes: {
|
|
634
|
+
method: "GET",
|
|
635
|
+
path: "/api/cache-stripes",
|
|
636
|
+
description:
|
|
637
|
+
"Per-stripe distribution counts, average stability scores, and composite cache health.",
|
|
638
|
+
} as const satisfies EndpointDef<"GET", undefined, CacheStripesResponse>,
|
|
617
639
|
// ─── Memory Effectiveness (S53B) ───────────────────────────────────────
|
|
618
640
|
|
|
619
641
|
/** GET /api/memory-status — Memory store aggregate statistics. */
|
|
@@ -639,4 +661,12 @@ export const ENDPOINTS = {
|
|
|
639
661
|
description:
|
|
640
662
|
"Best-effort detection of local embedder backends (ollama, llama.cpp, ONNX) available on the machine.",
|
|
641
663
|
} as const satisfies EndpointDef<"GET", undefined, SetupDetectResponse>,
|
|
664
|
+
|
|
665
|
+
/** POST /api/setup-configure — Write embedder config to .mega-compact.env. */
|
|
666
|
+
setupConfigure: {
|
|
667
|
+
method: "POST",
|
|
668
|
+
path: "/api/setup-configure",
|
|
669
|
+
description:
|
|
670
|
+
"Write the chosen embedder configuration to .mega-compact.env (loaded at next startup). Returns whether a restart is required.",
|
|
671
|
+
} as const satisfies EndpointDef<"POST", SetupConfigureRequest, SetupConfigureResponse>,
|
|
642
672
|
} as const;
|
|
@@ -208,4 +208,19 @@ export type {
|
|
|
208
208
|
export type { MemoryStatusResponse, MemoryStatsTopMemory } from "./memory.js";
|
|
209
209
|
|
|
210
210
|
// Setup wizard — embedder configuration + backend detection
|
|
211
|
-
export type { SetupStatusResponse, SetupDetectResponse, DetectResult, OllamaDetectResult } from "./setup.js";
|
|
211
|
+
export type { SetupStatusResponse, SetupDetectResponse, SetupConfigureRequest, SetupConfigureResponse, DetectResult, OllamaDetectResult } from "./setup.js";
|
|
212
|
+
|
|
213
|
+
// S46 — memory graph (visual memory map)
|
|
214
|
+
export type {
|
|
215
|
+
MemoryMapResponse,
|
|
216
|
+
MemoryMapNode,
|
|
217
|
+
MemoryMapEdgeEntry,
|
|
218
|
+
MemoryMapQuery,
|
|
219
|
+
} from "./memory-map.js";
|
|
220
|
+
|
|
221
|
+
// A3 — cache stripe distribution + health
|
|
222
|
+
export type {
|
|
223
|
+
StripeBucket,
|
|
224
|
+
CacheHealthScore,
|
|
225
|
+
CacheStripesResponse,
|
|
226
|
+
} from "./cache-stripes.js";
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* api-contracts/memory-map.ts — Memory graph API contract (S46).
|
|
3
|
+
*
|
|
4
|
+
* Response shape for GET /api/memory-map: graph nodes, edges, and metadata.
|
|
5
|
+
* This is a read-only JSON payload consumed by the MemoryMapTab React component.
|
|
6
|
+
*/
|
|
7
|
+
import type { GraphMetadata } from "../../../src/memoryGraph.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Query parameters for GET /api/memory-map.
|
|
11
|
+
* All fields are optional.
|
|
12
|
+
*/
|
|
13
|
+
export interface MemoryMapQuery {
|
|
14
|
+
/** Filter to a single session ID. */
|
|
15
|
+
readonly sessionId?: string;
|
|
16
|
+
/** Cosine similarity threshold (0..1). Default 0.7. */
|
|
17
|
+
readonly threshold?: number;
|
|
18
|
+
/** Max semantic edges per node. Default 3. */
|
|
19
|
+
readonly maxEdgesPerNode?: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Response body for GET /api/memory-map. */
|
|
23
|
+
export interface MemoryMapResponse {
|
|
24
|
+
readonly nodes: MemoryMapNode[];
|
|
25
|
+
readonly edges: MemoryMapEdgeEntry[];
|
|
26
|
+
readonly metadata: GraphMetadata;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** A node in the response (client-safe subset — no full embedding vector). */
|
|
30
|
+
export interface MemoryMapNode {
|
|
31
|
+
readonly id: string;
|
|
32
|
+
readonly sessionId: string;
|
|
33
|
+
readonly label: string;
|
|
34
|
+
readonly summaryTruncated: string;
|
|
35
|
+
readonly tokenEstimate: number;
|
|
36
|
+
readonly timestamp: number;
|
|
37
|
+
readonly dedupStatus: string | undefined;
|
|
38
|
+
readonly raptorLevel: number;
|
|
39
|
+
readonly topicSummary: string | undefined;
|
|
40
|
+
readonly decisionCount: number;
|
|
41
|
+
readonly textSnippet: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** An edge entry in the response. */
|
|
45
|
+
export interface MemoryMapEdgeEntry {
|
|
46
|
+
readonly source: string;
|
|
47
|
+
readonly target: string;
|
|
48
|
+
readonly weight: number;
|
|
49
|
+
readonly type: "temporal" | "semantic" | "raptor_parent";
|
|
50
|
+
}
|
|
@@ -56,3 +56,25 @@ export interface SetupDetectResponse {
|
|
|
56
56
|
/** Error message if detection itself failed, or null. */
|
|
57
57
|
readonly error: string | null;
|
|
58
58
|
}
|
|
59
|
+
|
|
60
|
+
/** Request body for POST /api/setup-configure. */
|
|
61
|
+
export interface SetupConfigureRequest {
|
|
62
|
+
/** Which embedder to configure. "trigram" clears the URL (uses built-in). */
|
|
63
|
+
readonly embedder: "ollama" | "llama" | "trigram";
|
|
64
|
+
/** Optional override URL (for non-default Ollama ports or llama.cpp). */
|
|
65
|
+
readonly url?: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Response for POST /api/setup-configure. */
|
|
69
|
+
export interface SetupConfigureResponse {
|
|
70
|
+
/** The embedder that was configured. */
|
|
71
|
+
readonly embedder: string;
|
|
72
|
+
/** The URL that was written (null for trigram). */
|
|
73
|
+
readonly url: string | null;
|
|
74
|
+
/** Path to the .mega-compact.env file that was written. */
|
|
75
|
+
readonly envPath: string;
|
|
76
|
+
/** Whether the user needs to restart pi to activate. */
|
|
77
|
+
readonly restartRequired: boolean;
|
|
78
|
+
/** The already-active embedder, if the new config matches (no restart needed). */
|
|
79
|
+
readonly alreadyActive: boolean;
|
|
80
|
+
}
|
|
@@ -196,4 +196,39 @@ export function handleProviderCache(
|
|
|
196
196
|
} catch {
|
|
197
197
|
return false;
|
|
198
198
|
}
|
|
199
|
-
}
|
|
199
|
+
}
|
|
200
|
+
// ---------------------------------------------------------------------------
|
|
201
|
+
// handleCacheStripes — "GET /api/cache-stripes"
|
|
202
|
+
// ---------------------------------------------------------------------------
|
|
203
|
+
|
|
204
|
+
export function handleCacheStripes(
|
|
205
|
+
req: IncomingMessage,
|
|
206
|
+
res: ServerResponse,
|
|
207
|
+
ctx: RouteContext,
|
|
208
|
+
): boolean {
|
|
209
|
+
if (!req.url?.startsWith("/api/cache-stripes")) return false;
|
|
210
|
+
if (req.method !== "GET") {
|
|
211
|
+
res.writeHead(405, { "Content-Type": "application/json" });
|
|
212
|
+
res.end(JSON.stringify({ error: "method_not_allowed" }));
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
try {
|
|
216
|
+
const stateDir = ctx.stateDir;
|
|
217
|
+
const pfReq = createRequire(import.meta.url);
|
|
218
|
+
const { readCacheStripes } = pfReq(
|
|
219
|
+
"../../src/store/sqlite/cache-stripes.js",
|
|
220
|
+
) as typeof import("../../src/store/sqlite/cache-stripes.js");
|
|
221
|
+
const result = readCacheStripes(stateDir);
|
|
222
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
223
|
+
res.end(JSON.stringify(result));
|
|
224
|
+
} catch (e) {
|
|
225
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
226
|
+
res.end(
|
|
227
|
+
JSON.stringify({
|
|
228
|
+
error: "cache_stripes_unavailable",
|
|
229
|
+
detail: String(e),
|
|
230
|
+
}),
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
@@ -307,6 +307,9 @@ export function handlePerf(
|
|
|
307
307
|
avg: avg(get("cache_hit_pct")),
|
|
308
308
|
latest: latest(get("cache_hit_pct")),
|
|
309
309
|
n: get("cache_hit_pct").length,
|
|
310
|
+
samples: rows
|
|
311
|
+
.filter((r) => r.kind === "cache_hit_pct")
|
|
312
|
+
.map((r) => ({ pct: r.value, ts: r.ts })),
|
|
310
313
|
},
|
|
311
314
|
db_recompute_ms: {
|
|
312
315
|
p50: pct(get("db_recompute_ms"), 50),
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* routes-memory-map.ts — GET /api/memory-map route handler (S46).
|
|
3
|
+
*
|
|
4
|
+
* Builds a memory graph from the local SQLite store and returns it as JSON.
|
|
5
|
+
* Uses an inline require to the pi-agnostic src/memoryGraph.ts builder.
|
|
6
|
+
*/
|
|
7
|
+
import { createRequire } from "node:module";
|
|
8
|
+
import type { ServerResponse, IncomingMessage } from "node:http";
|
|
9
|
+
import { parse as parseUrl } from "node:url";
|
|
10
|
+
import type { RouteContext } from "./routes-core.js";
|
|
11
|
+
import type { MemoryMapResponse, MemoryMapNode, MemoryMapEdgeEntry } from "./api-contracts/memory-map.js";
|
|
12
|
+
|
|
13
|
+
const _req = createRequire(import.meta.url);
|
|
14
|
+
|
|
15
|
+
// guardrails-allow PREVENT-PI-004: localhost-only dashboard API endpoint that reads from the local SQLite store — zero remote network calls.
|
|
16
|
+
|
|
17
|
+
export function handleMemoryMap(
|
|
18
|
+
req: IncomingMessage,
|
|
19
|
+
res: ServerResponse,
|
|
20
|
+
ctx: RouteContext,
|
|
21
|
+
): boolean {
|
|
22
|
+
if (req.method !== "GET") return false;
|
|
23
|
+
const parsed = parseUrl(req.url ?? "", true);
|
|
24
|
+
if (parsed.pathname !== "/api/memory-map") return false;
|
|
25
|
+
|
|
26
|
+
// guardrails-allow PREVENT-PI-004: local loopback-only dashboard server — reads the local SQLite store for graph data.
|
|
27
|
+
const { buildMemoryGraph } = _req("../../src/memoryGraph.js") as {
|
|
28
|
+
buildMemoryGraph: (opts?: {
|
|
29
|
+
sessionId?: string;
|
|
30
|
+
similarityThreshold?: number;
|
|
31
|
+
maxEdgesPerNode?: number;
|
|
32
|
+
stateDir?: string;
|
|
33
|
+
includeRaptorEdges?: boolean;
|
|
34
|
+
includeTemporalEdges?: boolean;
|
|
35
|
+
}) => MemoryGraphReturn;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
type MemoryGraphReturn = {
|
|
39
|
+
nodes: Array<{
|
|
40
|
+
id: string;
|
|
41
|
+
sessionId: string;
|
|
42
|
+
label: string;
|
|
43
|
+
summaryTruncated: string;
|
|
44
|
+
tokenEstimate: number;
|
|
45
|
+
timestamp: number;
|
|
46
|
+
dedupStatus: string | undefined;
|
|
47
|
+
raptorLevel: number;
|
|
48
|
+
topicSummary: string | undefined;
|
|
49
|
+
decisionCount: number;
|
|
50
|
+
textSnippet: string;
|
|
51
|
+
}>;
|
|
52
|
+
edges: Array<{
|
|
53
|
+
source: string;
|
|
54
|
+
target: string;
|
|
55
|
+
weight: number;
|
|
56
|
+
type: "temporal" | "semantic" | "raptor_parent";
|
|
57
|
+
}>;
|
|
58
|
+
metadata: {
|
|
59
|
+
sessionCount: number;
|
|
60
|
+
totalCheckpoints: number;
|
|
61
|
+
totalEdges: number;
|
|
62
|
+
semanticEdgeCount: number;
|
|
63
|
+
temporalEdgeCount: number;
|
|
64
|
+
raptorEdgeCount: number;
|
|
65
|
+
similarityThresholdUsed: number;
|
|
66
|
+
builtAt: number;
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const sessionId = typeof parsed.query.sessionId === "string" ? parsed.query.sessionId : undefined;
|
|
71
|
+
const threshold = typeof parsed.query.threshold === "string" ? Number.parseFloat(parsed.query.threshold) : undefined;
|
|
72
|
+
const maxEdges = typeof parsed.query.maxEdgesPerNode === "string" ? Number.parseInt(parsed.query.maxEdgesPerNode, 10) : undefined;
|
|
73
|
+
const raptorEdges = parsed.query.includeRaptorEdges === "false" ? false : true;
|
|
74
|
+
const temporalEdges = parsed.query.includeTemporalEdges === "false" ? false : true;
|
|
75
|
+
|
|
76
|
+
const graph = buildMemoryGraph({
|
|
77
|
+
sessionId,
|
|
78
|
+
similarityThreshold: threshold,
|
|
79
|
+
maxEdgesPerNode: maxEdges,
|
|
80
|
+
stateDir: ctx.stateDir,
|
|
81
|
+
includeRaptorEdges: raptorEdges,
|
|
82
|
+
includeTemporalEdges: temporalEdges,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const nodes: MemoryMapNode[] = graph.nodes.map((n) => ({
|
|
86
|
+
id: n.id,
|
|
87
|
+
sessionId: n.sessionId,
|
|
88
|
+
label: n.label,
|
|
89
|
+
summaryTruncated: n.summaryTruncated,
|
|
90
|
+
tokenEstimate: n.tokenEstimate,
|
|
91
|
+
timestamp: n.timestamp,
|
|
92
|
+
dedupStatus: n.dedupStatus,
|
|
93
|
+
raptorLevel: n.raptorLevel,
|
|
94
|
+
topicSummary: n.topicSummary,
|
|
95
|
+
decisionCount: n.decisionCount,
|
|
96
|
+
textSnippet: n.textSnippet,
|
|
97
|
+
}));
|
|
98
|
+
|
|
99
|
+
const edges: MemoryMapEdgeEntry[] = graph.edges as MemoryMapEdgeEntry[];
|
|
100
|
+
const response: MemoryMapResponse = { nodes, edges, metadata: graph.metadata };
|
|
101
|
+
|
|
102
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
103
|
+
res.end(JSON.stringify(response));
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
@@ -11,11 +11,15 @@
|
|
|
11
11
|
|
|
12
12
|
import { spawnSync } from "node:child_process"; // guardrails-allow PREVENT-PI-004: local subprocess detection only
|
|
13
13
|
import { createRequire } from "node:module";
|
|
14
|
+
import { writeFileSync, mkdirSync } from "node:fs";
|
|
15
|
+
import { join } from "node:path";
|
|
14
16
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
15
17
|
import type { RouteContext } from "./routes-core.js";
|
|
16
18
|
import type {
|
|
17
19
|
SetupStatusResponse,
|
|
18
20
|
SetupDetectResponse,
|
|
21
|
+
SetupConfigureRequest,
|
|
22
|
+
SetupConfigureResponse,
|
|
19
23
|
DetectResult,
|
|
20
24
|
OllamaDetectResult,
|
|
21
25
|
} from "./api-contracts/setup.js";
|
|
@@ -179,3 +183,111 @@ export function handleSetupDetect(
|
|
|
179
183
|
res.end(JSON.stringify(body));
|
|
180
184
|
return true;
|
|
181
185
|
}
|
|
186
|
+
|
|
187
|
+
// ---------------------------------------------------------------------------
|
|
188
|
+
// handleSetupConfigure — POST "/api/setup-configure"
|
|
189
|
+
// ---------------------------------------------------------------------------
|
|
190
|
+
|
|
191
|
+
const OLLAMA_DEFAULT_URL = "http://localhost:11434/api/embeddings"; // guardrails-allow PREVENT-PI-004: localhost-only config string, not a runtime fetch
|
|
192
|
+
const LLAMA_DEFAULT_URL = "http://localhost:8080/v1/embeddings"; // guardrails-allow PREVENT-PI-004: localhost-only config string, not a runtime fetch
|
|
193
|
+
|
|
194
|
+
function readJsonBody(
|
|
195
|
+
req: IncomingMessage,
|
|
196
|
+
cb: (
|
|
197
|
+
result:
|
|
198
|
+
| { ok: true; value: Record<string, unknown> }
|
|
199
|
+
| { ok: false; error: string },
|
|
200
|
+
) => void,
|
|
201
|
+
): void {
|
|
202
|
+
let body = "";
|
|
203
|
+
let tooBig = false;
|
|
204
|
+
req.on("data", (chunk: Buffer) => {
|
|
205
|
+
if (body.length > 65536) { tooBig = true; return; }
|
|
206
|
+
body += chunk.toString();
|
|
207
|
+
});
|
|
208
|
+
req.on("end", () => {
|
|
209
|
+
if (tooBig) return cb({ ok: false, error: "body_too_large" });
|
|
210
|
+
try {
|
|
211
|
+
const v = body ? JSON.parse(body) : {}; // PREVENT-001: parsed value type-checked below
|
|
212
|
+
if (typeof v !== "object" || v === null || Array.isArray(v)) {
|
|
213
|
+
return cb({ ok: false, error: "invalid_object" });
|
|
214
|
+
}
|
|
215
|
+
cb({ ok: true, value: v as Record<string, unknown> });
|
|
216
|
+
} catch {
|
|
217
|
+
cb({ ok: false, error: "invalid_json" });
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
req.on("error", () => cb({ ok: false, error: "read_error" }));
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export function handleSetupConfigure(
|
|
224
|
+
req: IncomingMessage,
|
|
225
|
+
res: ServerResponse,
|
|
226
|
+
ctx: RouteContext,
|
|
227
|
+
): boolean {
|
|
228
|
+
if (req.url !== "/api/setup-configure") return false;
|
|
229
|
+
if (req.method !== "POST") {
|
|
230
|
+
// guardrails-allow PREVENT-PI-004: loopback dashboard response (local)
|
|
231
|
+
res.writeHead(405, { "Content-Type": "application/json" });
|
|
232
|
+
res.end(JSON.stringify({ error: "method_not_allowed" }));
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
readJsonBody(req, (parsed) => {
|
|
236
|
+
if (!parsed.ok) {
|
|
237
|
+
// guardrails-allow PREVENT-PI-004: loopback dashboard response (local)
|
|
238
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
239
|
+
res.end(JSON.stringify({ error: parsed.error }));
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
const body = parsed.value as unknown as SetupConfigureRequest;
|
|
243
|
+
const embedder = body.embedder;
|
|
244
|
+
if (embedder !== "ollama" && embedder !== "llama" && embedder !== "trigram") {
|
|
245
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
246
|
+
res.end(JSON.stringify({ error: "invalid_embedder" }));
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
const url = body.url;
|
|
250
|
+
let resolvedUrl: string | null;
|
|
251
|
+
if (embedder === "ollama") resolvedUrl = typeof url === "string" && url ? url : OLLAMA_DEFAULT_URL;
|
|
252
|
+
else if (embedder === "llama") resolvedUrl = typeof url === "string" && url ? url : LLAMA_DEFAULT_URL;
|
|
253
|
+
else resolvedUrl = null;
|
|
254
|
+
|
|
255
|
+
// Write .mega-compact.env to the state dir (loaded by env-loader at next startup).
|
|
256
|
+
const stateDir = ctx.stateDir;
|
|
257
|
+
const envPath = join(stateDir, ".mega-compact.env");
|
|
258
|
+
const lines: string[] = [
|
|
259
|
+
"# Mega-Compact Embedder Configuration",
|
|
260
|
+
`# Configured via dashboard Setup tab at ${new Date().toISOString()}`,
|
|
261
|
+
];
|
|
262
|
+
if (resolvedUrl) {
|
|
263
|
+
lines.push(`export MEGACOMPACT_EMBEDDING_URL="${resolvedUrl}"`);
|
|
264
|
+
} else {
|
|
265
|
+
lines.push("# trigram: built-in embedder, no URL needed");
|
|
266
|
+
lines.push("# unset MEGACOMPACT_EMBEDDING_URL (commented to override any shell-set value)");
|
|
267
|
+
lines.push("# export MEGACOMPACT_EMBEDDING_URL=");
|
|
268
|
+
}
|
|
269
|
+
lines.push("");
|
|
270
|
+
try {
|
|
271
|
+
mkdirSync(stateDir, { recursive: true });
|
|
272
|
+
writeFileSync(envPath, lines.join("\n"), "utf-8");
|
|
273
|
+
} catch (e) {
|
|
274
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
275
|
+
res.end(JSON.stringify({ error: `write_failed: ${e instanceof Error ? e.message : String(e)}` }));
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
// Detect if the new config matches what's already active (no restart needed).
|
|
279
|
+
const currentUrl = process.env["MEGACOMPACT_EMBEDDING_URL"];
|
|
280
|
+
const alreadyActive = (resolvedUrl === null && !currentUrl) || (resolvedUrl !== null && currentUrl === resolvedUrl);
|
|
281
|
+
const resp: SetupConfigureResponse = {
|
|
282
|
+
embedder,
|
|
283
|
+
url: resolvedUrl,
|
|
284
|
+
envPath,
|
|
285
|
+
restartRequired: !alreadyActive,
|
|
286
|
+
alreadyActive,
|
|
287
|
+
};
|
|
288
|
+
// guardrails-allow PREVENT-PI-004: loopback dashboard response (local)
|
|
289
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
290
|
+
res.end(JSON.stringify(resp));
|
|
291
|
+
});
|
|
292
|
+
return true;
|
|
293
|
+
}
|
|
@@ -21,4 +21,6 @@ export { handleTurns } from "./routes-turns.js";
|
|
|
21
21
|
export { handleMaintenance } from "./routes-maintenance.js";
|
|
22
22
|
export { handleProviderCache } from "./routes-cache.js";
|
|
23
23
|
export { handleMemoryStatus } from "./routes-memory.js";
|
|
24
|
-
export { handleSetupStatus, handleSetupDetect } from "./routes-setup.js";
|
|
24
|
+
export { handleSetupStatus, handleSetupDetect, handleSetupConfigure } from "./routes-setup.js";
|
|
25
|
+
export { handleMemoryMap } from "./routes-memory-map.js";
|
|
26
|
+
export { handleCacheStripes } from "./routes-cache.js";
|
|
@@ -38,9 +38,12 @@ import {
|
|
|
38
38
|
handleTurns,
|
|
39
39
|
handleMaintenance,
|
|
40
40
|
handleProviderCache,
|
|
41
|
+
handleCacheStripes,
|
|
41
42
|
handleMemoryStatus,
|
|
42
43
|
handleSetupStatus,
|
|
43
44
|
handleSetupDetect,
|
|
45
|
+
handleSetupConfigure,
|
|
46
|
+
handleMemoryMap,
|
|
44
47
|
handleStatic,
|
|
45
48
|
} from "./routes.js";
|
|
46
49
|
|
|
@@ -231,8 +234,11 @@ export async function launchDashboardServer(
|
|
|
231
234
|
if (handleMaintenance(req, res, ctx)) return;
|
|
232
235
|
if (handleProviderCache(req, res, ctx)) return;
|
|
233
236
|
if (handleMemoryStatus(req, res, ctx)) return;
|
|
237
|
+
if (handleCacheStripes(req, res, ctx)) return;
|
|
234
238
|
if (handleSetupStatus(req, res, ctx)) return;
|
|
235
239
|
if (handleSetupDetect(req, res, ctx)) return;
|
|
240
|
+
if (handleSetupConfigure(req, res, ctx)) return;
|
|
241
|
+
if (handleMemoryMap(req, res, ctx)) return;
|
|
236
242
|
handleStatic(req, res, ctx);
|
|
237
243
|
});
|
|
238
244
|
|
|
@@ -30,6 +30,7 @@ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
|
30
30
|
import { closeVectorIndex } from "../src/store/vectorIndex.js";
|
|
31
31
|
import { closeMemoryIndex } from "../src/store/memoryIndex.js";
|
|
32
32
|
import { loadConfig } from "./mega-config.js";
|
|
33
|
+
import { loadMegaEnv } from "./mega-runtime/env-loader.js";
|
|
33
34
|
import { MegaRuntime } from "./mega-runtime.js";
|
|
34
35
|
import { registerEventHandlers } from "./mega-events.js";
|
|
35
36
|
import { registerCommands } from "./mega-commands.js";
|
|
@@ -41,6 +42,10 @@ import { registerMetricsCommands } from "./mega-metrics-cmds.js";
|
|
|
41
42
|
import { registerTopicsCommands } from "./mega-topics-cmds.js";
|
|
42
43
|
|
|
43
44
|
export default function (pi: ExtensionAPI) {
|
|
45
|
+
// Load .mega-compact.env (written by /mega-setup + dashboard Setup tab) BEFORE
|
|
46
|
+
// config resolution so the wizard's choices take effect. Shell env wins over
|
|
47
|
+
// the file (see env-loader.ts). Non-fatal: missing/malformed file is a no-op.
|
|
48
|
+
loadMegaEnv(loadConfig().stateDir);
|
|
44
49
|
const config = loadConfig();
|
|
45
50
|
// S38.9: preflight env validation — check for obviously invalid values at startup.
|
|
46
51
|
// Non-fatal: log warnings and fall back to defaults.
|
|
@@ -168,9 +168,21 @@ export interface MegaConfig {
|
|
|
168
168
|
* the tail of the view when auto is OFF AND no trim action is needed. Default ON
|
|
169
169
|
* (true). When false, restores the pre-sprint systemPrompt prepend behavior. */
|
|
170
170
|
recallTailInject: boolean;
|
|
171
|
+
/** A1 PLAN_V2 Phase 2: Message Separation — isolate user/assistant turns
|
|
172
|
+
* from volatile tool results so the prompt-cache prefix stays stable.
|
|
173
|
+
* Default OFF (flag-OFF = byte-identical pre-sprint). */
|
|
174
|
+
messageSeparation: boolean;
|
|
171
175
|
debug: boolean;
|
|
172
176
|
/** Master reconciliation: TUI shutdown widget (MEGACOMPACT_TUI_WIDGET=0 to disable). */
|
|
173
177
|
tuiWidget: boolean;
|
|
178
|
+
/** S57 B1: Query reformulation via embedding-neighbor keyword expansion. */
|
|
179
|
+
ragQueryReformulation: boolean;
|
|
180
|
+
/** S57 B2: Tiered recall router (L0 cache -> L1 FTS5 -> L2). */
|
|
181
|
+
ragTieredRouter: boolean;
|
|
182
|
+
/** S57 B3: Recall quality metrics (precision/recall scoring + logging). */
|
|
183
|
+
ragRecallMetrics: boolean;
|
|
184
|
+
/** S57 B4: Memory graph traversal (dashboard-oriented). */
|
|
185
|
+
ragMemoryGraph: boolean;
|
|
174
186
|
}
|
|
175
187
|
|
|
176
188
|
function envFlag(name: string, fallback: number): number {
|
|
@@ -332,7 +344,12 @@ export function loadConfig(): MegaConfig {
|
|
|
332
344
|
recallMaxTokens: envFlag("MEGACOMPACT_RECALL_MAX_TOKENS", 1500),
|
|
333
345
|
windowDedupe: envBool("MEGACOMPACT_WINDOW_DEDUPE", true),
|
|
334
346
|
recallTailInject: envBool("MEGACOMPACT_RECALL_TAIL_INJECT", true),
|
|
347
|
+
messageSeparation: envBool("MEGACOMPACT_MESSAGE_SEPARATION", false),
|
|
335
348
|
tuiWidget: envBool("MEGACOMPACT_TUI_WIDGET", true),
|
|
349
|
+
ragQueryReformulation: envBool("MEGACOMPACT_QUERY_REFORMULATION", false),
|
|
350
|
+
ragTieredRouter: envBool("MEGACOMPACT_TIERED_ROUTER", false),
|
|
351
|
+
ragRecallMetrics: envBool("MEGACOMPACT_RECALL_METRICS", false),
|
|
352
|
+
ragMemoryGraph: envBool("MEGACOMPACT_MEMORY_GRAPH", false),
|
|
336
353
|
// D.1: env-overridable recompact delta (minimum context growth % before
|
|
337
354
|
// re-compacting instead of replaying the cached live trim). Default 50.
|
|
338
355
|
recompactPctDelta: envFlag("MEGACOMPACT_RECOMPACT_PCT_DELTA", 50),
|
|
@@ -37,6 +37,7 @@ import {
|
|
|
37
37
|
} from "../mega-config.js";
|
|
38
38
|
import { appendMirrorMessages } from "./mirror-append.js";
|
|
39
39
|
import { stagedForTail, withRecallTail } from "./recall-tail.js";
|
|
40
|
+
import { buildSeparatedPrompt } from "./separated-prompt.js";
|
|
40
41
|
|
|
41
42
|
/** Register the context event handler (live-trim auto-trigger). */
|
|
42
43
|
export function registerContextHandler(
|
|
@@ -69,8 +70,15 @@ export function registerContextHandler(
|
|
|
69
70
|
// REAL transcript before any view is built, so the injected tail never
|
|
70
71
|
// reaches raw_transcript (PREVENT-PI: append-only, view-only).
|
|
71
72
|
const tailResult = (msgs?: readonly AgentMessage[]) => {
|
|
72
|
-
|
|
73
|
-
|
|
73
|
+
const base = msgs ?? messages;
|
|
74
|
+
if (!stagedForTail(runtime, config) && !config.messageSeparation) return undefined;
|
|
75
|
+
let result: AgentMessage[] = stagedForTail(runtime, config)
|
|
76
|
+
? withRecallTail(base, runtime, config)
|
|
77
|
+
: (base as AgentMessage[]);
|
|
78
|
+
if (config.messageSeparation) {
|
|
79
|
+
result = buildSeparatedPrompt(result);
|
|
80
|
+
}
|
|
81
|
+
return { messages: result };
|
|
74
82
|
};
|
|
75
83
|
// Always track context for the dashboard/widget, even when auto is off.
|
|
76
84
|
// (v0.8 regression: !config.auto gate sat above this, leaving ctx stats
|