pi-mega-compact 0.20.62 → 0.20.64

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.
Files changed (90) hide show
  1. package/dist/config/vector-cortex-enc2a.js +35 -0
  2. package/dist/config/vector-cortex.js +2 -0
  3. package/dist/config.js +1 -1
  4. package/dist/extensions/dashboard-server/routes-rag-settings-vector-cortex.js +1 -0
  5. package/dist/extensions/dashboard-server/routes-setup-enc2a.js +119 -0
  6. package/dist/extensions/dashboard-server/routes-setup.js +26 -0
  7. package/dist/src/config/vector-cortex-enc2a.js +35 -0
  8. package/dist/src/config/vector-cortex.js +2 -0
  9. package/dist/src/config.js +1 -1
  10. package/dist/src/vector-cortex/encoder/native-install-artifacts.js +43 -0
  11. package/dist/vector-cortex/encoder/native-install-artifacts.js +43 -0
  12. package/extensions/dashboard-client/dist/assets/{AdminTab-DEjVnlwe.js → AdminTab-sjV8P5A4.js} +2 -2
  13. package/extensions/dashboard-client/dist/assets/{AdminTab-DEjVnlwe.js.map → AdminTab-sjV8P5A4.js.map} +1 -1
  14. package/extensions/dashboard-client/dist/assets/{AreaChart-B1PoTqKJ.js → AreaChart-C03yuld4.js} +2 -2
  15. package/extensions/dashboard-client/dist/assets/{AreaChart-B1PoTqKJ.js.map → AreaChart-C03yuld4.js.map} +1 -1
  16. package/extensions/dashboard-client/dist/assets/{BarChart-DaoONT_V.js → BarChart-B9jtJ7ud.js} +2 -2
  17. package/extensions/dashboard-client/dist/assets/{BarChart-DaoONT_V.js.map → BarChart-B9jtJ7ud.js.map} +1 -1
  18. package/extensions/dashboard-client/dist/assets/{CacheTab-rD5sjlkW.js → CacheTab-B7Eh3qfp.js} +2 -2
  19. package/extensions/dashboard-client/dist/assets/{CacheTab-rD5sjlkW.js.map → CacheTab-B7Eh3qfp.js.map} +1 -1
  20. package/extensions/dashboard-client/dist/assets/{ConfigTab-BQkufK7t.js → ConfigTab-DDTqosv2.js} +2 -2
  21. package/extensions/dashboard-client/dist/assets/{ConfigTab-BQkufK7t.js.map → ConfigTab-DDTqosv2.js.map} +1 -1
  22. package/extensions/dashboard-client/dist/assets/{EventsTab-DGlQzJaT.js → EventsTab-BmyQGmUa.js} +2 -2
  23. package/extensions/dashboard-client/dist/assets/{EventsTab-DGlQzJaT.js.map → EventsTab-BmyQGmUa.js.map} +1 -1
  24. package/extensions/dashboard-client/dist/assets/{HealthTab-DW7kt4qm.js → HealthTab-DzPqNqpm.js} +2 -2
  25. package/extensions/dashboard-client/dist/assets/{HealthTab-DW7kt4qm.js.map → HealthTab-DzPqNqpm.js.map} +1 -1
  26. package/extensions/dashboard-client/dist/assets/{MaintenanceTab-CGiZ0OQ6.js → MaintenanceTab-6g3d-M1p.js} +2 -2
  27. package/extensions/dashboard-client/dist/assets/{MaintenanceTab-CGiZ0OQ6.js.map → MaintenanceTab-6g3d-M1p.js.map} +1 -1
  28. package/extensions/dashboard-client/dist/assets/{MemoryMapTab-BwyrxjuW.js → MemoryMapTab-Nk2yYPMS.js} +2 -2
  29. package/extensions/dashboard-client/dist/assets/{MemoryMapTab-BwyrxjuW.js.map → MemoryMapTab-Nk2yYPMS.js.map} +1 -1
  30. package/extensions/dashboard-client/dist/assets/{MetricsCards-IZaCOOXU.js → MetricsCards-BlIiuZp5.js} +2 -2
  31. package/extensions/dashboard-client/dist/assets/{MetricsCards-IZaCOOXU.js.map → MetricsCards-BlIiuZp5.js.map} +1 -1
  32. package/extensions/dashboard-client/dist/assets/MetricsTab-DfRDIAEU.js +2 -0
  33. package/extensions/dashboard-client/dist/assets/{MetricsTab-wCxVpHlC.js.map → MetricsTab-DfRDIAEU.js.map} +1 -1
  34. package/extensions/dashboard-client/dist/assets/{OverviewTab-DsH08Wr0.js → OverviewTab-xkuFE5GV.js} +2 -2
  35. package/extensions/dashboard-client/dist/assets/{OverviewTab-DsH08Wr0.js.map → OverviewTab-xkuFE5GV.js.map} +1 -1
  36. package/extensions/dashboard-client/dist/assets/{ReposTab-Dpb7sXWB.js → ReposTab-C6qZmmgQ.js} +2 -2
  37. package/extensions/dashboard-client/dist/assets/{ReposTab-Dpb7sXWB.js.map → ReposTab-C6qZmmgQ.js.map} +1 -1
  38. package/extensions/dashboard-client/dist/assets/{SessionsTab-DFMo7tKA.js → SessionsTab-Bkd_In3n.js} +2 -2
  39. package/extensions/dashboard-client/dist/assets/{SessionsTab-DFMo7tKA.js.map → SessionsTab-Bkd_In3n.js.map} +1 -1
  40. package/extensions/dashboard-client/dist/assets/SetupTab-CEXL71VP.js +3 -0
  41. package/extensions/dashboard-client/dist/assets/SetupTab-CEXL71VP.js.map +1 -0
  42. package/extensions/dashboard-client/dist/assets/{TimeSavedCard-BGPvmVFG.js → TimeSavedCard-Dr0KNUed.js} +2 -2
  43. package/extensions/dashboard-client/dist/assets/{TimeSavedCard-BGPvmVFG.js.map → TimeSavedCard-Dr0KNUed.js.map} +1 -1
  44. package/extensions/dashboard-client/dist/assets/{TurnMemoryView-BZo09Jri.js → TurnMemoryView-CjmSiRQ_.js} +2 -2
  45. package/extensions/dashboard-client/dist/assets/{TurnMemoryView-BZo09Jri.js.map → TurnMemoryView-CjmSiRQ_.js.map} +1 -1
  46. package/extensions/dashboard-client/dist/assets/TurnsTab-JsDstDDA.js +2 -0
  47. package/extensions/dashboard-client/dist/assets/{TurnsTab-CosKNvMp.js.map → TurnsTab-JsDstDDA.js.map} +1 -1
  48. package/extensions/dashboard-client/dist/assets/{VcStatusBadge-UEZLL6Zj.js → VcStatusBadge-C96wfemg.js} +2 -2
  49. package/extensions/dashboard-client/dist/assets/{VcStatusBadge-UEZLL6Zj.js.map → VcStatusBadge-C96wfemg.js.map} +1 -1
  50. package/extensions/dashboard-client/dist/assets/{VectorCortexTab-fDAgD2pN.js → VectorCortexTab-DGV3kA7X.js} +2 -2
  51. package/extensions/dashboard-client/dist/assets/{VectorCortexTab-fDAgD2pN.js.map → VectorCortexTab-DGV3kA7X.js.map} +1 -1
  52. package/extensions/dashboard-client/dist/assets/{WikiTab-7TIe2MkS.js → WikiTab-EFfy5v-D.js} +2 -2
  53. package/extensions/dashboard-client/dist/assets/{WikiTab-7TIe2MkS.js.map → WikiTab-EFfy5v-D.js.map} +1 -1
  54. package/extensions/dashboard-client/dist/assets/{button-C9qrZYdn.js → button-CvaPx9Bu.js} +2 -2
  55. package/extensions/dashboard-client/dist/assets/{button-C9qrZYdn.js.map → button-CvaPx9Bu.js.map} +1 -1
  56. package/extensions/dashboard-client/dist/assets/{card-DxZRNC4E.js → card-Crs5SwRQ.js} +2 -2
  57. package/extensions/dashboard-client/dist/assets/{card-DxZRNC4E.js.map → card-Crs5SwRQ.js.map} +1 -1
  58. package/extensions/dashboard-client/dist/assets/{client-extra-Dj7wJs6Z.js → client-extra-Bd27WKSo.js} +2 -2
  59. package/extensions/dashboard-client/dist/assets/{client-extra-Dj7wJs6Z.js.map → client-extra-Bd27WKSo.js.map} +1 -1
  60. package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-Dj-DYUgL.js → generateCategoricalChart-qnHql9Es.js} +2 -2
  61. package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-Dj-DYUgL.js.map → generateCategoricalChart-qnHql9Es.js.map} +1 -1
  62. package/extensions/dashboard-client/dist/assets/{index-Bq2n15a4.js → index-B4twCFnn.js} +14 -14
  63. package/extensions/dashboard-client/dist/assets/index-B4twCFnn.js.map +1 -0
  64. package/extensions/dashboard-client/dist/assets/index-CfnincWA.css +1 -0
  65. package/extensions/dashboard-client/dist/assets/{switch-1sEgLPHu.js → switch-BXutQI5d.js} +2 -2
  66. package/extensions/dashboard-client/dist/assets/{switch-1sEgLPHu.js.map → switch-BXutQI5d.js.map} +1 -1
  67. package/extensions/dashboard-client/dist/assets/{toggle-jMzQoJ2C.js → toggle-uE-OSaba.js} +2 -2
  68. package/extensions/dashboard-client/dist/assets/{toggle-jMzQoJ2C.js.map → toggle-uE-OSaba.js.map} +1 -1
  69. package/extensions/dashboard-client/dist/assets/{useSSE-Dxy616R1.js → useSSE-BRgPAqeS.js} +2 -2
  70. package/extensions/dashboard-client/dist/assets/{useSSE-Dxy616R1.js.map → useSSE-BRgPAqeS.js.map} +1 -1
  71. package/extensions/dashboard-client/dist/index.html +2 -2
  72. package/extensions/dashboard-client/src/App.tsx +34 -7
  73. package/extensions/dashboard-client/src/styles/base.css +64 -1
  74. package/extensions/dashboard-client/src/tabs/SetupTab/CortexRuntimeInstallCard.tsx +103 -0
  75. package/extensions/dashboard-client/src/tabs/SetupTab/CortexSetup.tsx +2 -0
  76. package/extensions/dashboard-server/api-contracts/setup.ts +24 -0
  77. package/extensions/dashboard-server/routes-rag-settings-vector-cortex.ts +6 -0
  78. package/extensions/dashboard-server/routes-setup-enc2a.ts +140 -0
  79. package/extensions/dashboard-server/routes-setup.ts +26 -0
  80. package/package.json +1 -1
  81. package/src/config/vector-cortex-enc2a.ts +37 -0
  82. package/src/config/vector-cortex.ts +2 -0
  83. package/src/config.ts +1 -0
  84. package/src/vector-cortex/encoder/native-install-artifacts.ts +60 -0
  85. package/extensions/dashboard-client/dist/assets/MetricsTab-wCxVpHlC.js +0 -2
  86. package/extensions/dashboard-client/dist/assets/SetupTab-D2IEBt1u.js +0 -3
  87. package/extensions/dashboard-client/dist/assets/SetupTab-D2IEBt1u.js.map +0 -1
  88. package/extensions/dashboard-client/dist/assets/TurnsTab-CosKNvMp.js +0 -2
  89. package/extensions/dashboard-client/dist/assets/index-Bq2n15a4.js.map +0 -1
  90. package/extensions/dashboard-client/dist/assets/index-C_aDd9kk.css +0 -1
