pi-mega-compact 0.11.1 → 0.11.2
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/endpoints.js +19 -0
- package/dist/extensions/dashboard-server/api-contracts/maintenance.js +7 -0
- package/dist/extensions/dashboard-server/api-contracts.test.js +1 -1
- package/dist/extensions/dashboard-server/routes-maintenance.js +293 -0
- package/dist/extensions/dashboard-server/routes.js +1 -0
- package/dist/extensions/dashboard-server/server.js +3 -1
- package/dist/src/store/sqlite/maintenance.js +20 -1
- package/extensions/dashboard-client/dist/assets/{AchievementTiles-DZp_xQOW.js → AchievementTiles-Cml6YC8w.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{AchievementTiles-DZp_xQOW.js.map → AchievementTiles-Cml6YC8w.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{AchievementsTab-BzFHpAHM.js → AchievementsTab-B8NqDt7I.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{AchievementsTab-BzFHpAHM.js.map → AchievementsTab-B8NqDt7I.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{CacheTab-DEQbTq2T.js → CacheTab-BCLzVL4S.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{CacheTab-DEQbTq2T.js.map → CacheTab-BCLzVL4S.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{ConfigTab-DQ4FG33J.js → ConfigTab-CBYvp2mV.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{ConfigTab-DQ4FG33J.js.map → ConfigTab-CBYvp2mV.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{EventsTab-D5HoEVYo.js → EventsTab-DlTJqiDm.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{EventsTab-D5HoEVYo.js.map → EventsTab-DlTJqiDm.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{GameTab-Jzsc4yeY.js → GameTab-DkGTqKJW.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{GameTab-Jzsc4yeY.js.map → GameTab-DkGTqKJW.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/MaintenanceTab-Cw43zmUx.js +2 -0
- package/extensions/dashboard-client/dist/assets/MaintenanceTab-Cw43zmUx.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{MetricsTab-D_XnsEYX.js → MetricsTab-BFo7pKM-.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MetricsTab-D_XnsEYX.js.map → MetricsTab-BFo7pKM-.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{OverviewTab-BMREvAth.js → OverviewTab-CClCUd3-.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{OverviewTab-BMREvAth.js.map → OverviewTab-CClCUd3-.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{ReposTab-DuyhOktG.js → ReposTab-_3R4RSLZ.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{ReposTab-DuyhOktG.js.map → ReposTab-_3R4RSLZ.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SessionsTab-mz_vz8i2.js → SessionsTab-CCYd-kSz.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SessionsTab-mz_vz8i2.js.map → SessionsTab-CCYd-kSz.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-B8AIjNTY.js → TimeSavedCard-0TqsrY6y.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-B8AIjNTY.js.map → TimeSavedCard-0TqsrY6y.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TopicsTab-DKuct4oD.js → TopicsTab-DRLJmVv0.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TopicsTab-DKuct4oD.js.map → TopicsTab-DRLJmVv0.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TurnsTab-11MGLxY8.js → TurnsTab-CLNM0T5R.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TurnsTab-11MGLxY8.js.map → TurnsTab-CLNM0T5R.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{index-CqLN7STl.js → index-BcoSz-L4.js} +10 -10
- package/extensions/dashboard-client/dist/assets/{index-CqLN7STl.js.map → index-BcoSz-L4.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{useSSE-CXrQSbVY.js → useSSE-Cezlih5V.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{useSSE-CXrQSbVY.js.map → useSSE-Cezlih5V.js.map} +1 -1
- package/extensions/dashboard-client/dist/index.html +1 -1
- package/extensions/dashboard-client/src/App.tsx +5 -1
- package/extensions/dashboard-client/src/api/client.ts +23 -0
- package/extensions/dashboard-client/src/tabs/MaintenanceTab.tsx +293 -0
- package/extensions/dashboard-server/api-contracts/endpoints.ts +30 -0
- package/extensions/dashboard-server/api-contracts/index.ts +12 -0
- package/extensions/dashboard-server/api-contracts/maintenance.ts +84 -0
- package/extensions/dashboard-server/api-contracts.test.ts +1 -1
- package/extensions/dashboard-server/api-contracts.ts +9 -0
- package/extensions/dashboard-server/routes-maintenance.ts +345 -0
- package/extensions/dashboard-server/routes.ts +1 -0
- package/extensions/dashboard-server/server.ts +2 -0
- package/package.json +1 -1
- package/src/store/sqlite/maintenance.ts +20 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{j as e}from"./index-
|
|
2
|
-
//# sourceMappingURL=TimeSavedCard-
|
|
1
|
+
import{j as e}from"./index-BcoSz-L4.js";function l(a){const t=a??0;return t>=1048576?`${(t/1048576).toFixed(1)} MiB`:t>=1024?`${(t/1024).toFixed(1)} KiB`:`${t} B`}function n(a){const t=a??0;return t>=3600?`${(t/3600).toFixed(1)}h`:t>=60?`${Math.round(t/60)}m`:t>=1?`${t.toFixed(1)}s`:`${Math.round(t*1e3)}ms`}function r(a){const c=(a??0)*100;return c>=10?`${Math.round(c)}%`:`${c.toFixed(1)}%`}function s({label:a,value:t}){return e.jsxs("div",{className:"ov-stat-row",children:[e.jsx("span",{className:"ov-stat-label",children:a}),e.jsx("span",{className:"ov-stat-value",children:t})]})}function u(a){return e.jsxs("div",{className:"card cache-hits-card",children:[e.jsx("h3",{children:"💾 Cache Hits & Compactions"}),e.jsx(s,{label:"Cache Hits (session)",value:a.cacheHitsSession.toLocaleString()}),e.jsx(s,{label:"Cache Hits (total)",value:a.cacheHitsTotal.toLocaleString()}),e.jsx(s,{label:"Tokens Saved (session)",value:a.tokensSavedSession.toLocaleString()}),e.jsx(s,{label:"Tokens Saved (total)",value:a.tokensSavedTotal.toLocaleString()}),e.jsx(s,{label:"Compactions (session)",value:a.compactionsSession.toLocaleString()}),e.jsx(s,{label:"Compactions (total)",value:a.compactionsTotal.toLocaleString()})]})}function o({label:a,value:t}){return e.jsxs("div",{className:"ov-stat-row",children:[e.jsx("span",{className:"ov-stat-label",children:a}),e.jsx("span",{className:"ov-stat-value",children:t})]})}function d(a){return e.jsxs("div",{className:"card time-saved-card",children:[e.jsx("h3",{children:"⏱ Time Saved (est.)"}),e.jsx(o,{label:"Compact (session)",value:n(a.compactSessionSec)}),e.jsx(o,{label:"Compact (total)",value:n(a.compactTotalSec)}),e.jsx(o,{label:"Cache Hit (session)",value:n(a.cacheHitSessionSec)}),e.jsx(o,{label:"Cache Hit (total)",value:n(a.cacheHitTotalSec)})]})}export{u as C,d as T,l as a,r as f};
|
|
2
|
+
//# sourceMappingURL=TimeSavedCard-0TqsrY6y.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimeSavedCard-
|
|
1
|
+
{"version":3,"file":"TimeSavedCard-0TqsrY6y.js","sources":["../../src/utils/format.ts","../../src/components/CacheHitsCard.tsx","../../src/components/TimeSavedCard.tsx"],"sourcesContent":["/**\n * dashboard-client/src/utils/format.ts — shared formatting helpers.\n *\n * Mirrors the format functions from the old static dashboard (html.ts)\n * so the React rewrite shows identical values.\n */\n\n/** Format bytes as KiB/MiB/B (matches html.ts fmtBytes). */\nexport function fmtBytes(b: number | null | undefined): string {\n\tconst n = b ?? 0;\n\tif (n >= 1_048_576) return `${(n / 1_048_576).toFixed(1)} MiB`;\n\tif (n >= 1024) return `${(n / 1024).toFixed(1)} KiB`;\n\treturn `${n} B`;\n}\n\n/** Format seconds as h/m/s/ms (matches html.ts fmtSec). */\nexport function fmtSec(s: number | null | undefined): string {\n\tconst n = s ?? 0;\n\tif (n >= 3600) return `${(n / 3600).toFixed(1)}h`;\n\tif (n >= 60) return `${Math.round(n / 60)}m`;\n\tif (n >= 1) return `${n.toFixed(1)}s`;\n\treturn `${Math.round(n * 1000)}ms`;\n}\n\n/**\n * Display a 0–1 fraction as a percentage string.\n * Uses one decimal place below 10%, rounded above (matches html.ts pct logic).\n */\nexport function fmtPctFromFraction(\n\tv: number | null | undefined,\n): string {\n\tconst n = v ?? 0;\n\tconst pct = n * 100;\n\tif (pct >= 10) return `${Math.round(pct)}%`;\n\treturn `${pct.toFixed(1)}%`;\n}\n\n/** Round a 0–1 fraction to a one-decimal percentage (for trophy values). */\nexport function fmtPct(v: number | null | undefined): string {\n\tconst n = v ?? 0;\n\treturn `${Math.round(n * 10) / 10}%`;\n}\n\n/** Format milliseconds (matches html.ts fmtMs). */\nexport function fmtMs(v: number | null | undefined): string {\n\tif (v == null) return \"\\u2014\";\n\treturn v >= 100 ? `${Math.round(v)}ms` : `${v.toFixed(1)}ms`;\n}\n\n/** Format a number with fixed decimals or em-dash for null (matches fmtNum). */\nexport function fmtNum(\n\tv: number | null | undefined,\n\tdec: number,\n): string {\n\tif (v == null || typeof v !== \"number\") return \"\\u2014\";\n\treturn v.toFixed(dec);\n}\n\n/** Collapse an array of numbers into a range string or single value. */\nexport function collapseNum(samples: number[]): string {\n\tif (samples.length === 0) return \"\\u2014\";\n\tconst lo = Math.min(...samples);\n\tconst hi = Math.max(...samples);\n\tif (lo === hi) return lo.toLocaleString();\n\treturn `${lo.toLocaleString()}\\u2013${hi.toLocaleString()}`;\n}\n\n/** Collapse an array of rates into a range string or single value. */\nexport function collapseRate(samples: number[]): string {\n\tif (samples.length === 0) return \"\\u2014\";\n\tconst lo = Math.min(...samples);\n\tconst hi = Math.max(...samples);\n\tif (lo === hi) return `$${lo.toFixed(6)}`;\n\treturn `$${lo.toFixed(6)}\\u2013$${hi.toFixed(6)}`;\n}\n\n/** Format a date string or null as locale string or em-dash. */\nexport function fmtDate(ts: string | number | null | undefined): string {\n\tif (!ts) return \"\\u2014\";\n\ttry {\n\t\treturn new Date(ts).toLocaleString();\n\t} catch {\n\t\treturn \"\\u2014\";\n\t}\n}\n","/**\n * dashboard-client/src/components/CacheHitsCard.tsx — Cache Hits & Compactions card.\n *\n * 6 fields: Cache Hits (session), Cache Hits (total),\n * Tokens Saved (session), Tokens Saved (total),\n * Compactions (session), Compactions (total).\n */\n\nimport type React from \"react\";\n\nexport interface CacheHitsCardProps {\n\t/** Cache hits in the current session. */\n\tcacheHitsSession: number;\n\t/** Total cache hits across all sessions. */\n\tcacheHitsTotal: number;\n\t/** Tokens saved by cache hits this session. */\n\ttokensSavedSession: number;\n\t/** Total tokens saved by cache hits. */\n\ttokensSavedTotal: number;\n\t/** Compactions performed this session. */\n\tcompactionsSession: number;\n\t/** Total compactions performed. */\n\tcompactionsTotal: number;\n}\n\nfunction StatRow({\n\tlabel,\n\tvalue,\n}: {\n\tlabel: string;\n\tvalue: string | number;\n}): React.ReactElement {\n\treturn (\n\t\t<div className=\"ov-stat-row\">\n\t\t\t<span className=\"ov-stat-label\">{label}</span>\n\t\t\t<span className=\"ov-stat-value\">{value}</span>\n\t\t</div>\n\t);\n}\n\nexport function CacheHitsCard(\n\tprops: CacheHitsCardProps,\n): React.ReactElement {\n\treturn (\n\t\t<div className=\"card cache-hits-card\">\n\t\t\t<h3>💾 Cache Hits & Compactions</h3>\n\t\t\t<StatRow\n\t\t\t\tlabel=\"Cache Hits (session)\"\n\t\t\t\tvalue={props.cacheHitsSession.toLocaleString()}\n\t\t\t/>\n\t\t\t<StatRow\n\t\t\t\tlabel=\"Cache Hits (total)\"\n\t\t\t\tvalue={props.cacheHitsTotal.toLocaleString()}\n\t\t\t/>\n\t\t\t<StatRow\n\t\t\t\tlabel=\"Tokens Saved (session)\"\n\t\t\t\tvalue={props.tokensSavedSession.toLocaleString()}\n\t\t\t/>\n\t\t\t<StatRow\n\t\t\t\tlabel=\"Tokens Saved (total)\"\n\t\t\t\tvalue={props.tokensSavedTotal.toLocaleString()}\n\t\t\t/>\n\t\t\t<StatRow\n\t\t\t\tlabel=\"Compactions (session)\"\n\t\t\t\tvalue={props.compactionsSession.toLocaleString()}\n\t\t\t/>\n\t\t\t<StatRow\n\t\t\t\tlabel=\"Compactions (total)\"\n\t\t\t\tvalue={props.compactionsTotal.toLocaleString()}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n","/**\n * dashboard-client/src/components/TimeSavedCard.tsx — Time Saved (est.) card.\n *\n * 4 fields: Compact (session), Compact (total),\n * Cache Hit (session), Cache Hit (total).\n */\n\nimport type React from \"react\";\nimport { fmtSec } from \"../utils/format\";\n\nexport interface TimeSavedCardProps {\n\t/** Seconds saved by compaction this session. */\n\tcompactSessionSec: number;\n\t/** Total seconds saved by compaction. */\n\tcompactTotalSec: number;\n\t/** Seconds saved by cache hits this session. */\n\tcacheHitSessionSec: number;\n\t/** Total seconds saved by cache hits. */\n\tcacheHitTotalSec: number;\n}\n\nfunction StatRow({\n\tlabel,\n\tvalue,\n}: {\n\tlabel: string;\n\tvalue: string;\n}): React.ReactElement {\n\treturn (\n\t\t<div className=\"ov-stat-row\">\n\t\t\t<span className=\"ov-stat-label\">{label}</span>\n\t\t\t<span className=\"ov-stat-value\">{value}</span>\n\t\t</div>\n\t);\n}\n\nexport function TimeSavedCard(\n\tprops: TimeSavedCardProps,\n): React.ReactElement {\n\treturn (\n\t\t<div className=\"card time-saved-card\">\n\t\t\t<h3>⏱ Time Saved (est.)</h3>\n\t\t\t<StatRow\n\t\t\t\tlabel=\"Compact (session)\"\n\t\t\t\tvalue={fmtSec(props.compactSessionSec)}\n\t\t\t/>\n\t\t\t<StatRow\n\t\t\t\tlabel=\"Compact (total)\"\n\t\t\t\tvalue={fmtSec(props.compactTotalSec)}\n\t\t\t/>\n\t\t\t<StatRow\n\t\t\t\tlabel=\"Cache Hit (session)\"\n\t\t\t\tvalue={fmtSec(props.cacheHitSessionSec)}\n\t\t\t/>\n\t\t\t<StatRow\n\t\t\t\tlabel=\"Cache Hit (total)\"\n\t\t\t\tvalue={fmtSec(props.cacheHitTotalSec)}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n"],"names":["fmtBytes","b","n","fmtSec","s","fmtPctFromFraction","v","pct","StatRow","label","value","jsxs","jsx","CacheHitsCard","props","TimeSavedCard"],"mappings":"wCAQO,SAASA,EAASC,EAAsC,CAC9D,MAAMC,EAAID,GAAK,EACf,OAAIC,GAAK,QAAkB,IAAIA,EAAI,SAAW,QAAQ,CAAC,CAAC,OACpDA,GAAK,KAAa,IAAIA,EAAI,MAAM,QAAQ,CAAC,CAAC,OACvC,GAAGA,CAAC,IACZ,CAGO,SAASC,EAAOC,EAAsC,CAC5D,MAAMF,EAAIE,GAAK,EACf,OAAIF,GAAK,KAAa,IAAIA,EAAI,MAAM,QAAQ,CAAC,CAAC,IAC1CA,GAAK,GAAW,GAAG,KAAK,MAAMA,EAAI,EAAE,CAAC,IACrCA,GAAK,EAAU,GAAGA,EAAE,QAAQ,CAAC,CAAC,IAC3B,GAAG,KAAK,MAAMA,EAAI,GAAI,CAAC,IAC/B,CAMO,SAASG,EACfC,EACS,CAET,MAAMC,GADID,GAAK,GACC,IAChB,OAAIC,GAAO,GAAW,GAAG,KAAK,MAAMA,CAAG,CAAC,IACjC,GAAGA,EAAI,QAAQ,CAAC,CAAC,GACzB,CCVA,SAASC,EAAQ,CAChB,MAAAC,EACA,MAAAC,CACD,EAGuB,CACtB,OACCC,EAAAA,KAAC,MAAA,CAAI,UAAU,cACd,SAAA,CAAAC,EAAAA,IAAC,OAAA,CAAK,UAAU,gBAAiB,SAAAH,EAAM,EACvCG,EAAAA,IAAC,OAAA,CAAK,UAAU,gBAAiB,SAAAF,CAAA,CAAM,CAAA,EACxC,CAEF,CAEO,SAASG,EACfC,EACqB,CACrB,OACCH,EAAAA,KAAC,MAAA,CAAI,UAAU,uBACd,SAAA,CAAAC,EAAAA,IAAC,MAAG,SAAA,6BAAA,CAA+B,EACnCA,EAAAA,IAACJ,EAAA,CACA,MAAM,uBACN,MAAOM,EAAM,iBAAiB,eAAA,CAAe,CAAA,EAE9CF,EAAAA,IAACJ,EAAA,CACA,MAAM,qBACN,MAAOM,EAAM,eAAe,eAAA,CAAe,CAAA,EAE5CF,EAAAA,IAACJ,EAAA,CACA,MAAM,yBACN,MAAOM,EAAM,mBAAmB,eAAA,CAAe,CAAA,EAEhDF,EAAAA,IAACJ,EAAA,CACA,MAAM,uBACN,MAAOM,EAAM,iBAAiB,eAAA,CAAe,CAAA,EAE9CF,EAAAA,IAACJ,EAAA,CACA,MAAM,wBACN,MAAOM,EAAM,mBAAmB,eAAA,CAAe,CAAA,EAEhDF,EAAAA,IAACJ,EAAA,CACA,MAAM,sBACN,MAAOM,EAAM,iBAAiB,eAAA,CAAe,CAAA,CAC9C,EACD,CAEF,CCnDA,SAASN,EAAQ,CAChB,MAAAC,EACA,MAAAC,CACD,EAGuB,CACtB,OACCC,EAAAA,KAAC,MAAA,CAAI,UAAU,cACd,SAAA,CAAAC,EAAAA,IAAC,OAAA,CAAK,UAAU,gBAAiB,SAAAH,EAAM,EACvCG,EAAAA,IAAC,OAAA,CAAK,UAAU,gBAAiB,SAAAF,CAAA,CAAM,CAAA,EACxC,CAEF,CAEO,SAASK,EACfD,EACqB,CACrB,OACCH,EAAAA,KAAC,MAAA,CAAI,UAAU,uBACd,SAAA,CAAAC,EAAAA,IAAC,MAAG,SAAA,qBAAA,CAAmB,EACvBA,EAAAA,IAACJ,EAAA,CACA,MAAM,oBACN,MAAOL,EAAOW,EAAM,iBAAiB,CAAA,CAAA,EAEtCF,EAAAA,IAACJ,EAAA,CACA,MAAM,kBACN,MAAOL,EAAOW,EAAM,eAAe,CAAA,CAAA,EAEpCF,EAAAA,IAACJ,EAAA,CACA,MAAM,sBACN,MAAOL,EAAOW,EAAM,kBAAkB,CAAA,CAAA,EAEvCF,EAAAA,IAACJ,EAAA,CACA,MAAM,oBACN,MAAOL,EAAOW,EAAM,gBAAgB,CAAA,CAAA,CACrC,EACD,CAEF"}
|
package/extensions/dashboard-client/dist/assets/{TopicsTab-DKuct4oD.js → TopicsTab-DRLJmVv0.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{u as m,r as a,m as u,n as p,j as e}from"./index-
|
|
2
|
-
//# sourceMappingURL=TopicsTab-
|
|
1
|
+
import{u as m,r as a,m as u,n as p,j as e}from"./index-BcoSz-L4.js";function b(s){return s?new Date(s).toLocaleString():"—"}function f(){const{data:s,loading:h,error:n}=m(a.useCallback(()=>u(),[]),{pollInterval:3e4}),[l,x]=a.useState(""),[i,o]=a.useState(null),r=m(a.useCallback(()=>i?p(i):Promise.reject(),[i]),{pollInterval:0}),d=a.useMemo(()=>{if(!s)return[];const t=l.trim().toLowerCase();return t?s.topics.filter(c=>c.label.toLowerCase().includes(t)||c.termScore.some(j=>j.term.toLowerCase().includes(t))):s.topics},[s,l]);return n&&!s?e.jsxs("div",{className:"tab-stub",children:["Error loading topics: ",n.message]}):h&&!s?e.jsx("div",{className:"tab-stub",children:"Loading topics…"}):s?s.totalTopics===0?e.jsxs("div",{className:"tab-stub",children:[e.jsx("h3",{children:"Wiki"}),e.jsx("p",{children:"No topics yet. Topics are auto-generated after every 10th compaction from real memory embeddings (k-means + TF-IDF)."}),e.jsx("p",{children:"Check back after a few more compaction cycles."})]}):e.jsxs("div",{className:"tab-content topics-tab",children:[e.jsx("h3",{children:"Wiki"}),e.jsxs("p",{className:"subtitle",children:[s.totalTopics," topic",s.totalTopics!==1?"s":""," ·"," ",s.totalAssigned," assigned memori",s.totalAssigned!==1?"es":"y",s.lastRebuildAt!=null&&e.jsxs(e.Fragment,{children:[" · last rebuild ",new Date(s.lastRebuildAt).toLocaleString()]})]}),e.jsx("input",{type:"search",className:"topics-search",placeholder:"Filter topics by label or term…",value:l,onChange:t=>x(t.target.value)}),i&&e.jsxs("section",{className:"topic-drilldown",children:[e.jsxs("h4",{children:[e.jsx("button",{type:"button",className:"link-btn",onClick:()=>o(null),children:"← back"})," ","Topic ",e.jsx("code",{children:i}),r.data&&e.jsxs(e.Fragment,{children:[" · ",r.data.label]}),r.data&&e.jsxs(e.Fragment,{children:[" · ",r.data.assignments.length," memories"]})]}),r.error?e.jsxs("div",{className:"tab-stub",children:["Error: ",r.error.message]}):r.loading&&!r.data?e.jsx("div",{className:"tab-stub",children:"Loading memories…"}):r.data?e.jsxs("table",{className:"data-table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Memory id"}),e.jsx("th",{children:"Confidence"}),e.jsx("th",{children:"Assigned"})]})}),e.jsx("tbody",{children:r.data.assignments.map(t=>e.jsxs("tr",{children:[e.jsx("td",{children:e.jsx("code",{children:t.memoryId})}),e.jsx("td",{children:t.confidence!=null?t.confidence.toFixed(2):"—"}),e.jsx("td",{children:b(t.assignedAt)})]},t.memoryId))})]}):null]}),!i&&e.jsxs("table",{className:"data-table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Label"}),e.jsx("th",{children:"Memories"}),e.jsx("th",{children:"Top Terms"}),e.jsx("th",{})]})}),e.jsxs("tbody",{children:[d.map(t=>e.jsxs("tr",{className:"topic-row",onClick:()=>o(t.id),style:{cursor:"pointer"},children:[e.jsx("td",{className:"topic-label",children:t.label}),e.jsx("td",{className:"topic-count",children:t.memoryCount}),e.jsx("td",{className:"topic-terms",children:t.termScore.slice(0,8).map(c=>c.term).join(", ")}),e.jsx("td",{children:e.jsx("button",{type:"button",className:"mini-btn",children:"drill"})})]},t.id)),d.length===0&&e.jsx("tr",{children:e.jsxs("td",{colSpan:4,className:"muted",children:["No topics match “",l,"”."]})})]})]})]}):e.jsx("div",{className:"tab-stub",children:"No topic data available."})}export{f as default};
|
|
2
|
+
//# sourceMappingURL=TopicsTab-DRLJmVv0.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TopicsTab-
|
|
1
|
+
{"version":3,"file":"TopicsTab-DRLJmVv0.js","sources":["../../src/tabs/TopicsTab.tsx"],"sourcesContent":["/**\n * dashboard-client/src/tabs/TopicsTab.tsx — Auto-categorizing wiki (S51 + S52 polish).\n *\n * Fetches /api/topics and renders the k-means + TF-IDF topic clusters. S52 polish\n * adds: (1) a search box filtering topics by label / discriminative term, and\n * (2) a topic drill-down — click a topic to load its member memories\n * (/api/topics/:id/memories). Read-only; no write operations.\n */\n\nimport type React from \"react\";\nimport { useCallback, useMemo, useState } from \"react\";\nimport { useApi } from \"../hooks/useApi\";\nimport { fetchTopics, fetchTopicMemories } from \"../api/client\";\nimport type { TopicsResponse, TopicMemoriesResponse } from \"@contracts\";\n\nfunction fmtTs(ms: number | null): string {\n\tif (!ms) return \"—\";\n\treturn new Date(ms).toLocaleString();\n}\n\nexport default function TopicsTab(): React.ReactElement {\n\tconst { data, loading, error } = useApi<TopicsResponse>(\n\t\tuseCallback(() => fetchTopics(), []),\n\t\t{ pollInterval: 30_000 },\n\t);\n\tconst [query, setQuery] = useState(\"\");\n\tconst [drillTopicId, setDrillTopicId] = useState<string | null>(null);\n\n\tconst drill = useApi<TopicMemoriesResponse>(\n\t\tuseCallback(\n\t\t\t() =>\n\t\t\t\tdrillTopicId ? fetchTopicMemories(drillTopicId) : Promise.reject(),\n\t\t\t[drillTopicId],\n\t\t),\n\t\t{ pollInterval: 0 },\n\t);\n\n\tconst filtered = useMemo(() => {\n\t\tif (!data) return [];\n\t\tconst q = query.trim().toLowerCase();\n\t\tif (!q) return data.topics;\n\t\treturn data.topics.filter(\n\t\t\t(t) =>\n\t\t\t\tt.label.toLowerCase().includes(q) ||\n\t\t\t\tt.termScore.some((s) => s.term.toLowerCase().includes(q)),\n\t\t);\n\t}, [data, query]);\n\n\tif (error && !data) {\n\t\treturn (\n\t\t\t<div className=\"tab-stub\">Error loading topics: {error.message}</div>\n\t\t);\n\t}\n\tif (loading && !data) {\n\t\treturn <div className=\"tab-stub\">Loading topics…</div>;\n\t}\n\tif (!data) {\n\t\treturn <div className=\"tab-stub\">No topic data available.</div>;\n\t}\n\n\tif (data.totalTopics === 0) {\n\t\treturn (\n\t\t\t<div className=\"tab-stub\">\n\t\t\t\t<h3>Wiki</h3>\n\t\t\t\t<p>\n\t\t\t\t\tNo topics yet. Topics are auto-generated after every 10th compaction\n\t\t\t\t\tfrom real memory embeddings (k-means + TF-IDF).\n\t\t\t\t</p>\n\t\t\t\t<p>Check back after a few more compaction cycles.</p>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<div className=\"tab-content topics-tab\">\n\t\t\t<h3>Wiki</h3>\n\t\t\t<p className=\"subtitle\">\n\t\t\t\t{data.totalTopics} topic{data.totalTopics !== 1 ? \"s\" : \"\"} ·{\" \"}\n\t\t\t\t{data.totalAssigned} assigned memori\n\t\t\t\t{data.totalAssigned !== 1 ? \"es\" : \"y\"}\n\t\t\t\t{data.lastRebuildAt != null && (\n\t\t\t\t\t<> · last rebuild {new Date(data.lastRebuildAt).toLocaleString()}</>\n\t\t\t\t)}\n\t\t\t</p>\n\n\t\t\t<input\n\t\t\t\ttype=\"search\"\n\t\t\t\tclassName=\"topics-search\"\n\t\t\t\tplaceholder=\"Filter topics by label or term…\"\n\t\t\t\tvalue={query}\n\t\t\t\tonChange={(e) => setQuery(e.target.value)}\n\t\t\t/>\n\n\t\t\t{drillTopicId && (\n\t\t\t\t<section className=\"topic-drilldown\">\n\t\t\t\t\t<h4>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tclassName=\"link-btn\"\n\t\t\t\t\t\t\tonClick={() => setDrillTopicId(null)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t← back\n\t\t\t\t\t\t</button>{\" \"}\n\t\t\t\t\t\tTopic <code>{drillTopicId}</code>\n\t\t\t\t\t\t{drill.data && <> · {drill.data.label}</>}\n\t\t\t\t\t\t{drill.data && <> · {drill.data.assignments.length} memories</>}\n\t\t\t\t\t</h4>\n\t\t\t\t\t{drill.error ? (\n\t\t\t\t\t\t<div className=\"tab-stub\">\n\t\t\t\t\t\t\tError: {(drill.error as Error).message}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : drill.loading && !drill.data ? (\n\t\t\t\t\t\t<div className=\"tab-stub\">Loading memories…</div>\n\t\t\t\t\t) : drill.data ? (\n\t\t\t\t\t\t<table className=\"data-table\">\n\t\t\t\t\t\t\t<thead>\n\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t\t<th>Memory id</th>\n\t\t\t\t\t\t\t\t\t<th>Confidence</th>\n\t\t\t\t\t\t\t\t\t<th>Assigned</th>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t</thead>\n\t\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t\t\t{drill.data.assignments.map((a) => (\n\t\t\t\t\t\t\t\t\t<tr key={a.memoryId}>\n\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t<code>{a.memoryId}</code>\n\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t\t\t{a.confidence != null ? a.confidence.toFixed(2) : \"—\"}\n\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t<td>{fmtTs(a.assignedAt)}</td>\n\t\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</tbody>\n\t\t\t\t\t\t</table>\n\t\t\t\t\t) : null}\n\t\t\t\t</section>\n\t\t\t)}\n\n\t\t\t{!drillTopicId && (\n\t\t\t\t<table className=\"data-table\">\n\t\t\t\t\t<thead>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<th>Label</th>\n\t\t\t\t\t\t\t<th>Memories</th>\n\t\t\t\t\t\t\t<th>Top Terms</th>\n\t\t\t\t\t\t\t<th></th>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</thead>\n\t\t\t\t\t<tbody>\n\t\t\t\t\t\t{filtered.map((t) => (\n\t\t\t\t\t\t\t<tr\n\t\t\t\t\t\t\t\tkey={t.id}\n\t\t\t\t\t\t\t\tclassName=\"topic-row\"\n\t\t\t\t\t\t\t\tonClick={() => setDrillTopicId(t.id)}\n\t\t\t\t\t\t\t\tstyle={{ cursor: \"pointer\" }}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<td className=\"topic-label\">{t.label}</td>\n\t\t\t\t\t\t\t\t<td className=\"topic-count\">{t.memoryCount}</td>\n\t\t\t\t\t\t\t\t<td className=\"topic-terms\">\n\t\t\t\t\t\t\t\t\t{t.termScore\n\t\t\t\t\t\t\t\t\t\t.slice(0, 8)\n\t\t\t\t\t\t\t\t\t\t.map((s) => s.term)\n\t\t\t\t\t\t\t\t\t\t.join(\", \")}\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t<button type=\"button\" className=\"mini-btn\">\n\t\t\t\t\t\t\t\t\t\tdrill\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t))}\n\t\t\t\t\t\t{filtered.length === 0 && (\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<td colSpan={4} className=\"muted\">\n\t\t\t\t\t\t\t\t\tNo topics match “{query}”.\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</tbody>\n\t\t\t\t</table>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n"],"names":["fmtTs","ms","TopicsTab","data","loading","error","useApi","useCallback","fetchTopics","query","setQuery","useState","drillTopicId","setDrillTopicId","drill","fetchTopicMemories","filtered","useMemo","q","t","s","jsxs","jsx","Fragment","e","a"],"mappings":"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"}
|
package/extensions/dashboard-client/dist/assets/{TurnsTab-11MGLxY8.js → TurnsTab-CLNM0T5R.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{u as f,r,o as C,q as w,s as I,t as T,v as $,j as e}from"./index-
|
|
2
|
-
//# sourceMappingURL=TurnsTab-
|
|
1
|
+
import{u as f,r,o as C,q as w,s as I,t as T,v as $,j as e}from"./index-BcoSz-L4.js";function j(n){return n?new Date(n).toLocaleString():"—"}function E(n){return n==="green"?"band band-green":n==="yellow"?"band band-yellow":n==="red"?"band band-red":"band"}function L(n){return n==="checkpoint"?"ckpt":n==="cluster_summary"?"raptor":"mem"}function S(){const{data:n,loading:i,error:d}=f(r.useCallback(()=>C(),[]),{pollInterval:1e4}),{data:c}=f(r.useCallback(()=>w(),[]),{pollInterval:5e3}),[s,l]=r.useState(null),[m,x]=r.useState(null),[v,p]=r.useState(!1),[N,u]=r.useState(null),[b,o]=r.useState(null),g=r.useCallback(async t=>{if(s===t){l(null),x(null);return}l(t),p(!0),x(null);try{const a=await I(t);x(a)}finally{p(!1)}},[s]),y=r.useCallback(async(t,a)=>{u(`fork:${t}:${a}`),o(null);try{const h=await T(t,a);o(`Forked → ${h.childConversationId} (${h.recalledCount} recalled)`)}catch(h){o(`Fork failed: ${h.message}`)}finally{u(null)}},[]),k=r.useCallback(async(t,a)=>{u(`rewind:${t}:${a}`),o(null);try{await $(t,a),o(`Rewind intent queued for turn ${a}`)}catch(h){o(`Rewind failed: ${h.message}`)}finally{u(null)}},[]);return d&&!n?e.jsxs("div",{className:"tab-stub",children:["Error loading turns: ",d.message]}):i&&!n?e.jsx("div",{className:"tab-stub",children:"Loading turns…"}):!n||n.conversations.length===0?e.jsxs("div",{className:"tab-stub",children:[e.jsx("h3",{children:"Turn-by-turn memory"}),e.jsxs("p",{children:["No turns recorded yet. Per-turn tracking starts when"," ",e.jsx("code",{children:"MEGACOMPACT_TURNS_DB=1"})," and the session runs through a compaction. Each turn records its context metrics + the checkpoints recalled into it."]})]}):e.jsxs("div",{className:"turns-tab",children:[e.jsx("h3",{children:"Turn-by-turn memory tracking + recall"}),b&&e.jsx("div",{className:"turns-notice",children:b}),c&&c.intents.length>0&&e.jsxs("section",{className:"turns-intents",children:[e.jsxs("h4",{children:["Pending rewind intents (",c.intents.length,")"]}),e.jsx("ul",{children:c.intents.map(t=>e.jsxs("li",{children:[j(t.createdAt)," — rewind ",e.jsx("code",{children:t.conversationId})," to turn ",t.targetTurnIndex]},t.id))})]}),e.jsxs("section",{className:"turns-conv-list",children:[e.jsxs("h4",{children:["Conversations (",n.conversations.length,")"]}),e.jsxs("table",{className:"turns-table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Conversation"}),e.jsx("th",{children:"Turns"}),e.jsx("th",{children:"Recall"}),e.jsx("th",{children:"Epochs"}),e.jsx("th",{children:"Avg ctx%"}),e.jsx("th",{children:"Last turn"}),e.jsx("th",{})]})}),e.jsx("tbody",{children:n.conversations.map(t=>e.jsx(R,{c:t,active:n.activeConversationId===t.conversationId,expanded:s===t.conversationId,onExpand:()=>g(t.conversationId)},t.conversationId))})]})]}),s&&e.jsxs("section",{className:"turns-detail",children:[e.jsxs("h4",{children:["Turns in ",e.jsx("code",{children:s})]}),v?e.jsx("div",{className:"tab-stub",children:"Loading turns…"}):m?e.jsx(A,{detail:m,busy:N,onFork:y,onRewind:k}):e.jsx("div",{className:"tab-stub",children:"No detail."})]})]})}function R({c:n,active:i,expanded:d,onExpand:c}){return e.jsx(e.Fragment,{children:e.jsxs("tr",{className:i?"turns-row active":"turns-row",onClick:c,style:{cursor:"pointer"},children:[e.jsxs("td",{children:[d?"▾":"▸"," ",e.jsx("code",{children:n.conversationId}),i&&e.jsx("span",{className:"pill",children:"active"})]}),e.jsx("td",{children:n.turnCount}),e.jsx("td",{children:n.totalRecall}),e.jsx("td",{children:n.epochCount}),e.jsxs("td",{children:[(n.avgCtxPercent*100).toFixed(0),"%"]}),e.jsx("td",{children:j(n.lastTurnAt)}),e.jsx("td",{})]})})}function A({detail:n,busy:i,onFork:d,onRewind:c}){return e.jsxs("table",{className:"turns-detail-table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"#"}),e.jsx("th",{children:"Role"}),e.jsx("th",{children:"Ctx"}),e.jsx("th",{children:"Band"}),e.jsx("th",{children:"Epoch"}),e.jsx("th",{children:"Recalled checkpoints (memory recall)"}),e.jsx("th",{children:"Ended"}),e.jsx("th",{children:"Actions"})]})}),e.jsx("tbody",{children:n.turns.map(s=>e.jsxs("tr",{children:[e.jsx("td",{children:s.turnIndex}),e.jsx("td",{children:s.role}),e.jsxs("td",{children:[s.ctxTokens??"—",s.ctxPercent!=null&&e.jsxs("span",{className:"muted",children:[" ","· ",(s.ctxPercent*100).toFixed(0),"%"]})]}),e.jsx("td",{children:e.jsx("span",{className:E(s.pressureBand),children:s.pressureBand??"—"})}),e.jsx("td",{children:s.epochId?e.jsx("code",{children:s.epochId.slice(0,8)}):"—"}),e.jsx("td",{className:"recall-cell",children:s.recall.length===0?e.jsx("span",{className:"muted",children:"—"}):e.jsx("ul",{className:"recall-list",children:s.recall.map(l=>e.jsxs("li",{children:[e.jsx("code",{children:l.checkpointId.slice(0,12)})," ",e.jsxs("span",{className:"muted",children:[L(l.source)," · ",l.score.toFixed(2),l.raptorLevel!=null?` · L${l.raptorLevel}`:""]})]},l.checkpointId))})}),e.jsx("td",{children:j(s.endedAt)}),e.jsxs("td",{className:"actions-cell",children:[e.jsx("button",{type:"button",className:"mini-btn",disabled:i!==null,onClick:()=>d(s.conversationId,s.turnIndex),children:"fork"}),e.jsx("button",{type:"button",className:"mini-btn",disabled:i!==null,onClick:()=>c(s.conversationId,s.turnIndex),children:"rewind"})]})]},`${s.conversationId}:${s.turnIndex}`))})]})}export{S as default};
|
|
2
|
+
//# sourceMappingURL=TurnsTab-CLNM0T5R.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TurnsTab-11MGLxY8.js","sources":["../../src/tabs/TurnsTab.tsx"],"sourcesContent":["/**\n * dashboard-client/src/tabs/TurnsTab.tsx — Turn-by-turn memory tracking + recall (S52).\n *\n * Fetches /api/turns (conversation list), expands the active conversation into\n * per-turn detail (/api/turns/conversation/:id), and renders:\n * - Conversation summary list (turn count, recall total, epochs, last turn).\n * - Per-turn rows: turn index, role, ctx tokens/percent + pressure band,\n * epoch id, and the injected-checkpoint recall set (the memory recalled\n * at each turn, with score + source).\n * - Pending rewind intents (S52A) + Fork action (S50C primitive).\n *\n * Read-mostly via /api/turns; fork/intent/prune via POST. No absolute URLs\n * (PREVENT-PI-004: loopback-only, same-origin static bundle).\n */\n\nimport type React from \"react\";\nimport { useCallback, useState } from \"react\";\nimport { useApi } from \"../hooks/useApi\";\nimport {\n\tfetchTurns,\n\tfetchConversationTurns,\n\tfetchTurnIntents,\n\tpostFork,\n\tpostTurnIntent,\n} from \"../api/client\";\nimport type {\n\tTurnsResponse,\n\tConversationTurnsResponse,\n\tRewindIntentsResponse,\n\tTurnRow,\n\tConversationSummary,\n} from \"@contracts\";\n\nfunction fmtTs(ms: number): string {\n\tif (!ms) return \"—\";\n\treturn new Date(ms).toLocaleString();\n}\n\nfunction bandClass(band: TurnRow[\"pressureBand\"]): string {\n\tif (band === \"green\") return \"band band-green\";\n\tif (band === \"yellow\") return \"band band-yellow\";\n\tif (band === \"red\") return \"band band-red\";\n\treturn \"band\";\n}\n\nfunction sourceLabel(s: TurnRow[\"recall\"][number][\"source\"]): string {\n\tif (s === \"checkpoint\") return \"ckpt\";\n\tif (s === \"cluster_summary\") return \"raptor\";\n\treturn \"mem\";\n}\n\nexport default function TurnsTab(): React.ReactElement {\n\tconst {\n\t\tdata: turns,\n\t\tloading,\n\t\terror,\n\t} = useApi<TurnsResponse>(\n\t\tuseCallback(() => fetchTurns(), []),\n\t\t{\n\t\t\tpollInterval: 10_000,\n\t\t},\n\t);\n\tconst { data: intents } = useApi<RewindIntentsResponse>(\n\t\tuseCallback(() => fetchTurnIntents(), []),\n\t\t{ pollInterval: 5_000 },\n\t);\n\tconst [expanded, setExpanded] = useState<string | null>(null);\n\tconst [detail, setDetail] = useState<ConversationTurnsResponse | null>(null);\n\tconst [detailLoading, setDetailLoading] = useState(false);\n\tconst [busy, setBusy] = useState<string | null>(null);\n\tconst [notice, setNotice] = useState<string | null>(null);\n\n\tconst expand = useCallback(\n\t\tasync (conversationId: string) => {\n\t\t\tif (expanded === conversationId) {\n\t\t\t\tsetExpanded(null);\n\t\t\t\tsetDetail(null);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsetExpanded(conversationId);\n\t\t\tsetDetailLoading(true);\n\t\t\tsetDetail(null);\n\t\t\ttry {\n\t\t\t\tconst d = await fetchConversationTurns(conversationId);\n\t\t\t\tsetDetail(d);\n\t\t\t} finally {\n\t\t\t\tsetDetailLoading(false);\n\t\t\t}\n\t\t},\n\t\t[expanded],\n\t);\n\n\tconst onFork = useCallback(\n\t\tasync (conversationId: string, turnIndex: number) => {\n\t\t\tsetBusy(`fork:${conversationId}:${turnIndex}`);\n\t\t\tsetNotice(null);\n\t\t\ttry {\n\t\t\t\tconst out = await postFork(conversationId, turnIndex);\n\t\t\t\tsetNotice(\n\t\t\t\t\t`Forked → ${out.childConversationId} (${out.recalledCount} recalled)`,\n\t\t\t\t);\n\t\t\t} catch (e) {\n\t\t\t\tsetNotice(`Fork failed: ${(e as Error).message}`);\n\t\t\t} finally {\n\t\t\t\tsetBusy(null);\n\t\t\t}\n\t\t},\n\t\t[],\n\t);\n\n\tconst onRewind = useCallback(\n\t\tasync (conversationId: string, turnIndex: number) => {\n\t\t\tsetBusy(`rewind:${conversationId}:${turnIndex}`);\n\t\t\tsetNotice(null);\n\t\t\ttry {\n\t\t\t\tawait postTurnIntent(conversationId, turnIndex);\n\t\t\t\tsetNotice(`Rewind intent queued for turn ${turnIndex}`);\n\t\t\t} catch (e) {\n\t\t\t\tsetNotice(`Rewind failed: ${(e as Error).message}`);\n\t\t\t} finally {\n\t\t\t\tsetBusy(null);\n\t\t\t}\n\t\t},\n\t\t[],\n\t);\n\n\tif (error && !turns) {\n\t\treturn <div className=\"tab-stub\">Error loading turns: {error.message}</div>;\n\t}\n\tif (loading && !turns) {\n\t\treturn <div className=\"tab-stub\">Loading turns…</div>;\n\t}\n\tif (!turns || turns.conversations.length === 0) {\n\t\treturn (\n\t\t\t<div className=\"tab-stub\">\n\t\t\t\t<h3>Turn-by-turn memory</h3>\n\t\t\t\t<p>\n\t\t\t\t\tNo turns recorded yet. Per-turn tracking starts when{\" \"}\n\t\t\t\t\t<code>MEGACOMPACT_TURNS_DB=1</code> and the session runs through a\n\t\t\t\t\tcompaction. Each turn records its context metrics + the checkpoints\n\t\t\t\t\trecalled into it.\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<div className=\"turns-tab\">\n\t\t\t<h3>Turn-by-turn memory tracking + recall</h3>\n\t\t\t{notice && <div className=\"turns-notice\">{notice}</div>}\n\n\t\t\t{intents && intents.intents.length > 0 && (\n\t\t\t\t<section className=\"turns-intents\">\n\t\t\t\t\t<h4>Pending rewind intents ({intents.intents.length})</h4>\n\t\t\t\t\t<ul>\n\t\t\t\t\t\t{intents.intents.map((i) => (\n\t\t\t\t\t\t\t<li key={i.id}>\n\t\t\t\t\t\t\t\t{fmtTs(i.createdAt)} — rewind <code>{i.conversationId}</code> to\n\t\t\t\t\t\t\t\tturn {i.targetTurnIndex}\n\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</ul>\n\t\t\t\t</section>\n\t\t\t)}\n\n\t\t\t<section className=\"turns-conv-list\">\n\t\t\t\t<h4>Conversations ({turns.conversations.length})</h4>\n\t\t\t\t<table className=\"turns-table\">\n\t\t\t\t\t<thead>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<th>Conversation</th>\n\t\t\t\t\t\t\t<th>Turns</th>\n\t\t\t\t\t\t\t<th>Recall</th>\n\t\t\t\t\t\t\t<th>Epochs</th>\n\t\t\t\t\t\t\t<th>Avg ctx%</th>\n\t\t\t\t\t\t\t<th>Last turn</th>\n\t\t\t\t\t\t\t<th></th>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</thead>\n\t\t\t\t\t<tbody>\n\t\t\t\t\t\t{turns.conversations.map((c: ConversationSummary) => (\n\t\t\t\t\t\t\t<ConversationRow\n\t\t\t\t\t\t\t\tkey={c.conversationId}\n\t\t\t\t\t\t\t\tc={c}\n\t\t\t\t\t\t\t\tactive={turns.activeConversationId === c.conversationId}\n\t\t\t\t\t\t\t\texpanded={expanded === c.conversationId}\n\t\t\t\t\t\t\t\tonExpand={() => expand(c.conversationId)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</tbody>\n\t\t\t\t</table>\n\t\t\t</section>\n\n\t\t\t{expanded && (\n\t\t\t\t<section className=\"turns-detail\">\n\t\t\t\t\t<h4>\n\t\t\t\t\t\tTurns in <code>{expanded}</code>\n\t\t\t\t\t</h4>\n\t\t\t\t\t{detailLoading ? (\n\t\t\t\t\t\t<div className=\"tab-stub\">Loading turns…</div>\n\t\t\t\t\t) : detail ? (\n\t\t\t\t\t\t<TurnDetail\n\t\t\t\t\t\t\tdetail={detail}\n\t\t\t\t\t\t\tbusy={busy}\n\t\t\t\t\t\t\tonFork={onFork}\n\t\t\t\t\t\t\tonRewind={onRewind}\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<div className=\"tab-stub\">No detail.</div>\n\t\t\t\t\t)}\n\t\t\t\t</section>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nfunction ConversationRow({\n\tc,\n\tactive,\n\texpanded,\n\tonExpand,\n}: {\n\tc: ConversationSummary;\n\tactive: boolean;\n\texpanded: boolean;\n\tonExpand: () => void;\n}): React.ReactElement {\n\treturn (\n\t\t<>\n\t\t\t<tr\n\t\t\t\tclassName={active ? \"turns-row active\" : \"turns-row\"}\n\t\t\t\tonClick={onExpand}\n\t\t\t\tstyle={{ cursor: \"pointer\" }}\n\t\t\t>\n\t\t\t\t<td>\n\t\t\t\t\t{expanded ? \"▾\" : \"▸\"} <code>{c.conversationId}</code>\n\t\t\t\t\t{active && <span className=\"pill\">active</span>}\n\t\t\t\t</td>\n\t\t\t\t<td>{c.turnCount}</td>\n\t\t\t\t<td>{c.totalRecall}</td>\n\t\t\t\t<td>{c.epochCount}</td>\n\t\t\t\t<td>{(c.avgCtxPercent * 100).toFixed(0)}%</td>\n\t\t\t\t<td>{fmtTs(c.lastTurnAt)}</td>\n\t\t\t\t<td />\n\t\t\t</tr>\n\t\t</>\n\t);\n}\n\nfunction TurnDetail({\n\tdetail,\n\tbusy,\n\tonFork,\n\tonRewind,\n}: {\n\tdetail: ConversationTurnsResponse;\n\tbusy: string | null;\n\tonFork: (conversationId: string, turnIndex: number) => void;\n\tonRewind: (conversationId: string, turnIndex: number) => void;\n}): React.ReactElement {\n\treturn (\n\t\t<table className=\"turns-detail-table\">\n\t\t\t<thead>\n\t\t\t\t<tr>\n\t\t\t\t\t<th>#</th>\n\t\t\t\t\t<th>Role</th>\n\t\t\t\t\t<th>Ctx</th>\n\t\t\t\t\t<th>Band</th>\n\t\t\t\t\t<th>Epoch</th>\n\t\t\t\t\t<th>Recalled checkpoints (memory recall)</th>\n\t\t\t\t\t<th>Ended</th>\n\t\t\t\t\t<th>Actions</th>\n\t\t\t\t</tr>\n\t\t\t</thead>\n\t\t\t<tbody>\n\t\t\t\t{detail.turns.map((t) => (\n\t\t\t\t\t<tr key={`${t.conversationId}:${t.turnIndex}`}>\n\t\t\t\t\t\t<td>{t.turnIndex}</td>\n\t\t\t\t\t\t<td>{t.role}</td>\n\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t{t.ctxTokens ?? \"—\"}\n\t\t\t\t\t\t\t{t.ctxPercent != null && (\n\t\t\t\t\t\t\t\t<span className=\"muted\">\n\t\t\t\t\t\t\t\t\t{\" \"}\n\t\t\t\t\t\t\t\t\t· {(t.ctxPercent * 100).toFixed(0)}%\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t<span className={bandClass(t.pressureBand)}>\n\t\t\t\t\t\t\t\t{t.pressureBand ?? \"—\"}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td>{t.epochId ? <code>{t.epochId.slice(0, 8)}</code> : \"—\"}</td>\n\t\t\t\t\t\t<td className=\"recall-cell\">\n\t\t\t\t\t\t\t{t.recall.length === 0 ? (\n\t\t\t\t\t\t\t\t<span className=\"muted\">—</span>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<ul className=\"recall-list\">\n\t\t\t\t\t\t\t\t\t{t.recall.map((r) => (\n\t\t\t\t\t\t\t\t\t\t<li key={r.checkpointId}>\n\t\t\t\t\t\t\t\t\t\t\t<code>{r.checkpointId.slice(0, 12)}</code>{\" \"}\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"muted\">\n\t\t\t\t\t\t\t\t\t\t\t\t{sourceLabel(r.source)} · {r.score.toFixed(2)}\n\t\t\t\t\t\t\t\t\t\t\t\t{r.raptorLevel != null ? ` · L${r.raptorLevel}` : \"\"}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</ul>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td>{fmtTs(t.endedAt)}</td>\n\t\t\t\t\t\t<td className=\"actions-cell\">\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclassName=\"mini-btn\"\n\t\t\t\t\t\t\t\tdisabled={busy !== null}\n\t\t\t\t\t\t\t\tonClick={() => onFork(t.conversationId, t.turnIndex)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tfork\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclassName=\"mini-btn\"\n\t\t\t\t\t\t\t\tdisabled={busy !== null}\n\t\t\t\t\t\t\t\tonClick={() => onRewind(t.conversationId, t.turnIndex)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\trewind\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t</tr>\n\t\t\t\t))}\n\t\t\t</tbody>\n\t\t</table>\n\t);\n}\n"],"names":["fmtTs","ms","bandClass","band","sourceLabel","s","TurnsTab","turns","loading","error","useApi","useCallback","fetchTurns","intents","fetchTurnIntents","expanded","setExpanded","useState","detail","setDetail","detailLoading","setDetailLoading","busy","setBusy","notice","setNotice","expand","conversationId","d","fetchConversationTurns","onFork","turnIndex","out","postFork","e","onRewind","postTurnIntent","jsxs","jsx","i","c","ConversationRow","TurnDetail","active","onExpand","Fragment","t","r"],"mappings":"oFAiCA,SAASA,EAAMC,EAAoB,CAClC,OAAKA,EACE,IAAI,KAAKA,CAAE,EAAE,eAAA,EADJ,GAEjB,CAEA,SAASC,EAAUC,EAAuC,CACzD,OAAIA,IAAS,QAAgB,kBACzBA,IAAS,SAAiB,mBAC1BA,IAAS,MAAc,gBACpB,MACR,CAEA,SAASC,EAAYC,EAAgD,CACpE,OAAIA,IAAM,aAAqB,OAC3BA,IAAM,kBAA0B,SAC7B,KACR,CAEA,SAAwBC,GAA+B,CACtD,KAAM,CACL,KAAMC,EACN,QAAAC,EACA,MAAAC,CAAA,EACGC,EACHC,cAAY,IAAMC,EAAA,EAAc,EAAE,EAClC,CACC,aAAc,GAAA,CACf,EAEK,CAAE,KAAMC,CAAA,EAAYH,EACzBC,cAAY,IAAMG,EAAA,EAAoB,EAAE,EACxC,CAAE,aAAc,GAAA,CAAM,EAEjB,CAACC,EAAUC,CAAW,EAAIC,EAAAA,SAAwB,IAAI,EACtD,CAACC,EAAQC,CAAS,EAAIF,EAAAA,SAA2C,IAAI,EACrE,CAACG,EAAeC,CAAgB,EAAIJ,EAAAA,SAAS,EAAK,EAClD,CAACK,EAAMC,CAAO,EAAIN,EAAAA,SAAwB,IAAI,EAC9C,CAACO,EAAQC,CAAS,EAAIR,EAAAA,SAAwB,IAAI,EAElDS,EAASf,EAAAA,YACd,MAAOgB,GAA2B,CACjC,GAAIZ,IAAaY,EAAgB,CAChCX,EAAY,IAAI,EAChBG,EAAU,IAAI,EACd,MACD,CACAH,EAAYW,CAAc,EAC1BN,EAAiB,EAAI,EACrBF,EAAU,IAAI,EACd,GAAI,CACH,MAAMS,EAAI,MAAMC,EAAuBF,CAAc,EACrDR,EAAUS,CAAC,CACZ,QAAA,CACCP,EAAiB,EAAK,CACvB,CACD,EACA,CAACN,CAAQ,CAAA,EAGJe,EAASnB,EAAAA,YACd,MAAOgB,EAAwBI,IAAsB,CACpDR,EAAQ,QAAQI,CAAc,IAAII,CAAS,EAAE,EAC7CN,EAAU,IAAI,EACd,GAAI,CACH,MAAMO,EAAM,MAAMC,EAASN,EAAgBI,CAAS,EACpDN,EACC,YAAYO,EAAI,mBAAmB,KAAKA,EAAI,aAAa,YAAA,CAE3D,OAASE,EAAG,CACXT,EAAU,gBAAiBS,EAAY,OAAO,EAAE,CACjD,QAAA,CACCX,EAAQ,IAAI,CACb,CACD,EACA,CAAA,CAAC,EAGIY,EAAWxB,EAAAA,YAChB,MAAOgB,EAAwBI,IAAsB,CACpDR,EAAQ,UAAUI,CAAc,IAAII,CAAS,EAAE,EAC/CN,EAAU,IAAI,EACd,GAAI,CACH,MAAMW,EAAeT,EAAgBI,CAAS,EAC9CN,EAAU,iCAAiCM,CAAS,EAAE,CACvD,OAASG,EAAG,CACXT,EAAU,kBAAmBS,EAAY,OAAO,EAAE,CACnD,QAAA,CACCX,EAAQ,IAAI,CACb,CACD,EACA,CAAA,CAAC,EAGF,OAAId,GAAS,CAACF,EACN8B,EAAAA,KAAC,MAAA,CAAI,UAAU,WAAW,SAAA,CAAA,wBAAsB5B,EAAM,OAAA,EAAQ,EAElED,GAAW,CAACD,EACR+B,EAAAA,IAAC,MAAA,CAAI,UAAU,WAAW,SAAA,iBAAc,EAE5C,CAAC/B,GAASA,EAAM,cAAc,SAAW,EAE3C8B,EAAAA,KAAC,MAAA,CAAI,UAAU,WACd,SAAA,CAAAC,EAAAA,IAAC,MAAG,SAAA,qBAAA,CAAmB,SACtB,IAAA,CAAE,SAAA,CAAA,uDACmD,IACrDA,EAAAA,IAAC,QAAK,SAAA,wBAAA,CAAsB,EAAO,uHAAA,CAAA,CAGpC,CAAA,EACD,EAKDD,EAAAA,KAAC,MAAA,CAAI,UAAU,YACd,SAAA,CAAAC,EAAAA,IAAC,MAAG,SAAA,uCAAA,CAAqC,EACxCd,GAAUc,EAAAA,IAAC,MAAA,CAAI,UAAU,eAAgB,SAAAd,EAAO,EAEhDX,GAAWA,EAAQ,QAAQ,OAAS,GACpCwB,OAAC,UAAA,CAAQ,UAAU,gBAClB,SAAA,CAAAA,OAAC,KAAA,CAAG,SAAA,CAAA,2BAAyBxB,EAAQ,QAAQ,OAAO,GAAA,EAAC,EACrDyB,EAAAA,IAAC,MACC,SAAAzB,EAAQ,QAAQ,IAAK0B,UACpB,KAAA,CACC,SAAA,CAAAvC,EAAMuC,EAAE,SAAS,EAAE,aAAUD,EAAAA,IAAC,OAAA,CAAM,SAAAC,EAAE,cAAA,CAAe,EAAO,YACvDA,EAAE,eAAA,GAFAA,EAAE,EAGX,CACA,CAAA,CACF,CAAA,EACD,EAGDF,EAAAA,KAAC,UAAA,CAAQ,UAAU,kBAClB,SAAA,CAAAA,OAAC,KAAA,CAAG,SAAA,CAAA,kBAAgB9B,EAAM,cAAc,OAAO,GAAA,EAAC,EAChD8B,EAAAA,KAAC,QAAA,CAAM,UAAU,cAChB,SAAA,CAAAC,EAAAA,IAAC,QAAA,CACA,gBAAC,KAAA,CACA,SAAA,CAAAA,EAAAA,IAAC,MAAG,SAAA,cAAA,CAAY,EAChBA,EAAAA,IAAC,MAAG,SAAA,OAAA,CAAK,EACTA,EAAAA,IAAC,MAAG,SAAA,QAAA,CAAM,EACVA,EAAAA,IAAC,MAAG,SAAA,QAAA,CAAM,EACVA,EAAAA,IAAC,MAAG,SAAA,UAAA,CAAQ,EACZA,EAAAA,IAAC,MAAG,SAAA,WAAA,CAAS,QACZ,KAAA,CAAA,CAAG,CAAA,CAAA,CACL,CAAA,CACD,QACC,QAAA,CACC,SAAA/B,EAAM,cAAc,IAAKiC,GACzBF,EAAAA,IAACG,EAAA,CAEA,EAAAD,EACA,OAAQjC,EAAM,uBAAyBiC,EAAE,eACzC,SAAUzB,IAAayB,EAAE,eACzB,SAAU,IAAMd,EAAOc,EAAE,cAAc,CAAA,EAJlCA,EAAE,cAAA,CAMR,CAAA,CACF,CAAA,CAAA,CACD,CAAA,EACD,EAECzB,GACAsB,EAAAA,KAAC,UAAA,CAAQ,UAAU,eAClB,SAAA,CAAAA,OAAC,KAAA,CAAG,SAAA,CAAA,YACMC,EAAAA,IAAC,QAAM,SAAAvB,CAAA,CAAS,CAAA,EAC1B,EACCK,EACAkB,EAAAA,IAAC,MAAA,CAAI,UAAU,WAAW,SAAA,gBAAA,CAAc,EACrCpB,EACHoB,EAAAA,IAACI,EAAA,CACA,OAAAxB,EACA,KAAAI,EACA,OAAAQ,EACA,SAAAK,CAAA,CAAA,EAGDG,EAAAA,IAAC,MAAA,CAAI,UAAU,WAAW,SAAA,YAAA,CAAU,CAAA,CAAA,CAEtC,CAAA,EAEF,CAEF,CAEA,SAASG,EAAgB,CACxB,EAAAD,EACA,OAAAG,EACA,SAAA5B,EACA,SAAA6B,CACD,EAKuB,CACtB,OACCN,MAAAO,EAAAA,SAAA,CACC,SAAAR,EAAAA,KAAC,KAAA,CACA,UAAWM,EAAS,mBAAqB,YACzC,QAASC,EACT,MAAO,CAAE,OAAQ,SAAA,EAEjB,SAAA,CAAAP,OAAC,KAAA,CACC,SAAA,CAAAtB,EAAW,IAAM,IAAI,IAACuB,EAAAA,IAAC,OAAA,CAAM,SAAAE,EAAE,cAAA,CAAe,EAC9CG,GAAUL,EAAAA,IAAC,OAAA,CAAK,UAAU,OAAO,SAAA,QAAA,CAAM,CAAA,EACzC,EACAA,EAAAA,IAAC,KAAA,CAAI,SAAAE,EAAE,SAAA,CAAU,EACjBF,EAAAA,IAAC,KAAA,CAAI,SAAAE,EAAE,WAAA,CAAY,EACnBF,EAAAA,IAAC,KAAA,CAAI,SAAAE,EAAE,UAAA,CAAW,SACjB,KAAA,CAAK,SAAA,EAAAA,EAAE,cAAgB,KAAK,QAAQ,CAAC,EAAE,GAAA,EAAC,EACzCF,EAAAA,IAAC,KAAA,CAAI,SAAAtC,EAAMwC,EAAE,UAAU,EAAE,QACxB,KAAA,CAAA,CAAG,CAAA,CAAA,CAAA,EAEN,CAEF,CAEA,SAASE,EAAW,CACnB,OAAAxB,EACA,KAAAI,EACA,OAAAQ,EACA,SAAAK,CACD,EAKuB,CACtB,OACCE,EAAAA,KAAC,QAAA,CAAM,UAAU,qBAChB,SAAA,CAAAC,EAAAA,IAAC,QAAA,CACA,gBAAC,KAAA,CACA,SAAA,CAAAA,EAAAA,IAAC,MAAG,SAAA,GAAA,CAAC,EACLA,EAAAA,IAAC,MAAG,SAAA,MAAA,CAAI,EACRA,EAAAA,IAAC,MAAG,SAAA,KAAA,CAAG,EACPA,EAAAA,IAAC,MAAG,SAAA,MAAA,CAAI,EACRA,EAAAA,IAAC,MAAG,SAAA,OAAA,CAAK,EACTA,EAAAA,IAAC,MAAG,SAAA,sCAAA,CAAoC,EACxCA,EAAAA,IAAC,MAAG,SAAA,OAAA,CAAK,EACTA,EAAAA,IAAC,MAAG,SAAA,SAAA,CAAO,CAAA,CAAA,CACZ,CAAA,CACD,EACAA,EAAAA,IAAC,SACC,SAAApB,EAAO,MAAM,IAAK4B,UACjB,KAAA,CACA,SAAA,CAAAR,EAAAA,IAAC,KAAA,CAAI,WAAE,SAAA,CAAU,EACjBA,EAAAA,IAAC,KAAA,CAAI,SAAAQ,EAAE,IAAA,CAAK,SACX,KAAA,CACC,SAAA,CAAAA,EAAE,WAAa,IACfA,EAAE,YAAc,MAChBT,EAAAA,KAAC,OAAA,CAAK,UAAU,QACd,SAAA,CAAA,IAAI,MACDS,EAAE,WAAa,KAAK,QAAQ,CAAC,EAAE,GAAA,CAAA,CACpC,CAAA,EAEF,EACAR,EAAAA,IAAC,KAAA,CACA,SAAAA,EAAAA,IAAC,OAAA,CAAK,UAAWpC,EAAU4C,EAAE,YAAY,EACvC,SAAAA,EAAE,cAAgB,GAAA,CACpB,EACD,EACAR,EAAAA,IAAC,KAAA,CAAI,SAAAQ,EAAE,QAAUR,EAAAA,IAAC,OAAA,CAAM,SAAAQ,EAAE,QAAQ,MAAM,EAAG,CAAC,CAAA,CAAE,EAAU,IAAI,EAC5DR,EAAAA,IAAC,KAAA,CAAG,UAAU,cACZ,SAAAQ,EAAE,OAAO,SAAW,EACpBR,EAAAA,IAAC,OAAA,CAAK,UAAU,QAAQ,aAAC,EAEzBA,EAAAA,IAAC,KAAA,CAAG,UAAU,cACZ,SAAAQ,EAAE,OAAO,IAAKC,GACdV,EAAAA,KAAC,KAAA,CACA,SAAA,CAAAC,MAAC,QAAM,SAAAS,EAAE,aAAa,MAAM,EAAG,EAAE,EAAE,EAAQ,IAC3CV,EAAAA,KAAC,OAAA,CAAK,UAAU,QACd,SAAA,CAAAjC,EAAY2C,EAAE,MAAM,EAAE,MAAIA,EAAE,MAAM,QAAQ,CAAC,EAC3CA,EAAE,aAAe,KAAO,OAAOA,EAAE,WAAW,GAAK,EAAA,CAAA,CACnD,CAAA,CAAA,EALQA,EAAE,YAMX,CACA,CAAA,CACF,CAAA,CAEF,EACAT,EAAAA,IAAC,KAAA,CAAI,SAAAtC,EAAM8C,EAAE,OAAO,EAAE,EACtBT,EAAAA,KAAC,KAAA,CAAG,UAAU,eACb,SAAA,CAAAC,EAAAA,IAAC,SAAA,CACA,KAAK,SACL,UAAU,WACV,SAAUhB,IAAS,KACnB,QAAS,IAAMQ,EAAOgB,EAAE,eAAgBA,EAAE,SAAS,EACnD,SAAA,MAAA,CAAA,EAGDR,EAAAA,IAAC,SAAA,CACA,KAAK,SACL,UAAU,WACV,SAAUhB,IAAS,KACnB,QAAS,IAAMa,EAASW,EAAE,eAAgBA,EAAE,SAAS,EACrD,SAAA,QAAA,CAAA,CAED,CAAA,CACD,CAAA,GArDQ,GAAGA,EAAE,cAAc,IAAIA,EAAE,SAAS,EAsD3C,CACA,CAAA,CACF,CAAA,EACD,CAEF"}
|
|
1
|
+
{"version":3,"file":"TurnsTab-CLNM0T5R.js","sources":["../../src/tabs/TurnsTab.tsx"],"sourcesContent":["/**\n * dashboard-client/src/tabs/TurnsTab.tsx — Turn-by-turn memory tracking + recall (S52).\n *\n * Fetches /api/turns (conversation list), expands the active conversation into\n * per-turn detail (/api/turns/conversation/:id), and renders:\n * - Conversation summary list (turn count, recall total, epochs, last turn).\n * - Per-turn rows: turn index, role, ctx tokens/percent + pressure band,\n * epoch id, and the injected-checkpoint recall set (the memory recalled\n * at each turn, with score + source).\n * - Pending rewind intents (S52A) + Fork action (S50C primitive).\n *\n * Read-mostly via /api/turns; fork/intent/prune via POST. No absolute URLs\n * (PREVENT-PI-004: loopback-only, same-origin static bundle).\n */\n\nimport type React from \"react\";\nimport { useCallback, useState } from \"react\";\nimport { useApi } from \"../hooks/useApi\";\nimport {\n\tfetchTurns,\n\tfetchConversationTurns,\n\tfetchTurnIntents,\n\tpostFork,\n\tpostTurnIntent,\n} from \"../api/client\";\nimport type {\n\tTurnsResponse,\n\tConversationTurnsResponse,\n\tRewindIntentsResponse,\n\tTurnRow,\n\tConversationSummary,\n} from \"@contracts\";\n\nfunction fmtTs(ms: number): string {\n\tif (!ms) return \"—\";\n\treturn new Date(ms).toLocaleString();\n}\n\nfunction bandClass(band: TurnRow[\"pressureBand\"]): string {\n\tif (band === \"green\") return \"band band-green\";\n\tif (band === \"yellow\") return \"band band-yellow\";\n\tif (band === \"red\") return \"band band-red\";\n\treturn \"band\";\n}\n\nfunction sourceLabel(s: TurnRow[\"recall\"][number][\"source\"]): string {\n\tif (s === \"checkpoint\") return \"ckpt\";\n\tif (s === \"cluster_summary\") return \"raptor\";\n\treturn \"mem\";\n}\n\nexport default function TurnsTab(): React.ReactElement {\n\tconst {\n\t\tdata: turns,\n\t\tloading,\n\t\terror,\n\t} = useApi<TurnsResponse>(\n\t\tuseCallback(() => fetchTurns(), []),\n\t\t{\n\t\t\tpollInterval: 10_000,\n\t\t},\n\t);\n\tconst { data: intents } = useApi<RewindIntentsResponse>(\n\t\tuseCallback(() => fetchTurnIntents(), []),\n\t\t{ pollInterval: 5_000 },\n\t);\n\tconst [expanded, setExpanded] = useState<string | null>(null);\n\tconst [detail, setDetail] = useState<ConversationTurnsResponse | null>(null);\n\tconst [detailLoading, setDetailLoading] = useState(false);\n\tconst [busy, setBusy] = useState<string | null>(null);\n\tconst [notice, setNotice] = useState<string | null>(null);\n\n\tconst expand = useCallback(\n\t\tasync (conversationId: string) => {\n\t\t\tif (expanded === conversationId) {\n\t\t\t\tsetExpanded(null);\n\t\t\t\tsetDetail(null);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsetExpanded(conversationId);\n\t\t\tsetDetailLoading(true);\n\t\t\tsetDetail(null);\n\t\t\ttry {\n\t\t\t\tconst d = await fetchConversationTurns(conversationId);\n\t\t\t\tsetDetail(d);\n\t\t\t} finally {\n\t\t\t\tsetDetailLoading(false);\n\t\t\t}\n\t\t},\n\t\t[expanded],\n\t);\n\n\tconst onFork = useCallback(\n\t\tasync (conversationId: string, turnIndex: number) => {\n\t\t\tsetBusy(`fork:${conversationId}:${turnIndex}`);\n\t\t\tsetNotice(null);\n\t\t\ttry {\n\t\t\t\tconst out = await postFork(conversationId, turnIndex);\n\t\t\t\tsetNotice(\n\t\t\t\t\t`Forked → ${out.childConversationId} (${out.recalledCount} recalled)`,\n\t\t\t\t);\n\t\t\t} catch (e) {\n\t\t\t\tsetNotice(`Fork failed: ${(e as Error).message}`);\n\t\t\t} finally {\n\t\t\t\tsetBusy(null);\n\t\t\t}\n\t\t},\n\t\t[],\n\t);\n\n\tconst onRewind = useCallback(\n\t\tasync (conversationId: string, turnIndex: number) => {\n\t\t\tsetBusy(`rewind:${conversationId}:${turnIndex}`);\n\t\t\tsetNotice(null);\n\t\t\ttry {\n\t\t\t\tawait postTurnIntent(conversationId, turnIndex);\n\t\t\t\tsetNotice(`Rewind intent queued for turn ${turnIndex}`);\n\t\t\t} catch (e) {\n\t\t\t\tsetNotice(`Rewind failed: ${(e as Error).message}`);\n\t\t\t} finally {\n\t\t\t\tsetBusy(null);\n\t\t\t}\n\t\t},\n\t\t[],\n\t);\n\n\tif (error && !turns) {\n\t\treturn <div className=\"tab-stub\">Error loading turns: {error.message}</div>;\n\t}\n\tif (loading && !turns) {\n\t\treturn <div className=\"tab-stub\">Loading turns…</div>;\n\t}\n\tif (!turns || turns.conversations.length === 0) {\n\t\treturn (\n\t\t\t<div className=\"tab-stub\">\n\t\t\t\t<h3>Turn-by-turn memory</h3>\n\t\t\t\t<p>\n\t\t\t\t\tNo turns recorded yet. Per-turn tracking starts when{\" \"}\n\t\t\t\t\t<code>MEGACOMPACT_TURNS_DB=1</code> and the session runs through a\n\t\t\t\t\tcompaction. Each turn records its context metrics + the checkpoints\n\t\t\t\t\trecalled into it.\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<div className=\"turns-tab\">\n\t\t\t<h3>Turn-by-turn memory tracking + recall</h3>\n\t\t\t{notice && <div className=\"turns-notice\">{notice}</div>}\n\n\t\t\t{intents && intents.intents.length > 0 && (\n\t\t\t\t<section className=\"turns-intents\">\n\t\t\t\t\t<h4>Pending rewind intents ({intents.intents.length})</h4>\n\t\t\t\t\t<ul>\n\t\t\t\t\t\t{intents.intents.map((i) => (\n\t\t\t\t\t\t\t<li key={i.id}>\n\t\t\t\t\t\t\t\t{fmtTs(i.createdAt)} — rewind <code>{i.conversationId}</code> to\n\t\t\t\t\t\t\t\tturn {i.targetTurnIndex}\n\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</ul>\n\t\t\t\t</section>\n\t\t\t)}\n\n\t\t\t<section className=\"turns-conv-list\">\n\t\t\t\t<h4>Conversations ({turns.conversations.length})</h4>\n\t\t\t\t<table className=\"turns-table\">\n\t\t\t\t\t<thead>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<th>Conversation</th>\n\t\t\t\t\t\t\t<th>Turns</th>\n\t\t\t\t\t\t\t<th>Recall</th>\n\t\t\t\t\t\t\t<th>Epochs</th>\n\t\t\t\t\t\t\t<th>Avg ctx%</th>\n\t\t\t\t\t\t\t<th>Last turn</th>\n\t\t\t\t\t\t\t<th></th>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</thead>\n\t\t\t\t\t<tbody>\n\t\t\t\t\t\t{turns.conversations.map((c: ConversationSummary) => (\n\t\t\t\t\t\t\t<ConversationRow\n\t\t\t\t\t\t\t\tkey={c.conversationId}\n\t\t\t\t\t\t\t\tc={c}\n\t\t\t\t\t\t\t\tactive={turns.activeConversationId === c.conversationId}\n\t\t\t\t\t\t\t\texpanded={expanded === c.conversationId}\n\t\t\t\t\t\t\t\tonExpand={() => expand(c.conversationId)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</tbody>\n\t\t\t\t</table>\n\t\t\t</section>\n\n\t\t\t{expanded && (\n\t\t\t\t<section className=\"turns-detail\">\n\t\t\t\t\t<h4>\n\t\t\t\t\t\tTurns in <code>{expanded}</code>\n\t\t\t\t\t</h4>\n\t\t\t\t\t{detailLoading ? (\n\t\t\t\t\t\t<div className=\"tab-stub\">Loading turns…</div>\n\t\t\t\t\t) : detail ? (\n\t\t\t\t\t\t<TurnDetail\n\t\t\t\t\t\t\tdetail={detail}\n\t\t\t\t\t\t\tbusy={busy}\n\t\t\t\t\t\t\tonFork={onFork}\n\t\t\t\t\t\t\tonRewind={onRewind}\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<div className=\"tab-stub\">No detail.</div>\n\t\t\t\t\t)}\n\t\t\t\t</section>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nfunction ConversationRow({\n\tc,\n\tactive,\n\texpanded,\n\tonExpand,\n}: {\n\tc: ConversationSummary;\n\tactive: boolean;\n\texpanded: boolean;\n\tonExpand: () => void;\n}): React.ReactElement {\n\treturn (\n\t\t<>\n\t\t\t<tr\n\t\t\t\tclassName={active ? \"turns-row active\" : \"turns-row\"}\n\t\t\t\tonClick={onExpand}\n\t\t\t\tstyle={{ cursor: \"pointer\" }}\n\t\t\t>\n\t\t\t\t<td>\n\t\t\t\t\t{expanded ? \"▾\" : \"▸\"} <code>{c.conversationId}</code>\n\t\t\t\t\t{active && <span className=\"pill\">active</span>}\n\t\t\t\t</td>\n\t\t\t\t<td>{c.turnCount}</td>\n\t\t\t\t<td>{c.totalRecall}</td>\n\t\t\t\t<td>{c.epochCount}</td>\n\t\t\t\t<td>{(c.avgCtxPercent * 100).toFixed(0)}%</td>\n\t\t\t\t<td>{fmtTs(c.lastTurnAt)}</td>\n\t\t\t\t<td />\n\t\t\t</tr>\n\t\t</>\n\t);\n}\n\nfunction TurnDetail({\n\tdetail,\n\tbusy,\n\tonFork,\n\tonRewind,\n}: {\n\tdetail: ConversationTurnsResponse;\n\tbusy: string | null;\n\tonFork: (conversationId: string, turnIndex: number) => void;\n\tonRewind: (conversationId: string, turnIndex: number) => void;\n}): React.ReactElement {\n\treturn (\n\t\t<table className=\"turns-detail-table\">\n\t\t\t<thead>\n\t\t\t\t<tr>\n\t\t\t\t\t<th>#</th>\n\t\t\t\t\t<th>Role</th>\n\t\t\t\t\t<th>Ctx</th>\n\t\t\t\t\t<th>Band</th>\n\t\t\t\t\t<th>Epoch</th>\n\t\t\t\t\t<th>Recalled checkpoints (memory recall)</th>\n\t\t\t\t\t<th>Ended</th>\n\t\t\t\t\t<th>Actions</th>\n\t\t\t\t</tr>\n\t\t\t</thead>\n\t\t\t<tbody>\n\t\t\t\t{detail.turns.map((t) => (\n\t\t\t\t\t<tr key={`${t.conversationId}:${t.turnIndex}`}>\n\t\t\t\t\t\t<td>{t.turnIndex}</td>\n\t\t\t\t\t\t<td>{t.role}</td>\n\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t{t.ctxTokens ?? \"—\"}\n\t\t\t\t\t\t\t{t.ctxPercent != null && (\n\t\t\t\t\t\t\t\t<span className=\"muted\">\n\t\t\t\t\t\t\t\t\t{\" \"}\n\t\t\t\t\t\t\t\t\t· {(t.ctxPercent * 100).toFixed(0)}%\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t<span className={bandClass(t.pressureBand)}>\n\t\t\t\t\t\t\t\t{t.pressureBand ?? \"—\"}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td>{t.epochId ? <code>{t.epochId.slice(0, 8)}</code> : \"—\"}</td>\n\t\t\t\t\t\t<td className=\"recall-cell\">\n\t\t\t\t\t\t\t{t.recall.length === 0 ? (\n\t\t\t\t\t\t\t\t<span className=\"muted\">—</span>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<ul className=\"recall-list\">\n\t\t\t\t\t\t\t\t\t{t.recall.map((r) => (\n\t\t\t\t\t\t\t\t\t\t<li key={r.checkpointId}>\n\t\t\t\t\t\t\t\t\t\t\t<code>{r.checkpointId.slice(0, 12)}</code>{\" \"}\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"muted\">\n\t\t\t\t\t\t\t\t\t\t\t\t{sourceLabel(r.source)} · {r.score.toFixed(2)}\n\t\t\t\t\t\t\t\t\t\t\t\t{r.raptorLevel != null ? ` · L${r.raptorLevel}` : \"\"}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</ul>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td>{fmtTs(t.endedAt)}</td>\n\t\t\t\t\t\t<td className=\"actions-cell\">\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclassName=\"mini-btn\"\n\t\t\t\t\t\t\t\tdisabled={busy !== null}\n\t\t\t\t\t\t\t\tonClick={() => onFork(t.conversationId, t.turnIndex)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tfork\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclassName=\"mini-btn\"\n\t\t\t\t\t\t\t\tdisabled={busy !== null}\n\t\t\t\t\t\t\t\tonClick={() => onRewind(t.conversationId, t.turnIndex)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\trewind\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t</tr>\n\t\t\t\t))}\n\t\t\t</tbody>\n\t\t</table>\n\t);\n}\n"],"names":["fmtTs","ms","bandClass","band","sourceLabel","s","TurnsTab","turns","loading","error","useApi","useCallback","fetchTurns","intents","fetchTurnIntents","expanded","setExpanded","useState","detail","setDetail","detailLoading","setDetailLoading","busy","setBusy","notice","setNotice","expand","conversationId","d","fetchConversationTurns","onFork","turnIndex","out","postFork","e","onRewind","postTurnIntent","jsxs","jsx","i","c","ConversationRow","TurnDetail","active","onExpand","Fragment","t","r"],"mappings":"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"}
|