dsh-context 0.53.2 → 0.53.3
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/lib/client.js +21 -4
- package/lib/index.js +81 -12
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -6168,6 +6168,20 @@ window.__ModuleLoader__.load({
|
|
|
6168
6168
|
Promise.resolve(sessions.refresh()).catch(() => {});
|
|
6169
6169
|
} catch {}
|
|
6170
6170
|
}
|
|
6171
|
+
const BACKFILL_ROUTE = "/api/dsh-context/backfill";
|
|
6172
|
+
/**
|
|
6173
|
+
* Summon the host's projection warm-up (host/backfill.ts): the dashboard is
|
|
6174
|
+
* the rows' only reader, so the host defers the corpus-wide cold reads until
|
|
6175
|
+
* this surface first opens (one pass per host process — later opens no-op
|
|
6176
|
+
* server-side, and the host answers at once). Fire-and-forget: an older host
|
|
6177
|
+
* without the route, or a transport hiccup, just leaves the panel on the
|
|
6178
|
+
* rows it already has.
|
|
6179
|
+
*/
|
|
6180
|
+
function requestActivityBackfill() {
|
|
6181
|
+
try {
|
|
6182
|
+
fetch(BACKFILL_ROUTE, { method: "POST" }).catch(() => {});
|
|
6183
|
+
} catch {}
|
|
6184
|
+
}
|
|
6171
6185
|
/**
|
|
6172
6186
|
* The row's relative-activity label ("3m ago"), unit-stepped: under a
|
|
6173
6187
|
* minute reads "just now", then minutes, hours, days. A future or invalid
|
|
@@ -6668,7 +6682,10 @@ window.__ModuleLoader__.load({
|
|
|
6668
6682
|
const rows = (0, react.useMemo)(() => rowsOfSnapshot(snapshot, wsSnapshot), [snapshot, wsSnapshot]);
|
|
6669
6683
|
const groups = (0, react.useMemo)(() => sessionGroupsOf(wsSnapshot), [wsSnapshot]);
|
|
6670
6684
|
(0, react.useEffect)(() => {
|
|
6671
|
-
if (open)
|
|
6685
|
+
if (open) {
|
|
6686
|
+
requestActivityBackfill();
|
|
6687
|
+
refreshSessions(ctx);
|
|
6688
|
+
}
|
|
6672
6689
|
}, [open]);
|
|
6673
6690
|
(0, react.useEffect)(() => {
|
|
6674
6691
|
setPage(0);
|
|
@@ -9475,7 +9492,7 @@ window.__ModuleLoader__.load({
|
|
|
9475
9492
|
return function PluginInfo() {
|
|
9476
9493
|
const [latest, setLatest] = (0, react.useState)(null);
|
|
9477
9494
|
(0, react.useEffect)(() => {
|
|
9478
|
-
if ("0.53.
|
|
9495
|
+
if ("0.53.3".includes("-dev")) return;
|
|
9479
9496
|
let on = true;
|
|
9480
9497
|
fetchLatestVersion().then((v) => {
|
|
9481
9498
|
if (on && v) setLatest(v);
|
|
@@ -9484,8 +9501,8 @@ window.__ModuleLoader__.load({
|
|
|
9484
9501
|
on = false;
|
|
9485
9502
|
};
|
|
9486
9503
|
}, []);
|
|
9487
|
-
const update = latest !== null && isNewerVersion(latest, "0.53.
|
|
9488
|
-
const nameText = "dsh-context (v0.53.
|
|
9504
|
+
const update = latest !== null && isNewerVersion(latest, "0.53.3") ? latest : null;
|
|
9505
|
+
const nameText = "dsh-context (v0.53.3)";
|
|
9489
9506
|
const nameValue = [nameText];
|
|
9490
9507
|
if (update) nameValue.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9491
9508
|
className: "lc-pi-update",
|
package/lib/index.js
CHANGED
|
@@ -870,7 +870,7 @@ function removeSurfaceSeqs(st, claimed, goneSeq) {
|
|
|
870
870
|
* rather than through `deriveEventMessage`, whose 0.1.2-rc.1 generation knows
|
|
871
871
|
* nothing of the V3 `system/message` variant. A malformed payload reads null.
|
|
872
872
|
*/
|
|
873
|
-
function messageOf(data) {
|
|
873
|
+
function messageOf$1(data) {
|
|
874
874
|
const message = data?.message;
|
|
875
875
|
return message !== null && typeof message === "object" ? message : null;
|
|
876
876
|
}
|
|
@@ -1230,7 +1230,7 @@ function applyTimeline(state, event, bounds) {
|
|
|
1230
1230
|
pushSystem(s, {
|
|
1231
1231
|
seq: event.seq,
|
|
1232
1232
|
time: event.time,
|
|
1233
|
-
tokens: estimateSystemContent(messageOf(data)?.content)
|
|
1233
|
+
tokens: estimateSystemContent(messageOf$1(data)?.content)
|
|
1234
1234
|
});
|
|
1235
1235
|
break;
|
|
1236
1236
|
}
|
|
@@ -2058,8 +2058,17 @@ function createToolAttribution(ctx) {
|
|
|
2058
2058
|
}
|
|
2059
2059
|
//#endregion
|
|
2060
2060
|
//#region src/host/backfill.ts
|
|
2061
|
-
/**
|
|
2062
|
-
const
|
|
2061
|
+
/** The plugin's warm-up trigger route, under the authenticated `/api` fence. */
|
|
2062
|
+
const BACKFILL_ROUTE = "/api/dsh-context/backfill";
|
|
2063
|
+
/**
|
|
2064
|
+
* Inter-session pacing so a multi-hundred-session backfill never starve the
|
|
2065
|
+
* host: each cold read is a full durable-log decode, and a boot-time host
|
|
2066
|
+
* under sustained read pressure stalls its own client handshake (the
|
|
2067
|
+
* workspace sidebar rides it), so the pass breathes between sessions.
|
|
2068
|
+
*/
|
|
2069
|
+
const YIELD_MS = 100;
|
|
2070
|
+
/** The `name` dsh raises for a durable log its migration surface refuses. */
|
|
2071
|
+
const UNSUPPORTED_MIGRATION = "SessionFormatUnsupportedMigrationError";
|
|
2063
2072
|
function asRecord(value) {
|
|
2064
2073
|
return value !== null && typeof value === "object" ? value : null;
|
|
2065
2074
|
}
|
|
@@ -2114,11 +2123,63 @@ function isLive(sessions, id) {
|
|
|
2114
2123
|
}
|
|
2115
2124
|
}
|
|
2116
2125
|
/**
|
|
2117
|
-
*
|
|
2118
|
-
*
|
|
2126
|
+
* Whether the cold read failed because the running harness refuses to
|
|
2127
|
+
* migrate this log — a permanent, source-side refusal (the artifact is left
|
|
2128
|
+
* unchanged, so retrying cannot succeed). Matched by the error's documented
|
|
2129
|
+
* `name`, so no dsh symbol needs importing and every supported baseline
|
|
2130
|
+
* classifies alike: an unknown error shape just falls to the warn path.
|
|
2131
|
+
*/
|
|
2132
|
+
function isUnsupportedMigration(error) {
|
|
2133
|
+
try {
|
|
2134
|
+
return asRecord(error)?.name === UNSUPPORTED_MIGRATION;
|
|
2135
|
+
} catch {
|
|
2136
|
+
return false;
|
|
2137
|
+
}
|
|
2138
|
+
}
|
|
2139
|
+
/** The error's printable form — a hostile error may throw on its own toString. */
|
|
2140
|
+
function messageOf(error) {
|
|
2141
|
+
try {
|
|
2142
|
+
return String(error);
|
|
2143
|
+
} catch {
|
|
2144
|
+
return "unprintable error";
|
|
2145
|
+
}
|
|
2146
|
+
}
|
|
2147
|
+
/**
|
|
2148
|
+
* Arm the warm-up behind its trigger route. The route flips `requested`
|
|
2149
|
+
* when the dashboard first opens; the cold-path faces compose `launch`.
|
|
2150
|
+
* Either half may land first; the first request after both launches the one
|
|
2151
|
+
* pass, and every later request is a no-op. Returns the deferred injects'
|
|
2152
|
+
* disposer (abort on unload).
|
|
2119
2153
|
*/
|
|
2120
2154
|
function watchActivityBackfill(ctx) {
|
|
2121
|
-
|
|
2155
|
+
let requested = false;
|
|
2156
|
+
let started = false;
|
|
2157
|
+
let launch = null;
|
|
2158
|
+
const tryLaunch = () => {
|
|
2159
|
+
if (!requested || started || launch === null) return;
|
|
2160
|
+
started = true;
|
|
2161
|
+
launch();
|
|
2162
|
+
};
|
|
2163
|
+
const routeFiber = ctx.inject(["connection"], (c) => {
|
|
2164
|
+
const connection = c.get("connection");
|
|
2165
|
+
const register = typeof connection?.fetch?.register === "function" ? connection.fetch.register.bind(connection.fetch) : void 0;
|
|
2166
|
+
if (register === void 0) return;
|
|
2167
|
+
try {
|
|
2168
|
+
c.effect(() => register({
|
|
2169
|
+
path: BACKFILL_ROUTE,
|
|
2170
|
+
methods: ["POST"],
|
|
2171
|
+
requestBody: "buffered",
|
|
2172
|
+
fetch: () => {
|
|
2173
|
+
requested = true;
|
|
2174
|
+
tryLaunch();
|
|
2175
|
+
return Response.json({ ok: true }, { headers: { "cache-control": "no-store" } });
|
|
2176
|
+
}
|
|
2177
|
+
}), "dsh-context: backfill route");
|
|
2178
|
+
} catch {
|
|
2179
|
+
return;
|
|
2180
|
+
}
|
|
2181
|
+
});
|
|
2182
|
+
const runnerFiber = ctx.inject([
|
|
2122
2183
|
"sessionQuery",
|
|
2123
2184
|
"sessionProjectionCache",
|
|
2124
2185
|
"sessionPersistence",
|
|
@@ -2137,6 +2198,7 @@ function watchActivityBackfill(ctx) {
|
|
|
2137
2198
|
const listed = await query.listSessions(abort.signal);
|
|
2138
2199
|
if (!Array.isArray(listed)) return;
|
|
2139
2200
|
let folded = 0;
|
|
2201
|
+
let refused = 0;
|
|
2140
2202
|
for (const record of listed) {
|
|
2141
2203
|
if (abort.signal.aborted) return;
|
|
2142
2204
|
const header = headerOf(record);
|
|
@@ -2148,21 +2210,28 @@ function watchActivityBackfill(ctx) {
|
|
|
2148
2210
|
cache.coldSnapshot(log.header, log.inheritedEventCount, log.events);
|
|
2149
2211
|
folded++;
|
|
2150
2212
|
} catch (error) {
|
|
2151
|
-
|
|
2213
|
+
if (isUnsupportedMigration(error)) {
|
|
2214
|
+
refused++;
|
|
2215
|
+
ctx.logger.debug(`dsh-context: projection backfill skipped "${header.id}" (${messageOf(error)})`);
|
|
2216
|
+
} else ctx.logger.warn(`dsh-context: projection backfill skipped "${header.id}" (${messageOf(error)})`);
|
|
2152
2217
|
}
|
|
2153
2218
|
await new Promise((resolve) => setTimeout(resolve, YIELD_MS));
|
|
2154
2219
|
}
|
|
2155
2220
|
if (folded > 0) ctx.logger.info(`dsh-context: projection rows backfilled for ${folded} session(s)`);
|
|
2221
|
+
if (refused > 0) ctx.logger.info(`dsh-context: projection backfill skipped ${refused} session(s) (legacy log format is not migratable; sources left unchanged)`);
|
|
2156
2222
|
};
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2223
|
+
launch = () => {
|
|
2224
|
+
run().catch((error) => {
|
|
2225
|
+
if (!abort.signal.aborted) ctx.logger.warn(`dsh-context: projection backfill stopped early (${messageOf(error)})`);
|
|
2226
|
+
});
|
|
2227
|
+
};
|
|
2228
|
+
tryLaunch();
|
|
2160
2229
|
return () => {
|
|
2161
2230
|
abort.abort();
|
|
2162
2231
|
};
|
|
2163
2232
|
});
|
|
2164
2233
|
return () => {
|
|
2165
|
-
|
|
2234
|
+
for (const fiber of [routeFiber, runnerFiber]) fiber?.dispose?.();
|
|
2166
2235
|
};
|
|
2167
2236
|
}
|
|
2168
2237
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-context",
|
|
3
|
-
"version": "0.53.
|
|
3
|
+
"version": "0.53.3",
|
|
4
4
|
"description": "A DeepSeek Harness plugin for context insight and management, with context dashboard and context command, for understanding how the context is made of, and how it evolves.",
|
|
5
5
|
"author": "bowenliang123",
|
|
6
6
|
"repository": {
|