pi-mega-compact 0.13.6 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -6
- package/dist/extensions/dashboard-server/api-contracts/endpoints/registry.js +6 -0
- package/dist/extensions/dashboard-server/index-reader.js +50 -25
- package/dist/extensions/dashboard-server/resolve-snapshot.js +81 -0
- package/dist/extensions/dashboard-server/routes-core.js +8 -3
- package/dist/extensions/dashboard-server/routes-rag-settings-helpers.js +7 -0
- package/dist/extensions/dashboard-server/routes-raptor.js +60 -0
- package/dist/extensions/dashboard-server/routes-repo.js +5 -1
- package/dist/extensions/dashboard-server/routes-sessions.js +6 -3
- package/dist/extensions/dashboard-server/routes.js +1 -1
- package/dist/extensions/dashboard-server/server.js +3 -1
- package/dist/extensions/mega-pipeline/recall.js +24 -16
- package/dist/extensions/mega-runtime/capture-model.js +5 -2
- package/dist/src/config/dedup.js +2 -1
- package/dist/src/costApi.js +113 -0
- package/dist/src/dedup/raptor/incremental.js +31 -3
- package/dist/src/dedup/raptor/index.js +10 -6
- package/dist/src/pricing.js +8 -0
- package/dist/src/vector-search.js +3 -3
- package/extensions/dashboard-client/dist/assets/{AreaChart-KAmp_6bL.js → AreaChart-C68tGr2J.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{AreaChart-KAmp_6bL.js.map → AreaChart-C68tGr2J.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{CacheTab-Bk-gm-R0.js → CacheTab-CDyZqMO-.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{CacheTab-Bk-gm-R0.js.map → CacheTab-CDyZqMO-.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/EventsTab-ByPYMJVG.js +2 -0
- package/extensions/dashboard-client/dist/assets/EventsTab-ByPYMJVG.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{HealthTab-D-IzmV29.js → HealthTab-CeHQR0py.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{HealthTab-D-IzmV29.js.map → HealthTab-CeHQR0py.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-CrlkCFVj.js → MaintenanceTab-ceTD_c1A.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-CrlkCFVj.js.map → MaintenanceTab-ceTD_c1A.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/MemoryMapTab-CRUdVR7u.js +2 -0
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-DHUdZ7RR.js.map → MemoryMapTab-CRUdVR7u.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MetricsTab-B7I4HWVg.js → MetricsTab-DP7Kmdu9.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MetricsTab-B7I4HWVg.js.map → MetricsTab-DP7Kmdu9.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{OverviewTab-K6j4ZI7u.js → OverviewTab-4CGP0djv.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{OverviewTab-K6j4ZI7u.js.map → OverviewTab-4CGP0djv.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{ReposTab-BSRWhn56.js → ReposTab-DUrP7Efa.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{ReposTab-BSRWhn56.js.map → ReposTab-DUrP7Efa.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SessionsTab-BXdizHN1.js → SessionsTab-Cg-IsijD.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SessionsTab-BXdizHN1.js.map → SessionsTab-Cg-IsijD.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SetupTab-CAgyfqY3.js → SetupTab-ZE1daXjN.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SetupTab-CAgyfqY3.js.map → SetupTab-ZE1daXjN.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-DwgCzPD9.js → TimeSavedCard-BkTgi3Af.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-DwgCzPD9.js.map → TimeSavedCard-BkTgi3Af.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TurnsTab-CVKcStBp.js → TurnsTab-CZvudHQF.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TurnsTab-CVKcStBp.js.map → TurnsTab-CZvudHQF.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{WikiTab-BNohxTbs.js → WikiTab-BVAnGp8_.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{WikiTab-BNohxTbs.js.map → WikiTab-BVAnGp8_.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{button-B4A-_dCA.js → button-CUrzhi2A.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{button-B4A-_dCA.js.map → button-CUrzhi2A.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{card-Cjn7Ifoe.js → card-BsfojHfp.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{card-Cjn7Ifoe.js.map → card-BsfojHfp.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{index-CQjCLvv7.js → index-OM3w-l2T.js} +11 -11
- package/extensions/dashboard-client/dist/assets/index-OM3w-l2T.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/pricing-DkYp8-vi.js +2 -0
- package/extensions/dashboard-client/dist/assets/pricing-DkYp8-vi.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{switch-CcdXX0Zm.js → switch-qSz2Un3t.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{switch-CcdXX0Zm.js.map → switch-qSz2Un3t.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{toggle-KdBnFLu3.js → toggle-DyBKcLe-.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{toggle-KdBnFLu3.js.map → toggle-DyBKcLe-.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{useSSE-B6t44vzc.js → useSSE-DqVouqww.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{useSSE-B6t44vzc.js.map → useSSE-DqVouqww.js.map} +1 -1
- package/extensions/dashboard-client/dist/index.html +1 -1
- package/extensions/dashboard-client/src/api/client.ts +10 -0
- package/extensions/dashboard-client/src/components/EventStream.tsx +1 -1
- package/extensions/dashboard-client/src/tabs/MemoryMapTab/RaptorTreeView.tsx +58 -4
- package/extensions/dashboard-server/api-contracts/endpoints/registry.ts +9 -1
- package/extensions/dashboard-server/api-contracts/index.ts +2 -2
- package/extensions/dashboard-server/api-contracts/raptor.ts +19 -0
- package/extensions/dashboard-server/index-reader.ts +29 -4
- package/extensions/dashboard-server/resolve-snapshot.ts +98 -0
- package/extensions/dashboard-server/routes-core.ts +8 -3
- package/extensions/dashboard-server/routes-rag-settings-helpers.ts +17 -0
- package/extensions/dashboard-server/routes-raptor.ts +88 -1
- package/extensions/dashboard-server/routes-repo.ts +5 -1
- package/extensions/dashboard-server/routes-sessions.ts +6 -3
- package/extensions/dashboard-server/routes.ts +1 -1
- package/extensions/dashboard-server/server.ts +2 -0
- package/extensions/mega-pipeline/recall.ts +30 -21
- package/extensions/mega-runtime/capture-model.ts +5 -2
- package/package.json +1 -1
- package/src/config/dedup.ts +2 -1
- package/src/costApi.ts +131 -0
- package/src/dedup/raptor/incremental.ts +48 -3
- package/src/dedup/raptor/index.ts +10 -6
- package/src/pricing.ts +8 -0
- package/src/vector-search.ts +3 -3
- package/extensions/dashboard-client/dist/assets/EventsTab-Cyylo0of.js +0 -2
- package/extensions/dashboard-client/dist/assets/EventsTab-Cyylo0of.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/MemoryMapTab-DHUdZ7RR.js +0 -2
- package/extensions/dashboard-client/dist/assets/index-CQjCLvv7.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/pricing-CvE4NllQ.js +0 -2
- package/extensions/dashboard-client/dist/assets/pricing-CvE4NllQ.js.map +0 -1
|
@@ -13,10 +13,12 @@
|
|
|
13
13
|
import type { Embedder, Vector } from "../../embedder.js";
|
|
14
14
|
import { cosineSimilarity } from "../../embedder.js";
|
|
15
15
|
import { defaultEmbedder as getDefaultEmbedder } from "../../embedder.js";
|
|
16
|
+
import type { EngineMessage } from "../../types.js";
|
|
16
17
|
import { buildRaptorTree, type Leaf, type RaptorTree } from "./tree.js";
|
|
17
18
|
import type { QualityMarker } from "./guardrails.js";
|
|
19
|
+
import { applyHallucinationGuardrails, sourceTokenSet } from "./guardrails.js";
|
|
18
20
|
import { meanVector } from "./kmeans.js";
|
|
19
|
-
import { summarizeCluster } from "./summarizer.js";
|
|
21
|
+
import { summarizeCluster, extractiveClusterSummary } from "./summarizer.js";
|
|
20
22
|
import type { Logger } from "../../log.js";
|
|
21
23
|
import {
|
|
22
24
|
saveRaptorTree,
|
|
@@ -27,6 +29,38 @@ import {
|
|
|
27
29
|
/** When >FRESH_THRESHOLD of existing leaves are new, a full rebuild is cheaper. */
|
|
28
30
|
const FRESH_THRESHOLD = 0.5;
|
|
29
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Summarize + apply hallucination guardrails (mirrors tree.ts:summarizeInto).
|
|
34
|
+
* If the guardrail marks the summary as extractive_fallback (drift/hallucination),
|
|
35
|
+
* re-summarize with the deterministic extractive path so we never serve a
|
|
36
|
+
* drifted LLM summary from an incremental update.
|
|
37
|
+
*/
|
|
38
|
+
function summarizeGuarded(
|
|
39
|
+
messages: EngineMessage[],
|
|
40
|
+
centroid: Vector,
|
|
41
|
+
embedder: Embedder,
|
|
42
|
+
consistencyThreshold?: number,
|
|
43
|
+
): { summary: string; tokenEstimate: number; qualityMarker: QualityMarker } {
|
|
44
|
+
let cs = summarizeCluster(messages);
|
|
45
|
+
const sources = messages.map((m) => m.text);
|
|
46
|
+
const guard = applyHallucinationGuardrails({
|
|
47
|
+
summary: cs.summary,
|
|
48
|
+
sources,
|
|
49
|
+
centroid,
|
|
50
|
+
embedder,
|
|
51
|
+
sourceTokens: sourceTokenSet(sources),
|
|
52
|
+
consistencyThreshold,
|
|
53
|
+
});
|
|
54
|
+
if (guard.marker === "extractive_fallback") {
|
|
55
|
+
cs = extractiveClusterSummary(messages);
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
summary: cs.summary,
|
|
59
|
+
tokenEstimate: cs.tokenEstimate,
|
|
60
|
+
qualityMarker: guard.marker === "extractive_fallback" ? "low" : guard.marker,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
30
64
|
/**
|
|
31
65
|
* Incrementally update a persisted RAPTOR tree with new leaves.
|
|
32
66
|
*
|
|
@@ -173,6 +207,7 @@ export function incrementRaptorTree(
|
|
|
173
207
|
for (const l of reallyNewLeaves) leafMap.set(l.id, l);
|
|
174
208
|
|
|
175
209
|
// Recompute affected Level-0 nodes.
|
|
210
|
+
const embedder = opts.embedder ?? getDefaultEmbedder();
|
|
176
211
|
for (const nid of affectedNodeIds) {
|
|
177
212
|
const node = tree.nodes.get(nid);
|
|
178
213
|
if (!node) continue;
|
|
@@ -186,7 +221,12 @@ export function incrementRaptorTree(
|
|
|
186
221
|
// Summarize: flatten messages from all covered leaves.
|
|
187
222
|
const messages = coveredLeaves.flatMap((l) => l.messages);
|
|
188
223
|
if (messages.length > 0) {
|
|
189
|
-
const cs =
|
|
224
|
+
const cs = summarizeGuarded(
|
|
225
|
+
messages,
|
|
226
|
+
node.embedding,
|
|
227
|
+
embedder,
|
|
228
|
+
opts.consistencyThreshold,
|
|
229
|
+
);
|
|
190
230
|
node.summary = cs.summary;
|
|
191
231
|
node.tokenEstimate = cs.tokenEstimate;
|
|
192
232
|
}
|
|
@@ -215,7 +255,12 @@ export function incrementRaptorTree(
|
|
|
215
255
|
);
|
|
216
256
|
const messages = covered.flatMap((l) => l.messages);
|
|
217
257
|
if (messages.length > 0) {
|
|
218
|
-
const cs =
|
|
258
|
+
const cs = summarizeGuarded(
|
|
259
|
+
messages,
|
|
260
|
+
node.embedding,
|
|
261
|
+
embedder,
|
|
262
|
+
opts.consistencyThreshold,
|
|
263
|
+
);
|
|
219
264
|
node.summary = cs.summary;
|
|
220
265
|
node.tokenEstimate = cs.tokenEstimate;
|
|
221
266
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* index.ts — RAPTOR orchestrator (Sprint 13, Phase 6).
|
|
2
|
+
* index.ts — RAPTOR orchestrator (Sprint 13, Phase 6 → promoted to live in S42B).
|
|
3
3
|
*
|
|
4
4
|
* Entry point that turns a session's leaves into a hierarchical summary tree.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* The tree is BUILT, PERSISTED to raptor_nodes, and SERVED in recall queries
|
|
6
|
+
* when RAPTOR_ENABLED=true (default). Set RAPTOR_SHADOW_MODE=true to build +
|
|
7
|
+
* persist only without serving (transition/eval use).
|
|
8
8
|
*
|
|
9
9
|
* PREVENT-PI-004: no network here. Any Ollama call lives in summarizer.ts
|
|
10
10
|
* (localhost-only, annotated). This module is pure orchestration.
|
|
@@ -20,9 +20,13 @@ import { saveRaptorTree, listRaptorNodes } from "../../store/sqlite.js";
|
|
|
20
20
|
import { insertBuildHistory, computeCoherenceScore } from "./buildHistory.js";
|
|
21
21
|
import { loadDedupConfig } from "../../config/dedup.js";
|
|
22
22
|
|
|
23
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* Shadow mode default OFF: the tree is built, persisted, AND served when
|
|
25
|
+
* RAPTOR_ENABLED=true (the Setup tab toggle). Set RAPTOR_SHADOW_MODE=true to
|
|
26
|
+
* build + persist only (transition/eval use without serving live recall).
|
|
27
|
+
*/
|
|
24
28
|
export function isShadowMode(): boolean {
|
|
25
|
-
return process.env.RAPTOR_SHADOW_MODE
|
|
29
|
+
return process.env.RAPTOR_SHADOW_MODE === "true";
|
|
26
30
|
}
|
|
27
31
|
|
|
28
32
|
export interface RaptorOrchestratorOptions {
|
package/src/pricing.ts
CHANGED
|
@@ -30,6 +30,8 @@ export const MODEL_INPUT_RATES: Record<string, number> = {
|
|
|
30
30
|
"claude-3-opus": 15e-6,
|
|
31
31
|
"claude-3-haiku": 0.25e-6,
|
|
32
32
|
"claude-3.5-haiku": 0.8e-6,
|
|
33
|
+
"claude-mythos-5": 15e-6, // Opus-class custom alias
|
|
34
|
+
"claude-fable": 5e-6, // Claude 5 mid-tier
|
|
33
35
|
"gpt-4o": 2.5e-6,
|
|
34
36
|
"gpt-4o-mini": 0.15e-6,
|
|
35
37
|
"gpt-4-turbo": 10e-6,
|
|
@@ -39,11 +41,17 @@ export const MODEL_INPUT_RATES: Record<string, number> = {
|
|
|
39
41
|
"gemini-2.0-flash": 0.1e-6,
|
|
40
42
|
"deepseek-chat": 0.14e-6,
|
|
41
43
|
"deepseek-reasoner": 0.55e-6,
|
|
44
|
+
"deepseek-v4-flash": 0.14e-6, // DeepSeek v4 flash-tier
|
|
42
45
|
codestral: 0.3e-6,
|
|
43
46
|
"mistral-large": 2e-6,
|
|
44
47
|
"llama-3.1-405b": 1.33e-6,
|
|
45
48
|
"llama-3.1-70b": 0.8e-6,
|
|
46
49
|
"llama-3.1-8b": 0.05e-6,
|
|
50
|
+
// GLM models (zai-org) — approximate open-weights pricing
|
|
51
|
+
"zai-org/GLM-5.1-FP8": 0.15e-6,
|
|
52
|
+
"zai-org/GLM-4.7-Flash": 0.1e-6,
|
|
53
|
+
"hf:zai-org/GLM-4.7-Flash": 0.1e-6,
|
|
54
|
+
"ozore/mimo-v2.5-pro": 0.5e-6,
|
|
47
55
|
};
|
|
48
56
|
|
|
49
57
|
/**
|
package/src/vector-search.ts
CHANGED
|
@@ -64,9 +64,9 @@ function raptorSearchHits(
|
|
|
64
64
|
const embedder = store.embedder;
|
|
65
65
|
const record = store.record;
|
|
66
66
|
|
|
67
|
-
// S25 gate (a): honor
|
|
68
|
-
// built + persisted
|
|
69
|
-
//
|
|
67
|
+
// S25 gate (a): honor shadow mode at SERVE time. When RAPTOR_SHADOW_MODE=true,
|
|
68
|
+
// the tree is built + persisted but NOT merged into recall (transition/eval).
|
|
69
|
+
// Default is live: shadow mode is opt-in, not the default.
|
|
70
70
|
if (isShadowMode()) return [];
|
|
71
71
|
// S25 gate (b): freshness + fallback guards with per-session cache.
|
|
72
72
|
// The cache avoids O(n·leaves) rehydrate on every search when the tree
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{r as o,j as r,B as g}from"./index-CQjCLvv7.js";import{u as m}from"./useSSE-B6t44vzc.js";import{T as u}from"./toggle-KdBnFLu3.js";const p={compact_start:"ev-compact",compact_end:"ev-compact",compact_trigger:"ev-trigger",compact_skip:"ev-trigger",tier_changed:"ev-tier",model_changed:"ev-tier",pressure_lifted:"ev-tier",checkpoint_persisted:"ev-checkpoint",recall_inject:"ev-recall",anchors_updated:"ev-recall",config_updated:"ev-config",config_preset:"ev-config",crew_presence_changed:"ev-crew",crew_turn_changed:"ev-crew",crew_bandit_chosen:"ev-crew",session_sample:"ev-recall",game_ritual_start:"ev-game",game_ritual_stage:"ev-game",game_ritual_end:"ev-game",game_mode_changed:"ev-game",game_render:"ev-game"},_=["all","compact_start","compact_end","recall_inject","checkpoint_persisted"];function h(e){switch(e.type){case"compact_start":return`trigger=${e.trigger} session=${e.sessionId.slice(0,8)}`;case"compact_end":return`freed=${e.tokensFreed} ok=${e.success} cp=${e.checkpointId.slice(0,8)}`;case"compact_trigger":return`pressure=${e.pressure}% threshold=${e.threshold}% armed=${e.armed}`;case"compact_skip":return`reason=${e.reason}`;case"tier_changed":return`${e.from} → ${e.to} ctx=${e.contextPct}%`;case"model_changed":return`${e.providerName}/${e.model}`;case"pressure_lifted":return`${e.beforePct}% → ${e.afterPct}%`;case"checkpoint_persisted":return`cp=${e.checkpointId.slice(0,8)} sessionTok=${e.sessionTokens}`;case"recall_inject":return`q="${e.query.slice(0,40)}" chunks=${e.chunks} tok=${e.tokens}`;case"anchors_updated":return`count=${e.count} pinned=${e.pinned}`;case"config_updated":return`key=${e.key}`;case"config_preset":return`preset=${e.preset}`;case"crew_presence_changed":return`agents=${e.activeAgents} turn=${e.currentTurn}`;case"crew_turn_changed":return`turn=${e.turnIndex} agent=${e.agentName}`;case"crew_bandit_chosen":return`agent=${e.chosenAgent} score=${e.score} regret=${e.regret}`;case"session_sample":return`sess=${e.sessionId.slice(0,8)} tok=${e.tokens.toLocaleString()} ctx=${Math.round(e.percent)}%`;case"game_ritual_start":case"game_ritual_stage":case"game_ritual_end":case"game_mode_changed":case"game_render":return`stage=${e.type}`;default:return`event=${e.type}`}}function f(e){try{return new Date(e).toLocaleTimeString()}catch{return e}}function x({events:e}){const[t,n]=o.useState("all"),[a,i]=o.useState(null),l=o.useMemo(()=>(t==="all"?e:e.filter(c=>c.type===t)).slice(-200).reverse(),[e,t]);return r.jsxs("div",{className:"flex flex-col gap-3",children:[r.jsxs("div",{className:"flex flex-wrap items-center gap-2",role:"toolbar",children:[_.map(s=>r.jsx(u,{pressed:t===s,onClick:()=>n(s),children:s==="all"?"all":s.replace(/_/g," ")},s)),r.jsxs("span",{className:"text-xs text-muted-foreground",children:[e.length," buffered"]})]}),r.jsxs("ul",{className:"flex flex-col gap-1 font-mono text-xs",children:[l.length===0&&r.jsx("li",{className:"text-muted-foreground",children:"No events yet."}),l.map((s,c)=>{const d=p[s.type]??"ev-default";return r.jsxs("li",{className:`rounded-md px-2 py-1.5 transition-colors hover:bg-bg-elevated/40 ${d}`,onClick:()=>i(a===c?null:c),children:[r.jsx("span",{className:"ev-time",children:f(s.ts)})," ",r.jsx("span",{className:"ev-type",children:s.type})," ",r.jsx("span",{className:"ev-summary",children:h(s)}),a===c&&r.jsx("pre",{className:"mt-2 overflow-x-auto rounded-md bg-bg-elevated/60 p-2 text-xs",children:JSON.stringify(s,null,2)})]},`${s.ts}-${c}`)})]})]})}const $=["all","compact","recall","config","crew","game"];function j({active:e,onFilter:t}){return r.jsx("div",{className:"flex flex-wrap gap-2",role:"toolbar","aria-label":"Event category filter",children:$.map(n=>r.jsx(u,{pressed:e===n,onClick:()=>t(n),children:n},n))})}const w=new Set(["compact_start","compact_end","compact_trigger","compact_skip"]),k=new Set(["config_updated","config_preset","tier_changed","model_changed","pressure_lifted","anchors_updated","checkpoint_persisted"]),y=new Set(["recall_inject","hyde_executed","recall_metrics"]),S=new Set(["crew_presence_changed","crew_turn_changed","crew_bandit_chosen"]),E=new Set(["game_ritual_start","game_ritual_stage","game_ritual_end","game_mode_changed","game_render"]);function N(e,t){if(t==="all")return!0;const n=e.type;return t==="compact"?w.has(n):t==="recall"?y.has(n):t==="config"?k.has(n):t==="crew"?S.has(n):E.has(n)}function P(){const{events:e,status:t,eventCount:n}=m(),[a,i]=o.useState("all"),l=o.useMemo(()=>e.filter(d=>N(d,a)),[e,a]),s=t==="connected"?"success":t==="error"?"danger":t==="connecting"?"warning":"outline",c=t==="connected"?"connected":t==="connecting"?"connecting…":t==="error"?"error":"disconnected";return r.jsxs("div",{className:"flex flex-col gap-4",children:[r.jsxs("div",{className:"flex items-center justify-between",children:[r.jsxs(g,{variant:s,role:"status",children:[r.jsx("span",{className:"mr-1 inline-block h-1.5 w-1.5 rounded-full bg-current","aria-hidden":"true"}),c]}),r.jsxs("span",{className:"text-xs text-muted-foreground",children:[n," events received"]})]}),r.jsx(j,{active:a,onFilter:i}),r.jsx(x,{events:l})]})}export{P as default};
|
|
2
|
-
//# sourceMappingURL=EventsTab-Cyylo0of.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"EventsTab-Cyylo0of.js","sources":["../../src/components/EventStream.tsx","../../src/components/EventCategoryFilter.tsx","../../src/tabs/EventsTab.tsx"],"sourcesContent":["/**\n * dashboard-client/src/components/EventStream.tsx — SSE event list with filters.\n *\n * Type badge colored by event type. Timestamp + expandable detail row.\n * Type filter chips (all + per-type). Virtualization: manual windowing for\n * 500+ events (render last N visible).\n */\n\nimport type React from \"react\";\nimport { useState, useMemo } from \"react\";\nimport type { SseEvent } from \"@contracts\";\nimport { Toggle } from \"../components/ui/toggle\";\n\nexport interface EventStreamProps {\n\tevents: SseEvent[];\n}\n\nconst TYPE_COLORS: Record<string, string> = {\n\tcompact_start: \"ev-compact\",\n\tcompact_end: \"ev-compact\",\n\tcompact_trigger: \"ev-trigger\",\n\tcompact_skip: \"ev-trigger\",\n\ttier_changed: \"ev-tier\",\n\tmodel_changed: \"ev-tier\",\n\tpressure_lifted: \"ev-tier\",\n\tcheckpoint_persisted: \"ev-checkpoint\",\n\trecall_inject: \"ev-recall\",\n\tanchors_updated: \"ev-recall\",\n\tconfig_updated: \"ev-config\",\n\tconfig_preset: \"ev-config\",\n\tcrew_presence_changed: \"ev-crew\",\n\tcrew_turn_changed: \"ev-crew\",\n\tcrew_bandit_chosen: \"ev-crew\",\n\tsession_sample: \"ev-recall\",\n\tgame_ritual_start: \"ev-game\",\n\tgame_ritual_stage: \"ev-game\",\n\tgame_ritual_end: \"ev-game\",\n\tgame_mode_changed: \"ev-game\",\n\tgame_render: \"ev-game\",\n};\n\n// Filterable event types (spec: compact_start/end, recall_inject, checkpoint_persisted + all).\nconst FILTER_TYPES = [\n\t\"all\",\n\t\"compact_start\",\n\t\"compact_end\",\n\t\"recall_inject\",\n\t\"checkpoint_persisted\",\n] as const;\ntype FilterType = (typeof FILTER_TYPES)[number];\n\nconst RENDER_WINDOW = 200; // render last 200 to keep DOM light under 500+ events\n\nfunction summarize(ev: SseEvent): string {\n\tswitch (ev.type) {\n\t\tcase \"compact_start\":\n\t\t\treturn `trigger=${ev.trigger} session=${ev.sessionId.slice(0, 8)}`;\n\t\tcase \"compact_end\":\n\t\t\treturn `freed=${ev.tokensFreed} ok=${ev.success} cp=${ev.checkpointId.slice(0, 8)}`;\n\t\tcase \"compact_trigger\":\n\t\t\treturn `pressure=${ev.pressure}% threshold=${ev.threshold}% armed=${ev.armed}`;\n\t\tcase \"compact_skip\":\n\t\t\treturn `reason=${ev.reason}`;\n\t\tcase \"tier_changed\":\n\t\t\treturn `${ev.from} → ${ev.to} ctx=${ev.contextPct}%`;\n\t\tcase \"model_changed\":\n\t\t\treturn `${ev.providerName}/${ev.model}`;\n\t\tcase \"pressure_lifted\":\n\t\t\treturn `${ev.beforePct}% → ${ev.afterPct}%`;\n\t\tcase \"checkpoint_persisted\":\n\t\t\treturn `cp=${ev.checkpointId.slice(0, 8)} sessionTok=${ev.sessionTokens}`;\n\t\tcase \"recall_inject\":\n\t\t\treturn `q=\"${ev.query.slice(0, 40)}\" chunks=${ev.chunks} tok=${ev.tokens}`;\n\t\tcase \"anchors_updated\":\n\t\t\treturn `count=${ev.count} pinned=${ev.pinned}`;\n\t\tcase \"config_updated\":\n\t\t\treturn `key=${ev.key}`;\n\t\tcase \"config_preset\":\n\t\t\treturn `preset=${ev.preset}`;\n\t\tcase \"crew_presence_changed\":\n\t\t\treturn `agents=${ev.activeAgents} turn=${ev.currentTurn}`;\n\t\tcase \"crew_turn_changed\":\n\t\t\treturn `turn=${ev.turnIndex} agent=${ev.agentName}`;\n\t\tcase \"crew_bandit_chosen\":\n\t\t\treturn `agent=${ev.chosenAgent} score=${ev.score} regret=${ev.regret}`;\n\t\tcase \"session_sample\":\n\t\t\treturn `sess=${ev.sessionId.slice(0, 8)} tok=${ev.tokens.toLocaleString()} ctx=${Math.round(ev.percent)}%`;\n\t\tcase \"game_ritual_start\":\n\t\tcase \"game_ritual_stage\":\n\t\tcase \"game_ritual_end\":\n\t\tcase \"game_mode_changed\":\n\t\tcase \"game_render\":\n\t\t\treturn `stage=${ev.type}`;\n\t\tdefault:\n\t\t\treturn `event=${ev.type}`;\n\t}\n}\n\nfunction formatTs(ts: string): string {\n\ttry {\n\t\tconst d = new Date(ts);\n\t\treturn d.toLocaleTimeString();\n\t} catch {\n\t\treturn ts;\n\t}\n}\n\nexport function EventStream({ events }: EventStreamProps): React.ReactElement {\n\tconst [filter, setFilter] = useState<FilterType>(\"all\");\n\tconst [expanded, setExpanded] = useState<number | null>(null);\n\n\tconst filtered = useMemo(() => {\n\t\tconst list =\n\t\t\tfilter === \"all\" ? events : events.filter((e) => e.type === filter);\n\t\t// Newest first; render only the last RENDER_WINDOW to keep DOM light.\n\t\treturn list.slice(-RENDER_WINDOW).reverse();\n\t}, [events, filter]);\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-3\">\n\t\t\t<div className=\"flex flex-wrap items-center gap-2\" role=\"toolbar\">\n\t\t\t\t{FILTER_TYPES.map((t) => (\n\t\t\t\t\t<Toggle\n\t\t\t\t\t\tkey={t}\n\t\t\t\t\t\tpressed={filter === t}\n\t\t\t\t\t\tonClick={() => setFilter(t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t === \"all\" ? \"all\" : t.replace(/_/g, \" \")}\n\t\t\t\t\t</Toggle>\n\t\t\t\t))}\n\t\t\t\t<span className=\"text-xs text-muted-foreground\">{events.length} buffered</span>\n\t\t\t</div>\n\t\t\t<ul className=\"flex flex-col gap-1 font-mono text-xs\">\n\t\t\t\t{filtered.length === 0 && (\n\t\t\t\t\t<li className=\"text-muted-foreground\">No events yet.</li>\n\t\t\t\t)}\n\t\t\t\t{filtered.map((ev, idx) => {\n\t\t\t\t\tconst cls = TYPE_COLORS[ev.type] ?? \"ev-default\";\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<li\n\t\t\t\t\t\t\tkey={`${ev.ts}-${idx}`}\n\t\t\t\t\t\t\tclassName={`rounded-md px-2 py-1.5 transition-colors hover:bg-bg-elevated/40 ${cls}`}\n\t\t\t\t\t\t\tonClick={() => setExpanded(expanded === idx ? null : idx)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<span className=\"ev-time\">{formatTs(ev.ts)}</span>{\" \"}\n\t\t\t\t\t\t\t<span className=\"ev-type\">{ev.type}</span>{\" \"}\n\t\t\t\t\t\t\t<span className=\"ev-summary\">{summarize(ev)}</span>\n\t\t\t\t\t\t\t{expanded === idx && (\n\t\t\t\t\t\t\t\t<pre className=\"mt-2 overflow-x-auto rounded-md bg-bg-elevated/60 p-2 text-xs\">\n\t\t\t\t\t\t\t\t\t{JSON.stringify(ev, null, 2)}\n\t\t\t\t\t\t\t\t</pre>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</li>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</ul>\n\t\t</div>\n\t);\n}\n","/**\n * dashboard-client/src/components/EventCategoryFilter.tsx\n *\n * Category-level filter chips for the Events tab. Filters SSE events by\n * category: all / compact / recall / config / crew / game.\n */\n\nimport type React from \"react\";\nimport { Toggle } from \"../components/ui/toggle\";\n\nexport type EventCategory =\n\t| \"all\"\n\t| \"compact\"\n\t| \"recall\"\n\t| \"config\"\n\t| \"crew\"\n\t| \"game\";\n\nconst CATEGORIES: readonly EventCategory[] = [\n\t\"all\",\n\t\"compact\",\n\t\"recall\",\n\t\"config\",\n\t\"crew\",\n\t\"game\",\n] as const;\n\nexport interface EventCategoryFilterProps {\n\t/** Currently active category. */\n\tactive: EventCategory;\n\t/** Called when the user selects a category. */\n\tonFilter: (category: EventCategory) => void;\n}\n\nexport function EventCategoryFilter({\n\tactive,\n\tonFilter,\n}: EventCategoryFilterProps): React.ReactElement {\n\treturn (\n\t\t<div className=\"flex flex-wrap gap-2\" role=\"toolbar\" aria-label=\"Event category filter\">\n\t\t\t{CATEGORIES.map((cat) => (\n\t\t\t\t<Toggle\n\t\t\t\t\tkey={cat}\n\t\t\t\t\tpressed={active === cat}\n\t\t\t\t\tonClick={() => onFilter(cat)}\n\t\t\t\t>\n\t\t\t\t\t{cat}\n\t\t\t\t</Toggle>\n\t\t\t))}\n\t\t</div>\n\t);\n}\n","/**\n * dashboard-client/src/tabs/EventsTab.tsx — Events tab (C1).\n *\n * Live SSE event stream via useSSE + EventStream with category filter chips.\n * Shows connection status + event count. Category filter uses the existing\n * EventCategoryFilter component to filter by all/compact/recall/config/crew/game.\n */\n\nimport type React from \"react\";\nimport { useState, useMemo } from \"react\";\nimport type { SseEvent } from \"@contracts\";\nimport { useSSE } from \"../hooks/useSSE\";\nimport { EventStream } from \"../components/EventStream\";\nimport {\n\tEventCategoryFilter,\n\ttype EventCategory,\n} from \"../components/EventCategoryFilter\";\nimport { Badge } from \"../components/ui/badge\";\n\nconst COMPACT_TYPES = new Set([\n\t\"compact_start\",\n\t\"compact_end\",\n\t\"compact_trigger\",\n\t\"compact_skip\",\n]);\nconst CONFIG_TYPES = new Set([\n\t\"config_updated\",\n\t\"config_preset\",\n\t\"tier_changed\",\n\t\"model_changed\",\n\t\"pressure_lifted\",\n\t\"anchors_updated\",\n\t\"checkpoint_persisted\",\n]);\nconst RECALL_TYPES = new Set([\n\t\"recall_inject\",\n\t\"hyde_executed\",\n\t\"recall_metrics\",\n]);\nconst CREW_TYPES = new Set([\n\t\"crew_presence_changed\",\n\t\"crew_turn_changed\",\n\t\"crew_bandit_chosen\",\n]);\nconst GAME_TYPES = new Set([\n\t\"game_ritual_start\",\n\t\"game_ritual_stage\",\n\t\"game_ritual_end\",\n\t\"game_mode_changed\",\n\t\"game_render\",\n]);\n\nfunction matchesCategory(ev: SseEvent, cat: EventCategory): boolean {\n\tif (cat === \"all\") return true;\n\tconst t = ev.type;\n\tif (cat === \"compact\") return COMPACT_TYPES.has(t);\n\tif (cat === \"recall\") return RECALL_TYPES.has(t);\n\tif (cat === \"config\") return CONFIG_TYPES.has(t);\n\tif (cat === \"crew\") return CREW_TYPES.has(t);\n\treturn GAME_TYPES.has(t); // cat === \"game\"\n}\n\nexport default function EventsTab(): React.ReactElement {\n\tconst { events, status, eventCount } = useSSE();\n\tconst [category, setCategory] = useState<EventCategory>(\"all\");\n\n\tconst filtered = useMemo(\n\t\t() => events.filter((e) => matchesCategory(e, category)),\n\t\t[events, category],\n\t);\n\n\tconst statusVariant =\n\t\tstatus === \"connected\"\n\t\t\t? (\"success\" as const)\n\t\t\t: status === \"error\"\n\t\t\t\t? (\"danger\" as const)\n\t\t\t\t: status === \"connecting\"\n\t\t\t\t\t? (\"warning\" as const)\n\t\t\t\t\t: (\"outline\" as const);\n\tconst statusLabel =\n\t\tstatus === \"connected\"\n\t\t\t? \"connected\"\n\t\t\t: status === \"connecting\"\n\t\t\t\t? \"connecting…\"\n\t\t\t\t: status === \"error\"\n\t\t\t\t\t? \"error\"\n\t\t\t\t\t: \"disconnected\";\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t<div className=\"flex items-center justify-between\">\n\t\t\t\t<Badge variant={statusVariant} role=\"status\">\n\t\t\t\t\t<span className=\"mr-1 inline-block h-1.5 w-1.5 rounded-full bg-current\" aria-hidden=\"true\" />\n\t\t\t\t\t{statusLabel}\n\t\t\t\t</Badge>\n\t\t\t\t<span className=\"text-xs text-muted-foreground\">\n\t\t\t\t\t{eventCount} events received\n\t\t\t\t</span>\n\t\t\t</div>\n\t\t\t<EventCategoryFilter active={category} onFilter={setCategory} />\n\t\t\t<EventStream events={filtered} />\n\t\t</div>\n\t);\n}\n"],"names":["TYPE_COLORS","FILTER_TYPES","summarize","ev","formatTs","ts","EventStream","events","filter","setFilter","useState","expanded","setExpanded","filtered","useMemo","e","jsxs","t","jsx","Toggle","idx","cls","CATEGORIES","EventCategoryFilter","active","onFilter","cat","COMPACT_TYPES","CONFIG_TYPES","RECALL_TYPES","CREW_TYPES","GAME_TYPES","matchesCategory","EventsTab","status","eventCount","useSSE","category","setCategory","statusVariant","statusLabel","Badge"],"mappings":"wIAiBA,MAAMA,EAAsC,CAC3C,cAAe,aACf,YAAa,aACb,gBAAiB,aACjB,aAAc,aACd,aAAc,UACd,cAAe,UACf,gBAAiB,UACjB,qBAAsB,gBACtB,cAAe,YACf,gBAAiB,YACjB,eAAgB,YAChB,cAAe,YACf,sBAAuB,UACvB,kBAAmB,UACnB,mBAAoB,UACpB,eAAgB,YAChB,kBAAmB,UACnB,kBAAmB,UACnB,gBAAiB,UACjB,kBAAmB,UACnB,YAAa,SACd,EAGMC,EAAe,CACpB,MACA,gBACA,cACA,gBACA,sBACD,EAKA,SAASC,EAAUC,EAAsB,CACxC,OAAQA,EAAG,KAAA,CACV,IAAK,gBACJ,MAAO,WAAWA,EAAG,OAAO,YAAYA,EAAG,UAAU,MAAM,EAAG,CAAC,CAAC,GACjE,IAAK,cACJ,MAAO,SAASA,EAAG,WAAW,OAAOA,EAAG,OAAO,OAAOA,EAAG,aAAa,MAAM,EAAG,CAAC,CAAC,GAClF,IAAK,kBACJ,MAAO,YAAYA,EAAG,QAAQ,eAAeA,EAAG,SAAS,WAAWA,EAAG,KAAK,GAC7E,IAAK,eACJ,MAAO,UAAUA,EAAG,MAAM,GAC3B,IAAK,eACJ,MAAO,GAAGA,EAAG,IAAI,MAAMA,EAAG,EAAE,QAAQA,EAAG,UAAU,IAClD,IAAK,gBACJ,MAAO,GAAGA,EAAG,YAAY,IAAIA,EAAG,KAAK,GACtC,IAAK,kBACJ,MAAO,GAAGA,EAAG,SAAS,OAAOA,EAAG,QAAQ,IACzC,IAAK,uBACJ,MAAO,MAAMA,EAAG,aAAa,MAAM,EAAG,CAAC,CAAC,eAAeA,EAAG,aAAa,GACxE,IAAK,gBACJ,MAAO,MAAMA,EAAG,MAAM,MAAM,EAAG,EAAE,CAAC,YAAYA,EAAG,MAAM,QAAQA,EAAG,MAAM,GACzE,IAAK,kBACJ,MAAO,SAASA,EAAG,KAAK,WAAWA,EAAG,MAAM,GAC7C,IAAK,iBACJ,MAAO,OAAOA,EAAG,GAAG,GACrB,IAAK,gBACJ,MAAO,UAAUA,EAAG,MAAM,GAC3B,IAAK,wBACJ,MAAO,UAAUA,EAAG,YAAY,SAASA,EAAG,WAAW,GACxD,IAAK,oBACJ,MAAO,QAAQA,EAAG,SAAS,UAAUA,EAAG,SAAS,GAClD,IAAK,qBACJ,MAAO,SAASA,EAAG,WAAW,UAAUA,EAAG,KAAK,WAAWA,EAAG,MAAM,GACrE,IAAK,iBACJ,MAAO,QAAQA,EAAG,UAAU,MAAM,EAAG,CAAC,CAAC,QAAQA,EAAG,OAAO,gBAAgB,QAAQ,KAAK,MAAMA,EAAG,OAAO,CAAC,IACxG,IAAK,oBACL,IAAK,oBACL,IAAK,kBACL,IAAK,oBACL,IAAK,cACJ,MAAO,SAASA,EAAG,IAAI,GACxB,QACC,MAAO,SAASA,EAAG,IAAI,EAAA,CAE1B,CAEA,SAASC,EAASC,EAAoB,CACrC,GAAI,CAEH,OADU,IAAI,KAAKA,CAAE,EACZ,mBAAA,CACV,MAAQ,CACP,OAAOA,CACR,CACD,CAEO,SAASC,EAAY,CAAE,OAAAC,GAAgD,CAC7E,KAAM,CAACC,EAAQC,CAAS,EAAIC,EAAAA,SAAqB,KAAK,EAChD,CAACC,EAAUC,CAAW,EAAIF,EAAAA,SAAwB,IAAI,EAEtDG,EAAWC,EAAAA,QAAQ,KAEvBN,IAAW,MAAQD,EAASA,EAAO,OAAQQ,GAAMA,EAAE,OAASP,CAAM,GAEvD,MAAM,IAAc,EAAE,QAAA,EAChC,CAACD,EAAQC,CAAM,CAAC,EAEnB,OACCQ,EAAAA,KAAC,MAAA,CAAI,UAAU,sBACd,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,oCAAoC,KAAK,UACtD,SAAA,CAAAf,EAAa,IAAKgB,GAClBC,EAAAA,IAACC,EAAA,CAEA,QAASX,IAAWS,EACpB,QAAS,IAAMR,EAAUQ,CAAC,EAEzB,aAAM,MAAQ,MAAQA,EAAE,QAAQ,KAAM,GAAG,CAAA,EAJrCA,CAAA,CAMN,EACDD,EAAAA,KAAC,OAAA,CAAK,UAAU,gCAAiC,SAAA,CAAAT,EAAO,OAAO,WAAA,CAAA,CAAS,CAAA,EACzE,EACAS,EAAAA,KAAC,KAAA,CAAG,UAAU,wCACZ,SAAA,CAAAH,EAAS,SAAW,GACpBK,MAAC,KAAA,CAAG,UAAU,wBAAwB,SAAA,iBAAc,EAEpDL,EAAS,IAAI,CAACV,EAAIiB,IAAQ,CAC1B,MAAMC,EAAMrB,EAAYG,EAAG,IAAI,GAAK,aACpC,OACCa,EAAAA,KAAC,KAAA,CAEA,UAAW,oEAAoEK,CAAG,GAClF,QAAS,IAAMT,EAAYD,IAAaS,EAAM,KAAOA,CAAG,EAExD,SAAA,CAAAF,MAAC,QAAK,UAAU,UAAW,SAAAd,EAASD,EAAG,EAAE,EAAE,EAAQ,IACnDe,EAAAA,IAAC,OAAA,CAAK,UAAU,UAAW,WAAG,KAAK,EAAQ,UAC1C,OAAA,CAAK,UAAU,aAAc,SAAAhB,EAAUC,CAAE,EAAE,EAC3CQ,IAAaS,GACbF,EAAAA,IAAC,MAAA,CAAI,UAAU,gEACb,SAAA,KAAK,UAAUf,EAAI,KAAM,CAAC,CAAA,CAC5B,CAAA,CAAA,EAVI,GAAGA,EAAG,EAAE,IAAIiB,CAAG,EAAA,CAcvB,CAAC,CAAA,CAAA,CACF,CAAA,EACD,CAEF,CC5IA,MAAME,EAAuC,CAC5C,MACA,UACA,SACA,SACA,OACA,MACD,EASO,SAASC,EAAoB,CACnC,OAAAC,EACA,SAAAC,CACD,EAAiD,CAChD,OACCP,EAAAA,IAAC,MAAA,CAAI,UAAU,uBAAuB,KAAK,UAAU,aAAW,wBAC9D,SAAAI,EAAW,IAAKI,GAChBR,EAAAA,IAACC,EAAA,CAEA,QAASK,IAAWE,EACpB,QAAS,IAAMD,EAASC,CAAG,EAE1B,SAAAA,CAAA,EAJIA,CAAA,CAMN,EACF,CAEF,CChCA,MAAMC,MAAoB,IAAI,CAC7B,gBACA,cACA,kBACA,cACD,CAAC,EACKC,MAAmB,IAAI,CAC5B,iBACA,gBACA,eACA,gBACA,kBACA,kBACA,sBACD,CAAC,EACKC,MAAmB,IAAI,CAC5B,gBACA,gBACA,gBACD,CAAC,EACKC,MAAiB,IAAI,CAC1B,wBACA,oBACA,oBACD,CAAC,EACKC,MAAiB,IAAI,CAC1B,oBACA,oBACA,kBACA,oBACA,aACD,CAAC,EAED,SAASC,EAAgB7B,EAAcuB,EAA6B,CACnE,GAAIA,IAAQ,MAAO,MAAO,GAC1B,MAAMT,EAAId,EAAG,KACb,OAAIuB,IAAQ,UAAkBC,EAAc,IAAIV,CAAC,EAC7CS,IAAQ,SAAiBG,EAAa,IAAIZ,CAAC,EAC3CS,IAAQ,SAAiBE,EAAa,IAAIX,CAAC,EAC3CS,IAAQ,OAAeI,EAAW,IAAIb,CAAC,EACpCc,EAAW,IAAId,CAAC,CACxB,CAEA,SAAwBgB,GAAgC,CACvD,KAAM,CAAE,OAAA1B,EAAQ,OAAA2B,EAAQ,WAAAC,CAAA,EAAeC,EAAA,EACjC,CAACC,EAAUC,CAAW,EAAI5B,EAAAA,SAAwB,KAAK,EAEvDG,EAAWC,EAAAA,QAChB,IAAMP,EAAO,OAAQQ,GAAMiB,EAAgBjB,EAAGsB,CAAQ,CAAC,EACvD,CAAC9B,EAAQ8B,CAAQ,CAAA,EAGZE,EACLL,IAAW,YACP,UACDA,IAAW,QACT,SACDA,IAAW,aACT,UACA,UACDM,EACLN,IAAW,YACR,YACAA,IAAW,aACV,cACAA,IAAW,QACV,QACA,eAEN,OACClB,EAAAA,KAAC,MAAA,CAAI,UAAU,sBACd,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACd,SAAA,CAAAA,EAAAA,KAACyB,EAAA,CAAM,QAASF,EAAe,KAAK,SACnC,SAAA,CAAArB,EAAAA,IAAC,OAAA,CAAK,UAAU,wDAAwD,cAAY,OAAO,EAC1FsB,CAAA,EACF,EACAxB,EAAAA,KAAC,OAAA,CAAK,UAAU,gCACd,SAAA,CAAAmB,EAAW,kBAAA,CAAA,CACb,CAAA,EACD,EACAjB,EAAAA,IAACK,EAAA,CAAoB,OAAQc,EAAU,SAAUC,EAAa,EAC9DpB,EAAAA,IAACZ,EAAA,CAAY,OAAQO,CAAA,CAAU,CAAA,EAChC,CAEF"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{j as e,r as i,X as B}from"./index-CQjCLvv7.js";import{T as I}from"./toggle-KdBnFLu3.js";const T={checkpoint:"#6366f1",turn:"#58a6ff","turn-content":"#22c55e",memory:"#f59e0b"},z={checkpoint:"Checkpoint",turn:"Turn","turn-content":"Turn Content",memory:"Memory"};function U(t,n){return`M 0,-${n} L ${t},0 L 0,${n} L -${t},0 Z`}function Y(t){return!t||t==="active"?1:.5}function Q(t,n,c,d,s,u,a){const p=u?T[d]??"#6366f1":"#d1d5db",m=s?"#ef4444":"none",h=Y(a);switch(d){case"checkpoint":return e.jsx("circle",{cx:t,cy:n,r:s?c+3:c,fill:p,opacity:h,stroke:m,strokeWidth:s?2:0});case"turn":return e.jsx("circle",{cx:t,cy:n,r:s?c+3:c,fill:"none",stroke:p,strokeWidth:2.5,opacity:h});case"turn-content":return e.jsxs("g",{children:[e.jsx("circle",{cx:t,cy:n,r:s?c+3:c,fill:"none",stroke:p,strokeWidth:2.5,opacity:h}),e.jsx("circle",{cx:t,cy:n,r:Math.max(3,c*.3),fill:p,opacity:h})]});case"memory":const g=c*.85,j=c*.85;return e.jsx("path",{d:U(g,j),transform:`translate(${t}, ${n})`,fill:p,opacity:h,stroke:m,strokeWidth:s?2:0})}}const X=5e3,P=.005,O=.01,D=.9,Z=.1,L=50;function J(t){const n=t.nodes.map((s,u)=>{const a=2*Math.PI*u/Math.max(t.nodes.length,1),p=200;return{...s,pos:{x:Math.cos(a)*p+300,y:Math.sin(a)*p+200},vx:0,vy:0,pinned:!1}}),c=new Map;n.forEach((s,u)=>c.set(s.id,u));const d=t.edges.map(s=>{const u=c.get(s.source),a=c.get(s.target);return u===void 0||a===void 0||u===a?null:{source:u,target:a,weight:s.weight,type:s.type}}).filter(s=>s!==null);return{nodes:n,edges:d}}function K(t){const{nodes:n,edges:c}=t,d=n.length;if(d!==0)for(let s=0;s<d;s++){if(n[s].pinned)continue;let u=0,a=0;for(let m=0;m<d;m++){if(s===m)continue;const h=n[s].pos.x-n[m].pos.x,g=n[s].pos.y-n[m].pos.y,j=h*h+g*g||1,v=X/j,b=Math.sqrt(j);u+=h/b*v,a+=g/b*v}for(const m of c){let h;if(m.source===s)h=m.target;else if(m.target===s)h=m.source;else continue;const g=n[h].pos.x-n[s].pos.x,j=n[h].pos.y-n[s].pos.y;u+=g*P*m.weight,a+=j*P*m.weight}u-=n[s].pos.x*O,a-=n[s].pos.y*O,n[s].vx=(n[s].vx+u)*D,n[s].vy=(n[s].vy+a)*D;const p=Math.sqrt(n[s].vx*n[s].vx+n[s].vy*n[s].vy);p>L&&(n[s].vx=n[s].vx/p*L,n[s].vy=n[s].vy/p*L),p>Z&&(n[s].pos.x+=n[s].vx,n[s].pos.y+=n[s].vy)}}const ee=300,te=.3,k=900,w=600,x=40;function M(t){switch(t){case"temporal":return"#6366f1";case"semantic":return"#22c55e";case"raptor_parent":return"#f59e0b"}}const N=({color:t,shape:n,label:c})=>{const d={display:"inline-block",width:"10px",height:"10px",verticalAlign:"middle",marginRight:"3px",borderRadius:n.startsWith("hollow")||n==="filled-circle"?"50%":void 0};let s;return n==="line"?e.jsx("span",{style:{color:t,marginRight:"6px"},children:c}):(n==="filled-circle"?s=e.jsx("span",{style:{...d,backgroundColor:t}}):n==="hollow-circle"?s=e.jsx("span",{style:{...d,border:`2px solid ${t}`,backgroundColor:"transparent"}}):n==="hollow-ring"?s=e.jsx("span",{style:{...d,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"}})}):s=e.jsx("span",{style:{...d,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:[s,c]})," "]}))},re=()=>{const[t,n]=i.useState(null),[c,d]=i.useState(!0),[s,u]=i.useState(null),[a,p]=i.useState(null),[m,h]=i.useState(""),[g]=i.useState(""),[j,v]=i.useState(0),b=i.useRef(null),S=i.useRef(0);i.useEffect(()=>{let r=!1;const o=new URLSearchParams;return g&&o.set("sessionId",g),o.set("threshold","0.7"),o.set("maxEdgesPerNode","4"),d(!0),u(null),fetch(`/api/memory-map?${o.toString()}`).then(l=>{if(!l.ok)throw new Error(`HTTP ${l.status}`);return l.json()}).then(l=>{r||(n(l),b.current=J(l),v(1),d(!1))}).catch(l=>{r||(u(l instanceof Error?l.message:"Unknown error"),d(!1))}),()=>{r=!0,cancelAnimationFrame(S.current)}},[g]),i.useEffect(()=>{if(!b.current||j===0)return;const r=b.current;let o=0;const l=()=>{o>=ee||(K(r),o++,v(o),S.current=requestAnimationFrame(l))};return S.current=requestAnimationFrame(l),()=>cancelAnimationFrame(S.current)},[j]);const W=i.useCallback((r,o)=>{const l=b.current;l&&(l.nodes[o].pinned=!l.nodes[o].pinned,l.nodes[o].pinned||(l.nodes[o].vx=0,l.nodes[o].vy=0),p(f=>f?.id===r.id?null:r),v(f=>f+1))},[]),$=i.useMemo(()=>{const r=b.current;if(!r||!m)return null;const o=m.toLowerCase();return new Set(r.nodes.map((l,f)=>l.summaryTruncated.toLowerCase().includes(o)||l.label.toLowerCase().includes(o)?f:-1).filter(l=>l>=0))},[m]),R=i.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]),F={green:"#22c55e",yellow:"#eab308",red:"#ef4444"},G=i.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]),A=i.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]),H=i.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(c)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(s)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: ",s]}),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||!b.current||H)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 y=b.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:m,onInput:r=>h(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:G})," · ",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:F[R.level]??"#6b7280"},title:`Validation: ${R.label}`,children:R.level==="green"?"Healthy":R.level==="yellow"?"Warnings":"Critical"})]}),A?e.jsx("div",{className:"text-[11px] text-muted-foreground",children:A}):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:T.checkpoint,shape:"filled-circle",label:"Checkpoint"}),e.jsx(N,{type:"node",color:T.turn,shape:"hollow-circle",label:"Turn"}),e.jsx(N,{type:"node",color:T["turn-content"],shape:"hollow-ring",label:"Turn Content"}),e.jsx(N,{type:"node",color:T.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:[y.edges.map((r,o)=>{const l=y.nodes[r.source],f=y.nodes[r.target],C=M(r.type),E=Math.max(1,r.weight*2.5);return e.jsx("line",{x1:x+l.pos.x/(y.nodes.length||1)*(k-2*x),y1:x+l.pos.y/(y.nodes.length||1)*(w-2*x),x2:x+f.pos.x/(y.nodes.length||1)*(k-2*x),y2:x+f.pos.y/(y.nodes.length||1)*(w-2*x),stroke:C,strokeWidth:E,opacity:te},`edge-${o}`)}),y.nodes.map((r,o)=>{const l=x+r.pos.x/(y.nodes.length||1)*(k-2*x),f=x+r.pos.y/(y.nodes.length||1)*(w-2*x),C=Math.min(20,8+r.tokenEstimate/500),E=$?$.has(o):!0,q=a?.id===r.id,V=r.label.length>20?r.label.slice(0,18)+"...":r.label;return e.jsxs("g",{className:"memory-map-node-group",onClick:()=>W(r,o),style:{cursor:"pointer"},children:[Q(l,f,C,r.nodeType,q,E,r.dedupStatus),e.jsx("text",{x:l,y:f+C+12,textAnchor:"middle",fontSize:"9px",fill:"#374151",className:"memory-map-label",children:V})]},`node-${o}`)})]}),a?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:z[a.nodeType]}),a.label]}),e.jsx("p",{className:"mt-1",children:a.summaryTruncated}),a.topicSummary?e.jsxs("p",{className:"mt-1",children:["Topic: ",a.topicSummary]}):null,e.jsxs("p",{className:"mt-1",children:["Tokens: ",a.tokenEstimate," | Decisions: ",a.decisionCount]}),e.jsxs("p",{children:["Session: ",a.sessionId]}),e.jsxs("p",{children:["Raptor Level: ",a.raptorLevel]}),e.jsx("p",{className:"mt-1 text-muted-foreground",children:a.textSnippet})]}):null]})};function se(t){return t===0?"#d4a017":t===1?"#3b82f6":"#14b8a6"}function _(t){return t?new Date(t).toLocaleString():"—"}function ne({node:t}){const n=se(t.level),c=t.children.length>0?`${t.children.length} child${t.children.length===1?"":"ren"}`:"leaf";return e.jsxs("div",{style:{background:"#14142b",border:`1px solid ${n}`,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:n,color:"#fff",borderRadius:"10px",padding:"1px 8px",fontSize:"11px",fontWeight:600},children:["L",t.level]}),e.jsxs("span",{style:{fontSize:"12px",color:"#6b7280"},children:[c," · ",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 oe(){const[t,n]=i.useState(null),[c,d]=i.useState(!0),[s,u]=i.useState(null);return i.useEffect(()=>{let a=!1;return d(!0),u(null),B().then(p=>{a||(n(p),d(!1))}).catch(p=>{a||(u(p instanceof Error?p.message:"Unknown error"),d(!1))}),()=>{a=!0}},[]),c?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..."}):s?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: ",s]})}):!t||t.empty||t.nodes.length===0?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)."})}):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)]})]}),t.nodes.map(a=>e.jsx(ne,{node:a},a.id))]})}const ce=()=>{const[t,n]=i.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(I,{pressed:t==="map",onClick:()=>n("map"),"aria-label":"Memory Map view",children:"Memory Map"}),e.jsx(I,{pressed:t==="raptor",onClick:()=>n("raptor"),"aria-label":"RAPTOR Tree view",children:"RAPTOR Tree"})]}),t==="map"&&e.jsx(re,{}),t==="raptor"&&e.jsx(oe,{})]})};export{ce as default};
|
|
2
|
-
//# sourceMappingURL=MemoryMapTab-DHUdZ7RR.js.map
|