pi-mega-compact 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/extensions/dashboard-server/api-contracts/endpoints/registry.js +6 -0
- package/dist/extensions/dashboard-server/routes-cache.js +17 -5
- package/dist/extensions/dashboard-server/routes-game.js +60 -0
- package/dist/extensions/dashboard-server/routes.js +1 -1
- package/dist/extensions/dashboard-server/server.js +3 -1
- package/dist/extensions/mega-runtime/capture-model.js +15 -2
- package/dist/extensions/mega-runtime/runtime-snapshot.js +26 -0
- package/dist/extensions/mega-runtime/runtime.js +1 -0
- package/extensions/dashboard-client/dist/assets/AreaChart-rJdaOUlj.js +2 -0
- package/extensions/dashboard-client/dist/assets/AreaChart-rJdaOUlj.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/BarChart-DOfc8me9.js +2 -0
- package/extensions/dashboard-client/dist/assets/BarChart-DOfc8me9.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{CacheTab-CDyZqMO-.js → CacheTab-EhqkEglo.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{CacheTab-CDyZqMO-.js.map → CacheTab-EhqkEglo.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{EventsTab-ByPYMJVG.js → EventsTab-BUACwWXf.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{EventsTab-ByPYMJVG.js.map → EventsTab-BUACwWXf.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{HealthTab-CeHQR0py.js → HealthTab-CDEYVRBb.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{HealthTab-CeHQR0py.js.map → HealthTab-CDEYVRBb.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-ceTD_c1A.js → MaintenanceTab-DtanIeCQ.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-ceTD_c1A.js.map → MaintenanceTab-DtanIeCQ.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-CRUdVR7u.js → MemoryMapTab-BGEhL7OG.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-CRUdVR7u.js.map → MemoryMapTab-BGEhL7OG.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/MetricsTab-Cktozn4s.js +2 -0
- package/extensions/dashboard-client/dist/assets/MetricsTab-Cktozn4s.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/OverviewTab-08v6Ayuf.js +16 -0
- package/extensions/dashboard-client/dist/assets/OverviewTab-08v6Ayuf.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{ReposTab-DUrP7Efa.js → ReposTab-Bg72Ozdc.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{ReposTab-DUrP7Efa.js.map → ReposTab-Bg72Ozdc.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/SessionsTab-BcTK9Lg6.js +2 -0
- package/extensions/dashboard-client/dist/assets/{SessionsTab-Cg-IsijD.js.map → SessionsTab-BcTK9Lg6.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SetupTab-ZE1daXjN.js → SetupTab-Bt-Ru1xp.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SetupTab-ZE1daXjN.js.map → SetupTab-Bt-Ru1xp.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-BkTgi3Af.js → TimeSavedCard-ic_LjJ79.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-BkTgi3Af.js.map → TimeSavedCard-ic_LjJ79.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TurnsTab-CZvudHQF.js → TurnsTab-D9AZTMgG.js} +4 -4
- package/extensions/dashboard-client/dist/assets/{TurnsTab-CZvudHQF.js.map → TurnsTab-D9AZTMgG.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/WikiTab-hRcJPi_m.js +2 -0
- package/extensions/dashboard-client/dist/assets/{WikiTab-BVAnGp8_.js.map → WikiTab-hRcJPi_m.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{button-CUrzhi2A.js → button-BdAtIbVu.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{button-CUrzhi2A.js.map → button-BdAtIbVu.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{card-BsfojHfp.js → card-BFYc_QrK.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{card-BsfojHfp.js.map → card-BFYc_QrK.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/generateCategoricalChart-BwzyqytT.js +70 -0
- package/extensions/dashboard-client/dist/assets/generateCategoricalChart-BwzyqytT.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{index-OM3w-l2T.js → index-pmtEr3sb.js} +8 -8
- package/extensions/dashboard-client/dist/assets/index-pmtEr3sb.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/index-za_gmEmQ.css +1 -0
- package/extensions/dashboard-client/dist/assets/{switch-qSz2Un3t.js → switch-DEyGlFwJ.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{switch-qSz2Un3t.js.map → switch-DEyGlFwJ.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{toggle-DyBKcLe-.js → toggle-pDMBQYQj.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{toggle-DyBKcLe-.js.map → toggle-pDMBQYQj.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{useSSE-DqVouqww.js → useSSE-BKaC4dao.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{useSSE-DqVouqww.js.map → useSSE-BKaC4dao.js.map} +1 -1
- package/extensions/dashboard-client/dist/index.html +2 -2
- package/extensions/dashboard-client/package-lock.json +56 -0
- package/extensions/dashboard-client/package.json +3 -0
- package/extensions/dashboard-client/src/api/client.ts +11 -0
- package/extensions/dashboard-client/src/components/SessionContextGauges.tsx +14 -8
- package/extensions/dashboard-client/src/components/WidgetDetailModal.tsx +69 -0
- package/extensions/dashboard-client/src/components/charts/PerfBarChart.tsx +89 -0
- package/extensions/dashboard-client/src/components/charts/PerfLineChart.tsx +108 -0
- package/extensions/dashboard-client/src/components/layout/AppShell.tsx +1 -1
- package/extensions/dashboard-client/src/components/ui/SortableCard.tsx +75 -0
- package/extensions/dashboard-client/src/hooks/useCardPositions.ts +74 -0
- package/extensions/dashboard-client/src/styles/base.css +2 -4
- package/extensions/dashboard-client/src/styles/session-gauges.css +28 -15
- package/extensions/dashboard-client/src/tabs/OverviewTab.tsx +310 -79
- package/extensions/dashboard-client/src/types/card.ts +40 -0
- package/extensions/dashboard-client/tailwind.config.js +1 -1
- package/extensions/dashboard-server/api-contracts/endpoints/registry.ts +10 -0
- package/extensions/dashboard-server/api-contracts/endpoints/types.ts +36 -0
- package/extensions/dashboard-server/api-contracts/endpoints.ts +3 -0
- package/extensions/dashboard-server/api-contracts/index.ts +3 -0
- package/extensions/dashboard-server/routes-cache.ts +17 -5
- package/extensions/dashboard-server/routes-game.ts +72 -0
- package/extensions/dashboard-server/routes.ts +1 -0
- package/extensions/dashboard-server/server.ts +2 -0
- package/extensions/mega-runtime/capture-model.ts +14 -2
- package/extensions/mega-runtime/runtime-snapshot.ts +40 -0
- package/extensions/mega-runtime/runtime.ts +1 -0
- package/package.json +1 -1
- package/extensions/dashboard-client/dist/assets/AreaChart-C68tGr2J.js +0 -70
- package/extensions/dashboard-client/dist/assets/AreaChart-C68tGr2J.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/MetricsTab-DP7Kmdu9.js +0 -2
- package/extensions/dashboard-client/dist/assets/MetricsTab-DP7Kmdu9.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/OverviewTab-4CGP0djv.js +0 -2
- package/extensions/dashboard-client/dist/assets/OverviewTab-4CGP0djv.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/SessionsTab-Cg-IsijD.js +0 -2
- package/extensions/dashboard-client/dist/assets/WikiTab-BVAnGp8_.js +0 -2
- package/extensions/dashboard-client/dist/assets/index-CUA6EDRF.css +0 -1
- package/extensions/dashboard-client/dist/assets/index-OM3w-l2T.js.map +0 -1
|
@@ -13,7 +13,8 @@ import { createRequire } from "node:module";
|
|
|
13
13
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
14
14
|
|
|
15
15
|
import type { RouteContext } from "./routes-core.js";
|
|
16
|
-
import { computeCacheSavings } from "../../src/pricing.js";
|
|
16
|
+
import { computeCacheSavings, lookupModelInputRate } from "../../src/pricing.js";
|
|
17
|
+
import { costApiConfig, lookupCostApiPricing } from "../../src/costApi.js";
|
|
17
18
|
|
|
18
19
|
// ---------------------------------------------------------------------------
|
|
19
20
|
// handleProviderCache — "/api/provider-cache"
|
|
@@ -118,18 +119,29 @@ export function handleProviderCache(
|
|
|
118
119
|
} | null = null;
|
|
119
120
|
try {
|
|
120
121
|
const snap = latestModelSnapshot(stateDir); // guardrails-allow PREVENT-PI-004: local SQLite read (loopback dashboard)
|
|
121
|
-
|
|
122
|
+
let rate = snap?.inputRate ?? 0;
|
|
123
|
+
let modelName = snap?.modelName ?? snap?.modelId ?? "unknown";
|
|
124
|
+
// Fallback chain: SQLite snapshot → local pricing table → cost API
|
|
125
|
+
if (rate <= 0 && modelName !== "unknown") {
|
|
126
|
+
rate = lookupModelInputRate(modelName) ?? 0;
|
|
127
|
+
}
|
|
128
|
+
if (rate <= 0 && costApiConfig().enabled && modelName !== "unknown") {
|
|
129
|
+
// guardrails-allow PREVENT-PI-004: cost API pricing lookup (user-opted-in)
|
|
130
|
+
const apiPricing = lookupCostApiPricing(modelName);
|
|
131
|
+
rate = apiPricing?.inputRate ?? 0;
|
|
132
|
+
}
|
|
133
|
+
if (rate > 0) {
|
|
122
134
|
const s = computeCacheSavings(
|
|
123
135
|
lifetime.totalCacheRead,
|
|
124
136
|
lifetime.totalCacheWrite,
|
|
125
|
-
|
|
137
|
+
rate,
|
|
126
138
|
);
|
|
127
139
|
savings = {
|
|
128
140
|
cacheReadSaved: s.cacheReadSaved,
|
|
129
141
|
cacheWriteCost: s.cacheWriteCost,
|
|
130
142
|
netSaved: s.netSaved,
|
|
131
|
-
model:
|
|
132
|
-
inputRate:
|
|
143
|
+
model: modelName,
|
|
144
|
+
inputRate: rate,
|
|
133
145
|
};
|
|
134
146
|
}
|
|
135
147
|
} catch {
|
|
@@ -8,6 +8,7 @@ import type { IncomingMessage, ServerResponse } from "node:http";
|
|
|
8
8
|
|
|
9
9
|
import type { RouteContext } from "./routes-core.js";
|
|
10
10
|
import type { GameMetric } from "../../src/game/scoring.js";
|
|
11
|
+
import type { PerfKind } from "../../src/store/sqlite/perf-samples.js";
|
|
11
12
|
|
|
12
13
|
// ---------------------------------------------------------------------------
|
|
13
14
|
// handleGameState — "/api/game-state" (GET + PUT)
|
|
@@ -351,6 +352,77 @@ export function handlePerf(
|
|
|
351
352
|
return true;
|
|
352
353
|
}
|
|
353
354
|
|
|
355
|
+
// ---------------------------------------------------------------------------
|
|
356
|
+
// handlePerfSamples — "/api/perf/samples"
|
|
357
|
+
// ---------------------------------------------------------------------------
|
|
358
|
+
|
|
359
|
+
export function handlePerfSamples(
|
|
360
|
+
req: IncomingMessage,
|
|
361
|
+
res: ServerResponse,
|
|
362
|
+
ctx: RouteContext,
|
|
363
|
+
): boolean {
|
|
364
|
+
if (!req.url?.startsWith("/api/perf/samples")) return false;
|
|
365
|
+
|
|
366
|
+
const { stateDir } = ctx;
|
|
367
|
+
|
|
368
|
+
// /api/perf/samples — dashboard Perf tab chart drill-down. GET returns raw
|
|
369
|
+
// perf_samples for a single kind (?kind=<k>&minutes=<n>) ascending by ts so
|
|
370
|
+
// the client can render a time-series for any perf metric (turn_latency_ms,
|
|
371
|
+
// tps, disk_write_ms, cache_hit_pct, db_recompute_ms, etc.). `kind` is
|
|
372
|
+
// required and validated against the PERF_KINDS allow-list (400 on unknown);
|
|
373
|
+
// `minutes` defaults to 60 and is capped at 1440 (24h). Reads perf_samples
|
|
374
|
+
// via the same require()'d sqlite helper as /api/perf — no new SQLite code.
|
|
375
|
+
// Non-GET -> 405. PREVENT-PI-004: loopback.
|
|
376
|
+
const psReq = createRequire(import.meta.url);
|
|
377
|
+
const { readPerfSamples, PERF_KINDS } = psReq(
|
|
378
|
+
"../../src/store/sqlite.js",
|
|
379
|
+
) as typeof import("../../src/store/sqlite.js");
|
|
380
|
+
if (req.method !== "GET") {
|
|
381
|
+
res.writeHead(405, { "Content-Type": "application/json" }); // guardrails-allow PREVENT-PI-004: loopback dashboard response (local)
|
|
382
|
+
res.end(JSON.stringify({ error: "method_not_allowed" }));
|
|
383
|
+
return true;
|
|
384
|
+
}
|
|
385
|
+
try {
|
|
386
|
+
const url = new URL(req.url, "http://x"); // guardrails-allow PREVENT-PI-004: localhost dashboard URL base (loopback-only)
|
|
387
|
+
const kindParam = url.searchParams.get("kind") ?? "";
|
|
388
|
+
if (!(PERF_KINDS as readonly string[]).includes(kindParam)) {
|
|
389
|
+
res.writeHead(400, { "Content-Type": "application/json" }); // guardrails-allow PREVENT-PI-004: loopback dashboard response (local)
|
|
390
|
+
res.end(JSON.stringify({ error: "unknown_kind", kind: kindParam }));
|
|
391
|
+
return true;
|
|
392
|
+
}
|
|
393
|
+
let minutes = Number(url.searchParams.get("minutes") ?? "60");
|
|
394
|
+
if (!Number.isFinite(minutes) || minutes <= 0) minutes = 60;
|
|
395
|
+
minutes = Math.min(minutes, 1440); // cap at 24h
|
|
396
|
+
const sinceTs = Date.now() - minutes * 60_000;
|
|
397
|
+
const kind = kindParam as PerfKind; // validated against PERF_KINDS above
|
|
398
|
+
const rows = readPerfSamples(stateDir, sinceTs, kind); // guardrails-allow PREVENT-PI-004: local SQLite read (loopback dashboard)
|
|
399
|
+
const samples = rows.map((r) => ({
|
|
400
|
+
ts: r.ts,
|
|
401
|
+
value: r.value,
|
|
402
|
+
...((r.meta != null && typeof r.meta === "object"
|
|
403
|
+
? { meta: JSON.stringify(r.meta) }
|
|
404
|
+
: r.meta != null
|
|
405
|
+
? { meta: String(r.meta) }
|
|
406
|
+
: {}) as { meta?: string }),
|
|
407
|
+
}));
|
|
408
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
409
|
+
res.end(
|
|
410
|
+
JSON.stringify({
|
|
411
|
+
samples,
|
|
412
|
+
kind: kindParam,
|
|
413
|
+
minutes,
|
|
414
|
+
updatedAt: Date.now(),
|
|
415
|
+
}),
|
|
416
|
+
);
|
|
417
|
+
} catch (e) {
|
|
418
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
419
|
+
res.end(
|
|
420
|
+
JSON.stringify({ error: "perf_samples_unavailable", detail: String(e) }),
|
|
421
|
+
);
|
|
422
|
+
}
|
|
423
|
+
return true;
|
|
424
|
+
}
|
|
425
|
+
|
|
354
426
|
// ---------------------------------------------------------------------------
|
|
355
427
|
// handleAchievements — "/api/achievements"
|
|
356
428
|
// ---------------------------------------------------------------------------
|
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
handleGameState,
|
|
34
34
|
handleGameScores,
|
|
35
35
|
handlePerf,
|
|
36
|
+
handlePerfSamples,
|
|
36
37
|
handleAchievements,
|
|
37
38
|
handleSessions,
|
|
38
39
|
handleTopics,
|
|
@@ -247,6 +248,7 @@ export async function launchDashboardServer(
|
|
|
247
248
|
if (handleEvents(req, res, ctx)) return;
|
|
248
249
|
if (handleGameState(req, res, ctx)) return;
|
|
249
250
|
if (handleGameScores(req, res, ctx)) return;
|
|
251
|
+
if (handlePerfSamples(req, res, ctx)) return;
|
|
250
252
|
if (handlePerf(req, res, ctx)) return;
|
|
251
253
|
if (handleAchievements(req, res, ctx)) return;
|
|
252
254
|
if (handleSessions(req, res, ctx)) return;
|
|
@@ -11,6 +11,7 @@ import { resolveRepoRoot } from "../mega-config.js";
|
|
|
11
11
|
import { recordModelSnapshot, recordRepoModel } from "../../src/store/sqlite.js";
|
|
12
12
|
import type { ModelSnapshot } from "../../src/store/sqlite.js";
|
|
13
13
|
import { lookupModelInputRate } from "../../src/pricing.js";
|
|
14
|
+
import { costApiConfig, lookupCostApiPricing } from "../../src/costApi.js";
|
|
14
15
|
|
|
15
16
|
// ---------------------------------------------------------------------- types
|
|
16
17
|
|
|
@@ -45,13 +46,24 @@ export function captureModelImpl(ctx: CaptureModelContext, ectx: ExtensionContex
|
|
|
45
46
|
}
|
|
46
47
|
const modelId = m.id;
|
|
47
48
|
const fallbackInput = lookupModelInputRate(modelId);
|
|
49
|
+
let inputRate = m.cost?.input || fallbackInput || 0;
|
|
50
|
+
let outputRate = m.cost?.output ?? 0;
|
|
51
|
+
// Cost API last-resort fallback for models not in the local pricing table
|
|
52
|
+
if (inputRate <= 0 && costApiConfig().enabled) {
|
|
53
|
+
// guardrails-allow PREVENT-PI-004: cost API pricing lookup (user-opted-in)
|
|
54
|
+
const apiPricing = lookupCostApiPricing(modelId);
|
|
55
|
+
if (apiPricing) {
|
|
56
|
+
inputRate = apiPricing.inputRate ?? 0;
|
|
57
|
+
if (outputRate <= 0) outputRate = apiPricing.outputRate ?? 0;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
48
60
|
const snap: Omit<ModelSnapshot, "capturedAt"> = {
|
|
49
61
|
provider: m.provider,
|
|
50
62
|
providerName,
|
|
51
63
|
modelId,
|
|
52
64
|
modelName: m.name ?? null,
|
|
53
|
-
inputRate
|
|
54
|
-
outputRate
|
|
65
|
+
inputRate,
|
|
66
|
+
outputRate,
|
|
55
67
|
contextWindow: m.contextWindow ?? 0,
|
|
56
68
|
maxTokens: m.maxTokens ?? 0,
|
|
57
69
|
reasoning: !!m.reasoning,
|
|
@@ -72,6 +72,9 @@ export interface RuntimeSnapshotContext extends RuntimeHelpersContext {
|
|
|
72
72
|
lastSnapshotSig: string | null;
|
|
73
73
|
lastWidgetCtx?: ExtensionContext;
|
|
74
74
|
lastActivityAt: number;
|
|
75
|
+
/** Timestamp (ms) of the last session heartbeat write. Used by the
|
|
76
|
+
* material-change gate fast path to refresh heartbeats on a cadence. */
|
|
77
|
+
lastHeartbeatAt: number;
|
|
75
78
|
lastLevel: number;
|
|
76
79
|
diagCtxFastGate: number;
|
|
77
80
|
diagLiveTrimFires: number;
|
|
@@ -117,6 +120,12 @@ export function snapshotImpl(
|
|
|
117
120
|
const sig = materialSigImpl(self);
|
|
118
121
|
if (ctx && self.widgetData && self.lastSnapshotSig === sig) {
|
|
119
122
|
self.renderWidget(ctx);
|
|
123
|
+
// Refresh heartbeat on a time cadence even when material state hasn't
|
|
124
|
+
// changed, so the session doesn't appear stale and get pruned by the
|
|
125
|
+
// dashboard's 30-min cutoff. The full snapshot recompute is still gated
|
|
126
|
+
// (expensive SQLite opens + writeFileSync), but a heartbeat row is
|
|
127
|
+
// cheap (single INSERT OR REPLACE on the index DB).
|
|
128
|
+
refreshHeartbeatIfStale(self, ctx, 10_000);
|
|
120
129
|
return;
|
|
121
130
|
}
|
|
122
131
|
const perfT0 = performance.now();
|
|
@@ -313,4 +322,35 @@ export function snapshotImpl(
|
|
|
313
322
|
/* non-fatal: perf instrumentation never blocks the agent */
|
|
314
323
|
}
|
|
315
324
|
self.lastSnapshotSig = sig;
|
|
325
|
+
self.lastHeartbeatAt = Date.now();
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// ----------------------------------------------------------- heartbeat refresh
|
|
329
|
+
|
|
330
|
+
/** Refresh the session heartbeat if enough time has elapsed since the last
|
|
331
|
+
* write. Called from the material-change gate fast path (where the full
|
|
332
|
+
* snapshot recompute is skipped) so the session stays visible in the
|
|
333
|
+
* dashboard during idle/typing periods. Non-fatal — best-effort like the
|
|
334
|
+
* main heartbeat write. */
|
|
335
|
+
function refreshHeartbeatIfStale(
|
|
336
|
+
self: RuntimeSnapshotContext,
|
|
337
|
+
ctx: ExtensionContext | undefined,
|
|
338
|
+
intervalMs: number,
|
|
339
|
+
): void {
|
|
340
|
+
const now = Date.now();
|
|
341
|
+
if (now - self.lastHeartbeatAt < intervalMs) return;
|
|
342
|
+
try {
|
|
343
|
+
const repo =
|
|
344
|
+
resolveRepoRoot(ctx?.cwd ?? self.currentStateDir) ?? self.currentStateDir;
|
|
345
|
+
recordSessionHeartbeat(
|
|
346
|
+
process.pid,
|
|
347
|
+
self.rt.sessionId,
|
|
348
|
+
repo,
|
|
349
|
+
self.currentStateDir,
|
|
350
|
+
self.lastCtxWindow || 0,
|
|
351
|
+
);
|
|
352
|
+
self.lastHeartbeatAt = now;
|
|
353
|
+
} catch {
|
|
354
|
+
/* non-fatal: heartbeat refresh must never block the snapshot path */
|
|
355
|
+
}
|
|
316
356
|
}
|
|
@@ -209,6 +209,7 @@ export class MegaRuntime {
|
|
|
209
209
|
// (already-registered) widget factory is refreshed. Kills the per-event
|
|
210
210
|
// main-thread block during typing/idle streaming with no material change.
|
|
211
211
|
lastSnapshotSig: string | null = null;
|
|
212
|
+
lastHeartbeatAt: number = 0;
|
|
212
213
|
// v0.8.5: bumped whenever the cached game-state memo is evicted (bumpGameState
|
|
213
214
|
// for in-process /mega-game writes, the fs.watch callback for cross-process
|
|
214
215
|
// dashboard-server writes, and bindRepo on repo switch) so the snapshot gate
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-mega-compact",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
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",
|