@@ -176,13 +176,16 @@ function NewDashboard({
176
176
  snapshot,
177
177
  loading,
178
178
  error,
179
+ viewToggle,
179
180
  }: AppState & {
180
181
  activeTab: TabId;
181
182
  setActiveTab: (id: TabId) => void;
183
+ viewToggle?: React.ReactNode;
182
184
  }): React.ReactElement {
183
185
  return (
184
186
  <ErrorBoundary>
185
187
  <AppShell active={activeTab} onTabChange={setActiveTab} snapshot={snapshot}>
188
+ {viewToggle ? <div className="view-toggle-wrap">{viewToggle}</div> : null}
186
189
  <LegacyContent activeTab={activeTab} snapshot={snapshot} loading={loading} error={error} />
187
190
  </AppShell>
188
191
  </ErrorBoundary>
@@ -217,6 +220,11 @@ function ConsolidatedNav({
217
220
 
218
221
  export default function App(): React.ReactElement {
219
222
  const [activeTab, setActiveTab] = useState<ActiveTab>("overview");
223
+ // DASH-0d consolidated 7-surface view is OPT-IN. The default is the full
224
+ // NewDashboard layout (left Sidebar + mobile BottomBar, 13 tabs). A toggle
225
+ // button (rendered when the consolidated code is available) lets the operator
226
+ // switch to the minimal 7-surface view on demand.
227
+ const [consolidatedView, setConsolidatedView] = useState(false);
220
228
  const {
221
229
  data: snapshot,
222
230
  loading,
@@ -235,6 +243,7 @@ export default function App(): React.ReactElement {
235
243
  { pollInterval: 0, maxRetries: 0 },
236
244
  );
237
245
  const dash0dOn = dash0dEnabled(settingsData);
246
+ const canConsolidate = NEW_UI() && dash0dOn;
238
247
 
239
248
  // Additive hash→surface deep-link router: every legacy #hash maps to a live
240
249
  // consolidated surface; empty hash keeps current behavior (default overview).
@@ -242,12 +251,27 @@ export default function App(): React.ReactElement {
242
251
  // pre-rollup 13-tab behavior unchanged (hash ignored).
243
252
  const hashSurface = useHashTab();
244
253
  useEffect(() => {
245
- if (dash0dOn && hashSurface != null) setActiveTab(hashSurface);
246
- }, [dash0dOn, hashSurface]);
254
+ if (canConsolidate && consolidatedView && hashSurface != null)
255
+ setActiveTab(hashSurface);
256
+ }, [canConsolidate, consolidatedView, hashSurface]);
247
257
 
248
- // Flag-ON consolidated New-UI surface: a 7-surface rail + the consolidated
249
- // content. Flag-OFF (or legacy NEW_UI false) renders the 13-tab path as today.
250
- if (NEW_UI() && dash0dOn) {
258
+ // The toggle button renders inside both view headers when the consolidated
259
+ // code is available. Default view = full (Sidebar+BottomBar); minimal = 7
260
+ // surfaces.
261
+ const ViewToggle = canConsolidate ? (
262
+ <button
263
+ type="button"
264
+ className="view-toggle-btn"
265
+ onClick={() => setConsolidatedView((v) => !v)}
266
+ aria-pressed={consolidatedView}
267
+ title={consolidatedView ? "Switch to full dashboard" : "Switch to minimal dashboard"}
268
+ >
269
+ {consolidatedView ? "Full view" : "Minimal view"}
270
+ </button>
271
+ ) : null;
272
+
273
+ // Consolidated 7-surface view — OPT-IN via the toggle button above.
274
+ if (canConsolidate && consolidatedView) {
251
275
  const current = DASH_SURFACE_IDS.includes(activeTab as DashTabId)
252
276
  ? (activeTab as DashTabId)
253
277
  : "overview";
@@ -256,6 +280,7 @@ export default function App(): React.ReactElement {
256
280
  <div className="dashboard-app">
257
281
  <header className="dashboard-header">
258
282
  <h1>mega-compact dashboard <span className="tier">{snapshot?.tier ?? "unknown"}</span></h1>
283
+ {ViewToggle}
259
284
  </header>
260
285
  <ConsolidatedNav active={current} onSelect={(id: DashTabId) => setActiveTab(id)} />
261
286
  <main className="dashboard-content">
@@ -271,8 +296,9 @@ export default function App(): React.ReactElement {
271
296
  );
272
297
  }
273
298
 
274
- // Flag-off (or legacy NEW_UI): always a legacy TabId (hash routing is gated
275
- // on dash0dOn above, so activeTab stays a 13-tab id here).
299
+ // Default view (full): always a legacy TabId (hash routing is gated on
300
+ // canConsolidate && consolidatedView above, so activeTab stays a 13-tab id
301
+ // here).
276
302
  const legacyTab = (activeTab as TabId) ?? "overview";
277
303
 
278
304
  if (NEW_UI()) {
@@ -283,6 +309,7 @@ export default function App(): React.ReactElement {
283
309
  snapshot={snapshot}
284
310
  loading={loading}
285
311
  error={error}
312
+ viewToggle={ViewToggle}
286
313
  />
287
314
  );
288
315
  }
@@ -43,10 +43,18 @@ body {
43
43
  gap: clamp(8px, 1.5vw, 16px);
44
44
  }
45
45
 
46
+ .dashboard-header {
47
+ display: flex;
48
+ align-items: center;
49
+ justify-content: space-between;
50
+ gap: 8px;
51
+ flex-wrap: wrap;
52
+ }
53
+
46
54
  .dashboard-header h1 {
47
55
  font-size: clamp(16px, 1.4vw, 22px);
48
56
  font-weight: 600;
49
- margin: 0 0 clamp(8px, 1vw, 16px);
57
+ margin: 0;
50
58
  }
51
59
 
52
60
  .dashboard-header .tier,
@@ -65,6 +73,61 @@ body {
65
73
  color: var(--accent);
66
74
  }
67
75
 
76
+ /* View toggle button — switches between full (default) and minimal 7-surface */
77
+ .view-toggle-btn {
78
+ background: var(--panel);
79
+ border: 1px solid var(--border);
80
+ color: var(--muted);
81
+ padding: 4px 12px;
82
+ font-size: clamp(11px, 0.8vw, 13px);
83
+ border-radius: 8px;
84
+ cursor: pointer;
85
+ white-space: nowrap;
86
+ transition: color 0.15s, border-color 0.15s;
87
+ }
88
+ .view-toggle-btn:hover {
89
+ color: var(--text);
90
+ border-color: var(--accent);
91
+ }
92
+ .view-toggle-btn[aria-pressed="true"] {
93
+ color: var(--accent);
94
+ border-color: var(--accent);
95
+ }
96
+ .view-toggle-wrap {
97
+ position: fixed;
98
+ top: 12px;
99
+ right: 16px;
100
+ z-index: 50;
101
+ }
102
+
103
+ /* Consolidated 7-surface nav — horizontal scrollable rail (mobile-friendly) */
104
+ .consolidated-nav {
105
+ display: flex;
106
+ gap: 4px;
107
+ overflow-x: auto;
108
+ flex-wrap: nowrap;
109
+ border-bottom: 1px solid var(--border);
110
+ margin-bottom: clamp(8px, 1vw, 16px);
111
+ padding-bottom: 2px;
112
+ }
113
+ .consolidated-nav button {
114
+ background: none;
115
+ border: none;
116
+ color: var(--muted);
117
+ padding: 8px 14px;
118
+ cursor: pointer;
119
+ font-size: clamp(12px, 0.85vw, 14px);
120
+ white-space: nowrap;
121
+ border-bottom: 2px solid transparent;
122
+ }
123
+ .consolidated-nav button.active {
124
+ color: var(--text);
125
+ border-bottom-color: var(--accent);
126
+ }
127
+ .consolidated-nav button:hover {
128
+ color: var(--text);
129
+ }
130
+
68
131
  .tab-bar {
69
132
  display: flex;
70
133
  gap: 4px;
@@ -0,0 +1,103 @@
1
+ /**
2
+ * SetupTab/CortexRuntimeInstallCard.tsx — operator-run install guide card
3
+ * (ENC-2a).
4
+ *
5
+ * Pure render. When `SetupStatusResponse.nativeOrtInstallGuide` is non-null
6
+ * (opt-in on, effective runtime still wasm, platform installable), this card
7
+ * surfaces the three copy-paste steps the operator runs OUTSIDE the dashboard:
8
+ * install onnxruntime-node, restart via pi, and the expected next status. When
9
+ * the guide is null the card hides entirely (the modifiers card already
10
+ * surfaces the honest ENC-0g state).
11
+ *
12
+ * NO client-side execution — the install script is never spawned from here.
13
+ * Data comes exclusively from the existing /api/setup-status poll.
14
+ */
15
+ import type React from "react";
16
+ import { useState, useCallback, useEffect } from "react";
17
+ import type { SetupStatusResponse } from "@contracts";
18
+ import { fetchSetupStatus } from "../../api/client";
19
+ import { styles } from "./CortexSetupStyles";
20
+
21
+ function useCopyState(): [boolean, (text: string) => Promise<void>] {
22
+ const [copied, setCopied] = useState(false);
23
+ const copy = useCallback(async (text: string) => {
24
+ try {
25
+ await navigator.clipboard.writeText(text);
26
+ setCopied(true);
27
+ window.setTimeout(() => setCopied(false), 1500);
28
+ } catch {
29
+ setCopied(false);
30
+ }
31
+ }, []);
32
+ return [copied, copy];
33
+ }
34
+
35
+ export default function CortexRuntimeInstallCard(): React.ReactElement {
36
+ const [status, setStatus] = useState<SetupStatusResponse | null>(null);
37
+ const [copied, copy] = useCopyState();
38
+
39
+ const loadStatus = useCallback(() => {
40
+ fetchSetupStatus()
41
+ .then(setStatus)
42
+ .catch(() => {
43
+ /* best-effort poll; hide card when unavailable */
44
+ });
45
+ }, []);
46
+
47
+ useEffect(() => {
48
+ loadStatus();
49
+ const id = setInterval(loadStatus, 5000);
50
+ return () => clearInterval(id);
51
+ }, [loadStatus]);
52
+
53
+ const guide = status?.nativeOrtInstallGuide ?? null;
54
+ const installedVersion = status?.nativeOrtInstalledVersion ?? null;
55
+ if (!guide) return <></>;
56
+
57
+ return (
58
+ <div style={styles.section}>
59
+ <h3 style={styles.sectionTitle}>Encoder Runtime Install</h3>
60
+ <p style={{ ...styles.label, fontSize: "0.85rem", marginBottom: "0.75rem" }}>
61
+ Platform: {guide.platform}
62
+ </p>
63
+ {installedVersion !== null && (
64
+ <div style={styles.row}>
65
+ <span style={styles.label}>Detected:</span>
66
+ <span style={styles.value}>{installedVersion}</span>
67
+ </div>
68
+ )}
69
+ {guide.commands.map((command, i) => (
70
+ <div key={`${i}-${command}`} style={styles.row}>
71
+ <span style={styles.label}>Step {i + 1}:</span>
72
+ <code
73
+ style={{
74
+ ...styles.mono,
75
+ display: "inline-block",
76
+ marginTop: "0.15rem",
77
+ }}
78
+ >
79
+ {command}
80
+ </code>
81
+ <button
82
+ type="button"
83
+ onClick={() => {
84
+ void copy(command);
85
+ }}
86
+ style={{ marginLeft: "0.5rem", fontSize: "0.8rem" }}
87
+ >
88
+ Copy
89
+ </button>
90
+ </div>
91
+ ))}
92
+ <p style={{ ...styles.row, fontSize: "0.85rem" }}>
93
+ <span style={styles.label}>Script:</span>{" "}
94
+ <code style={styles.mono}>{guide.scriptPath}</code>
95
+ </p>
96
+ {copied && (
97
+ <p style={{ color: "#4caf50", fontSize: "0.8rem", margin: "0.25rem 0 0" }}>
98
+ Copied to clipboard
99
+ </p>
100
+ )}
101
+ </div>
102
+ );
103
+ }
@@ -15,6 +15,7 @@ import { CortexEncoderCard } from "./CortexEncoderCard";
15
15
  import { CortexBlockersCard } from "./CortexBlockersCard";
16
16
  import { CortexActionsCard } from "./CortexActionsCard";
17
17
  import CortexRuntimeCard from "./CortexRuntimeCard";
18
+ import CortexRuntimeInstallCard from "./CortexRuntimeInstallCard";
18
19
  import { VectorCortexCosineFpCard } from "./VectorCortexCosineFpCard";
19
20
  import { VectorCortexRepoCorpusCard } from "./VectorCortexRepoCorpusCard";
20
21
  import { styles } from "./CortexSetupStyles";
@@ -43,6 +44,7 @@ export default function CortexSetup(): React.ReactElement {
43
44
 
44
45
  <CortexEncoderCard data={state.data} error={state.error} />
45
46
  <CortexRuntimeCard />
47
+ <CortexRuntimeInstallCard />
46
48
  <VectorCortexCosineFpCard />
47
49
  <VectorCortexRepoCorpusCard />
48
50
  <CortexBlockersCard
@@ -64,6 +64,25 @@ export interface SetupStatusResponse {
64
64
  * operand — persists even when `nativeOrtBudgetMib` is absent because the
65
65
  * runtime applies the default when unset. Additive, flag-gated. */
66
66
  readonly nativeOrtBudgetEffectiveMib?: string;
67
+ /** ENC-2a: the native onnxruntime install-guide, present (as an object) when
68
+ * the operator opted into the native backend AND the effective runtime is
69
+ * still wasm (onnxruntime-node absent) AND the host platform is installable.
70
+ * `null` when opt-in is off or the platform is unsupported/demoted (the guide
71
+ * never renders). Built ONLY from the artifacts module constants — no inline
72
+ * URLs or hashes in the route. Additive, flag-gated; absent = no guide. */
73
+ readonly nativeOrtInstallGuide?: {
74
+ /** The host's EncoderPlatform this guide is matched to. */
75
+ readonly platform: string;
76
+ /** The [install, restart, verify] copy-paste commands. */
77
+ readonly commands: readonly string[];
78
+ /** The committed operator script path (repo-rel). */
79
+ readonly scriptPath: string;
80
+ } | null;
81
+ /** ENC-2a: the installed native onnxruntime version read from
82
+ * `~/.pi/mega-compact/native-ort/` when the probe marker/package is present
83
+ * and platform-matched. Absent (NOT null) when not installed, so the client
84
+ * hides the detected-version row. Additive, flag-gated, reader-only. */
85
+ readonly nativeOrtInstalledVersion?: string | null;
67
86
  }
68
87
 
69
88
  /**
@@ -132,6 +151,11 @@ export interface SetupConfigureRequest {
132
151
  * positive integer string within `ENC_2BUDGET_MAX_MIB` (validated; additive,
133
152
  * flag-gated). */
134
153
  readonly nativeOrtBudgetMib?: string;
154
+ /** ENC-2a: an optional { boolean } guide-request key. `true` → 200 + the
155
+ * guide echoed (this sprint conveys the GUIDE only — no server-side
156
+ * execution); `false` → 400 `guide_rejected_false_nothing_to_do`.
157
+ * Flag-gated, additive — ignored (no-op) when the flag is off. */
158
+ readonly nativeOrtInstallGuide?: boolean;
135
159
  }
136
160
 
137
161
  /** Response for POST /api/setup-configure. */
@@ -314,6 +314,12 @@ export const VECTOR_CORTEX_SETTINGS: SettingGroup = {
314
314
  "ENC-2a exposes the runtime operator knob MEGACOMPACT_NATIVE_ORT_BUDGET_MIB (default 300 MiB, clamp 8192) as a dashboard Settings field. The knob gates budgetOk in the encoder runtime decision (decision.ts installBudgetMib + runtime-select.ts selectRuntimeBackend). Persisted to the per-repo .mega-compact.env via the setup-configure writer branch; the GET status route surfaces the persisted value AND the effective integer installBudgetMib() resolves to (so the dashboard shows the runtime's actual operand). OFF = no new GET fields, no writer branch, no new Settings rows (byte-identical ENC-1b predecessor).",
315
315
  true,
316
316
  ),
317
+ boolDirect(
318
+ "MEGACOMPACT_ENC_2A",
319
+ "ENC-2a native onnxruntime install GUIDE (detect + copy-paste)",
320
+ "ENC-2a surfaces the platform-matched native onnxruntime install-guide (three copy-paste steps + script path) on the Setup Cortex sub-tab when the operator opted into the native backend but the effective runtime is still wasm (onnxruntime-node absent). Pure guidance — the extension NEVER executes or fetches (PREVENT-PI-004 unchanged); the committed operator script scripts/encoder/install-native-ort.mjs runs in the USER's shell. OFF = no guide GET fields, no guide-request POST branch, no install card (byte-identical ENC-1b predecessor).",
321
+ true,
322
+ ),
317
323
  boolDirect(
318
324
  "MEGACOMPACT_COSINE_FP_BENCH",
319
325
  "COS-FP-A Synthetic FP Bench",
@@ -0,0 +1,140 @@
1
+ /**
2
+ * dashboard-server/routes-setup-enc2a.ts — ENC-2a native onnxruntime install
3
+ * GUIDE (reader-only) + installed-version probe.
4
+ *
5
+ * Extracted out of routes-setup.ts (which hovers at the 300-line source soft
6
+ * cap, mirroring the ENC-1a/ENC-1b/ENC-2budget sibling extracts) so the
7
+ * ENC-2a additive GET fields — the platform-matched native install guide and
8
+ * the installed-version probe — live in a sibling impl file and routes-setup.ts
9
+ * stays a thin host.
10
+ *
11
+ * The guide's job is OPERATOR run-script assist: when the operator opted into
12
+ * the native backend (`MEGACOMPACT_ENCODER_NATIVE=1`) but the effective runtime
13
+ * is still `"wasm"` (onnxruntime-node not yet installed) AND the host platform
14
+ * is installable, the GET status response carries a `nativeOrtInstallGuide`
15
+ * object with the [install, restart, verify] copy-paste commands + the committed
16
+ * operator script path. The commands/URL/hash are built ONLY from the artifacts
17
+ * module constants (`src/vector-cortex/encoder/native-install-artifacts.ts`) —
18
+ * never an inline registry URL or literal hash (PREVENT-PI-004). The installed-
19
+ * version probe reads the local `~/.pi/mega-compact/native-ort/` package.json
20
+ * when present (reader-only filesystem read, zero network).
21
+ *
22
+ * The flag is off (or opt-in off / unsupported platform / non-wasm backend) ->
23
+ * guide `null` and installedVersion `null` -> the host omits both fields,
24
+ * byte-identical to the ENC-1b-era shape.
25
+ *
26
+ * Guardrails: PREVENT-PI-004 (local filesystem reads + in-memory backend
27
+ * selection only, zero network), PREVENT-001 (null-safe JSON), PREVENT-011
28
+ * (no `any`).
29
+ */
30
+
31
+ import { readFileSync, existsSync } from "node:fs";
32
+ import { join } from "node:path";
33
+ import { ENC_2A_ENABLED } from "../../src/config/vector-cortex.js";
34
+ import { readEnc1bEnv } from "./routes-setup-enc1b.js";
35
+ import { selectRuntimeBackend } from "../../src/vector-cortex/encoder/runtime-select.js";
36
+ import { detectPlatform } from "../../src/vector-cortex/encoder/asset.js";
37
+ import {
38
+ NATIVE_ORT_VERSION,
39
+ NATIVE_ORT_PACKAGE,
40
+ NATIVE_ORT_INSTALLABLE_PLATFORMS,
41
+ } from "../../src/vector-cortex/encoder/native-install-artifacts.js";
42
+ import type { SetupConfigureRequest } from "./api-contracts/setup.js";
43
+
44
+ /** The committed operator script that performs the install (repo-relative). */
45
+ const ENC_2A_SCRIPT_PATH = "scripts/encoder/install-native-ort.mjs";
46
+
47
+ /** Where the operator script installs the native binding (absolute install
48
+ * prefix used verbatim in the guide commands + the version probe). */
49
+ function nativeOrtDir(): string {
50
+ return join(process.env.HOME ?? "", ".pi", "mega-compact", "native-ort");
51
+ }
52
+
53
+ /**
54
+ * True when the payload carries the ENC-2a guide-request key `false`/`true`
55
+ * (flag-gated, additive). `false` -> 400 (operator-driven no-op); `true` -> 200
56
+ * + the guide echoed (still no server execution — the execute path is ENC-2c).
57
+ * Flag-off -> null so the key falls through unrecognized (byte-identical
58
+ * ENC-1b-era predecessor).
59
+ */
60
+ export function enc2aGuideRequest(
61
+ body: SetupConfigureRequest,
62
+ ): { status: 400 } | { status: 200 } | null {
63
+ if (!ENC_2A_ENABLED()) return null;
64
+ if (body.nativeOrtInstallGuide === true) return { status: 200 };
65
+ if (body.nativeOrtInstallGuide === false) return { status: 400 };
66
+ return null;
67
+ }
68
+
69
+ /**
70
+ * Read the ENC-2a native install GUIDE + installed-version, additive GET fields.
71
+ *
72
+ * The guide renders only when EVERY gate passes: flag on, operator opted into
73
+ * native, effective backend is still `"wasm"` (onnxruntime-node absent), and the
74
+ * host platform is installable (darwin-x64 is excluded — no native binding
75
+ * upstream, the ENC-0e demotion sentinel). The effective backend + demotion
76
+ * reason go through the EXISTING `selectRuntimeBackend` (reader-only — never a
77
+ * reimplemented literal). `installedVersion` probes
78
+ * `~/.pi/mega-compact/native-ort/node_modules/onnxruntime-node/package.json`
79
+ * when present; null otherwise. Returns `{ guide: null, installedVersion: null }`
80
+ * when the flag is off (byte-identical predecessor).
81
+ */
82
+ export function readEnc2aGuide(stateDir: string): {
83
+ guide: { platform: string; commands: readonly string[]; scriptPath: string } | null;
84
+ installedVersion: string | null;
85
+ } {
86
+ if (!ENC_2A_ENABLED()) return { guide: null, installedVersion: null };
87
+ const env = readEnc1bEnv(stateDir);
88
+ const platform = detectPlatform();
89
+ const chosen = selectRuntimeBackend({
90
+ platform: platform ?? "unsupported",
91
+ benchRecord: null,
92
+ nativeOptIn: env.nativeOptIn,
93
+ });
94
+ const backend = chosen.backend === "native" ? "native" : "wasm";
95
+
96
+ let guide: { platform: string; commands: readonly string[]; scriptPath: string } | null = null;
97
+ if (
98
+ env.nativeOptIn &&
99
+ backend === "wasm" &&
100
+ platform !== null &&
101
+ (NATIVE_ORT_INSTALLABLE_PLATFORMS as readonly string[]).includes(platform)
102
+ ) {
103
+ guide = {
104
+ platform,
105
+ commands: [
106
+ `npm install --prefix ${nativeOrtDir()} ${NATIVE_ORT_PACKAGE}@${NATIVE_ORT_VERSION}`,
107
+ "pi update --extensions && pi session-start",
108
+ "expect encoderBackend: native on next status poll",
109
+ ],
110
+ scriptPath: ENC_2A_SCRIPT_PATH,
111
+ };
112
+ }
113
+
114
+ return { guide, installedVersion: probeInstalledVersion() };
115
+ }
116
+
117
+ /** Probe the local native-ort package.json for the installed onnxruntime-node
118
+ * version. Null when the package is absent/unreadable (reader-only, local). */
119
+ function probeInstalledVersion(): string | null {
120
+ try {
121
+ const pkgPath = join(
122
+ nativeOrtDir(),
123
+ "node_modules",
124
+ NATIVE_ORT_PACKAGE,
125
+ "package.json",
126
+ );
127
+ if (!existsSync(pkgPath)) return null;
128
+ const raw = JSON.parse(readFileSync(pkgPath, "utf8")) as unknown;
129
+ if (
130
+ typeof raw === "object" &&
131
+ raw !== null &&
132
+ typeof (raw as { version?: unknown }).version === "string"
133
+ ) {
134
+ return (raw as { version: string }).version;
135
+ }
136
+ return null;
137
+ } catch {
138
+ return null;
139
+ }
140
+ }
@@ -21,6 +21,7 @@ import {
21
21
  tryEnc2BudgetInto,
22
22
  enc2BudgetValidateCombined,
23
23
  } from "./routes-setup-enc2budget.js";
24
+ import { readEnc2aGuide, enc2aGuideRequest } from "./routes-setup-enc2a.js";
24
25
  import { writeEmbedderEnv } from "./routes-setup-env-upsert.js";
25
26
  import {
26
27
  detectOllama,
@@ -85,6 +86,11 @@ export function handleSetupStatus(
85
86
  }
86
87
  const configured = detectConfiguredEmbedder(ctx.stateDir);
87
88
  const active = detectCurrentEmbedder();
89
+ // ENC-2a (flag-gated, additive): the native install-guide + installed-version
90
+ // fields. Optional fields are added only when present/installable; when the
91
+ // flag is off readEnc2aGuide returns nulls so the body stays byte-identical
92
+ // to the ENC-1b-era shape.
93
+ const enc2a = readEnc2aGuide(ctx.stateDir);
88
94
  // ENC-1a (flag-gated, additive): echo the persisted endpoint URL and an
89
95
  // embeddingApiKeySet boolean ONLY — the raw API key is never returned. When
90
96
  // the flag is off (or neither is set) both fields are simply omitted.
@@ -100,6 +106,8 @@ export function handleSetupStatus(
100
106
  ),
101
107
  ...enc1aStatusFields(ctx.stateDir), ...enc1bStatusFields(ctx.stateDir),
102
108
  ...enc2BudgetStatusFields(ctx.stateDir),
109
+ ...(enc2a.guide !== null ? { nativeOrtInstallGuide: enc2a.guide } : {}),
110
+ ...(enc2a.installedVersion !== null ? { nativeOrtInstalledVersion: enc2a.installedVersion } : {}),
103
111
  };
104
112
  // guardrails-allow PREVENT-PI-004: loopback dashboard response (local)
105
113
  res.writeHead(200, { "Content-Type": "application/json" });
@@ -218,10 +226,28 @@ export function handleSetupConfigure(
218
226
  return;
219
227
  }
220
228
  const body = parsed.value as unknown as SetupConfigureRequest;
229
+ // ENC-2a guide-request key (flag-gated, additive): `false` → 400 (an
230
+ // operator-driven no-op — this sprint conveys the GUIDE only, no server
231
+ // execution), `true` → 200 + the guide echoed (still no execution; the
232
+ // execute path is ENC-2c). Flag-off: enc2aGuideRequest returns null so the
233
+ // key falls through unrecognized (byte-identical ENC-1b-era predecessor).
234
+ const guideReq = enc2aGuideRequest(body);
235
+ // guardrails-allow PREVENT-PI-004: loopback dashboard response (local)
236
+ if (guideReq !== null && guideReq.status === 400) {
237
+ res.writeHead(400, { "Content-Type": "application/json" });
238
+ res.end(JSON.stringify({ error: "guide_rejected_false_nothing_to_do" }));
239
+ return;
240
+ }
221
241
  // ENC-1a (flag-gated, additive): a pure external-embedder configure
222
242
  // (new keys, no embedder selection) is handled by the sibling writer.
223
243
  // Flag-off = the keys are simply not recognized, falling through to the
224
244
  // pre-ENC-1a embedder path below (byte-identical predecessor).
245
+ if (guideReq !== null && guideReq.status === 200) {
246
+ // guardrails-allow PREVENT-PI-004: loopback dashboard response (local)
247
+ res.writeHead(200, { "Content-Type": "application/json" });
248
+ res.end(JSON.stringify({ nativeOrtInstallGuide: readEnc2aGuide(ctx.stateDir).guide }));
249
+ return;
250
+ }
225
251
  if (tryEnc1aConfigure(body, res, ctx)) return;
226
252
  if (tryEnc1bConfigure(body, res, ctx)) return; // pure ENC-1b configure (dim/headers/allow-remote/native)
227
253
  // ENC-1b combined-payload validation: when a payload carries a valid
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-mega-compact",
3
- "version": "0.20.62",
3
+ "version": "0.20.64",
4
4
  "description": "Layered, local, vector-backed context compressor for pi — supersede/collapse/cluster compaction with deduped inline recall.",
5
5
  "type": "module",
6
6
  "license": "BSD-3-Clause",
@@ -0,0 +1,37 @@
1
+ /**
2
+ * config/vector-cortex-enc2a.ts — ENC-2a native onnxruntime install-guide flag
3
+ * (operator run-script assist).
4
+ *
5
+ * Sibling of vector-cortex-enc1a.ts / vector-cortex-enc1b.ts /
6
+ * vector-cortex-enc2budget.ts so vector-cortex.ts stays under the 300-line soft
7
+ * limit (soft-as-hard gate). vector-cortex.ts re-exports the flag below and
8
+ * root src/config.ts re-exports it, so no consumer import path changes.
9
+ *
10
+ * ENC-2a, when the operator opted into the native backend
11
+ * (`MEGACOMPACT_ENCODER_NATIVE=1`) but `encoderBackend` is still `"wasm"`
12
+ * (onnxruntime-node absent / not yet installed), surfaces an "Encoder Runtime
13
+ * Install" card on the Cortex sub-tab with copy-paste operator commands: the
14
+ * install + restart + verify steps built ONLY from the artifacts-module
15
+ * constants (`src/vector-cortex/encoder/native-install-artifacts.ts`) — never
16
+ * an inline registry URL or hash in the route (PREVENT-PI-004). The guide
17
+ * renders only on an installable host platform; the ENC-0e darwin-x64 demotion
18
+ * sentinel keeps it absent on an Intel Mac (no native binding upstream).
19
+ *
20
+ * `MEGACOMPACT_ENC_2A=0` disables: no guide fields, no install card, no absent
21
+ * read — byte-identical to the ENC-1b predecessor. The flag MUST also be a
22
+ * dashboard SETTINGS toggle (visible in config UI, never in EXCLUDED_SETTINGS
23
+ * — see `feedback_dashboard-flags-toggleable` memory).
24
+ *
25
+ * Pi-agnostic, dependency-free (PREVENT-PI-004 / PREVENT-011).
26
+ */
27
+
28
+ import { sprintFlag } from "./vector-cortex-flag.js";
29
+
30
+ /**
31
+ * ENC-2a — operator run-script assist (dashboard install guide for the
32
+ * onnxruntime-node native binding). Default ON. `MEGACOMPACT_ENC_2A=0` disables
33
+ * and is byte-identical to the ENC-1b predecessor: no guide/absent fields, no
34
+ * install card. This flag MUST also be a dashboard SETTINGS toggle (visible in
35
+ * config UI, never in EXCLUDED_SETTINGS).
36
+ */
37
+ export const ENC_2A_ENABLED = (): boolean => sprintFlag("MEGACOMPACT_ENC_2A");
@@ -92,6 +92,8 @@ export {
92
92
  ENC_2BUDGET_MAX_MIB,
93
93
  ENC_2BUDGET_DEFAULT_MIB,
94
94
  } from "./vector-cortex-enc2budget.js";
95
+ // ENC-2a native onnxruntime install-guide flag extracted to vector-cortex-enc2a.ts.
96
+ export { ENC_2A_ENABLED } from "./vector-cortex-enc2a.js";
95
97
  // Breaker constants (TRIAD_RESILIENCE.md §breaker) extracted to vector-cortex-breakers.ts.
96
98
  export {
97
99
  BREAKER_WINDOW_MS,
package/src/config.ts CHANGED
@@ -202,6 +202,7 @@ export {
202
202
  ENC_2BUDGET_NATIVE_ORT_BUDGET_ENV,
203
203
  ENC_2BUDGET_MAX_MIB,
204
204
  ENC_2BUDGET_DEFAULT_MIB,
205
+ ENC_2A_ENABLED,
205
206
  COSINE_FP_BENCH_ENABLED,
206
207
  COSINE_FP_REAL_ENABLED,
207
208
  REPO_CORPUS_ENABLED,
@@ -0,0 +1,60 @@
1
+ /**
2
+ * vector-cortex/encoder/native-install-artifacts.ts — ENC-2a native
3
+ * onnxruntime install-guide constants (PURE data module).
4
+ *
5
+ * Single source of truth for the operator's native-backend install guide
6
+ * (`onnxruntime-node`, the sole onnxruntime Node.js binding this extension's
7
+ * native path uses). The guide rendered by
8
+ * `extensions/dashboard-server/routes-setup-enc2a.ts` and the operator script
9
+ * `scripts/encoder/install-native-ort.mjs` build their commands/URLs ONLY from
10
+ * these scalars — never an inline registry URL or literal hash in the route or
11
+ * extension runtime (PREVENT-PI-004: the registry tarball URL is derived by
12
+ * callers from `NATIVE_ORT_PACKAGE` + "@" + `NATIVE_ORT_VERSION`, so no network
13
+ * path and no literal registry URL or scheme appears in src/).
14
+ *
15
+ * Package facts (verified, not invented):
16
+ * - onnxruntime-node publishes ONE monolithic ~100MB npm tarball — not
17
+ * per-platform `optionalDependencies` — so a single
18
+ * `NATIVE_ORT_TARBALL_SHA256` pins the whole artifact for every host.
19
+ * - darwin-x64 has NO native binding (arm64-only upstream since 1.17), so the
20
+ * guide stays absent on an Intel Mac (the ENC-0e demotion sentinel).
21
+ * - `NATIVE_ORT_TARBALL_SHA256` was computed from TWO independent downloads of
22
+ * the 1.27.0 tarball (real, cross-checked, not guessed).
23
+ *
24
+ * Pi-agnostic, dependency-free, pure data — zero I/O, zero network
25
+ * (PREVENT-PI-004 / PREVENT-011).
26
+ */
27
+
28
+ /** onnxruntime-node version the guide installs (real published version). */
29
+ export const NATIVE_ORT_VERSION: string = "1.27.0";
30
+
31
+ /** onnxruntime-node npm package name (the native onnxruntime binding). */
32
+ export const NATIVE_ORT_PACKAGE: string = "onnxruntime-node";
33
+
34
+ /** SHA-256 of the onnxruntime-node@1.27.0 npm tarball (one sha for all hosts).
35
+ * Computed from TWO independent tarball downloads; lowercase hex, 64 chars. */
36
+ export const NATIVE_ORT_TARBALL_SHA256: string =
37
+ "c3779c01c59832f8c03e2c392ac3af10bf08579f1822e8b1c63cc451edb302a2";
38
+
39
+ /**
40
+ * The host platform the guide can render for. darwin-x64 is deliberately NOT
41
+ * installable (no native onnxruntime binding upstream — arm64-only since 1.17);
42
+ * the guide stays absent on an Intel Mac (ENC-0e demotion sentinel).
43
+ */
44
+ export type EncoderPlatform =
45
+ | "linux-x64"
46
+ | "linux-arm64"
47
+ | "darwin-arm64"
48
+ | "win32-x64"
49
+ | "darwin-x64";
50
+
51
+ /**
52
+ * Platforms for which an operator install-guide can be rendered (native
53
+ * binding exists upstream). darwin-x64 is excluded — it has NO native binding.
54
+ */
55
+ export const NATIVE_ORT_INSTALLABLE_PLATFORMS: readonly EncoderPlatform[] = [
56
+ "linux-x64",
57
+ "linux-arm64",
58
+ "darwin-arm64",
59
+ "win32-x64",
60
+ ];