dsh-sessions-manager 3.7.2 → 3.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +16 -7
- package/README.md +16 -7
- package/lib/client.js +98 -5
- package/lib/client.js.map +2 -2
- package/lib/index.js +83 -7
- package/lib/index.js.map +3 -3
- package/package.json +9 -9
- package/src/active-session.js +87 -0
- package/src/auto-archive.js +9 -2
- package/src/client/index.jsx +135 -11
- package/src/index.js +42 -4
package/lib/index.js
CHANGED
|
@@ -960,7 +960,9 @@ function pickInactiveCandidates(items, options = {}) {
|
|
|
960
960
|
const now = Number.isFinite(options.now) ? options.now : Date.now();
|
|
961
961
|
const cutoff = now - days * DAY_MS;
|
|
962
962
|
const skipStarred = options.skipStarred !== false;
|
|
963
|
-
const
|
|
963
|
+
const activeIds = new Set(
|
|
964
|
+
Array.isArray(options.activeSessionIds) ? options.activeSessionIds.map((id) => String(id)) : options.activeSessionId != null ? [String(options.activeSessionId)] : []
|
|
965
|
+
);
|
|
964
966
|
const list = Array.isArray(items) ? items : [];
|
|
965
967
|
const out = [];
|
|
966
968
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -970,7 +972,7 @@ function pickInactiveCandidates(items, options = {}) {
|
|
|
970
972
|
if (seen.has(id)) continue;
|
|
971
973
|
if (item.archived) continue;
|
|
972
974
|
if (skipStarred && item.starred) continue;
|
|
973
|
-
if (
|
|
975
|
+
if (activeIds.has(id)) continue;
|
|
974
976
|
const updatedAt = Number(item.updatedAt);
|
|
975
977
|
if (!Number.isFinite(updatedAt) || updatedAt <= 0) continue;
|
|
976
978
|
if (updatedAt < cutoff) {
|
|
@@ -1350,6 +1352,58 @@ function createEmptyScanStore({ dir, file }) {
|
|
|
1350
1352
|
};
|
|
1351
1353
|
}
|
|
1352
1354
|
|
|
1355
|
+
// src/active-session.js
|
|
1356
|
+
var DEFAULT_ACTIVE_TTL_MS = 45 * 1e3;
|
|
1357
|
+
var MAX_ACTIVE_REPORTS = 32;
|
|
1358
|
+
function isUsableSessionId(value) {
|
|
1359
|
+
return typeof value === "string" && value.length > 0 && value.length <= 200 && !/[\\/\0]/.test(value) && value !== "." && value !== "..";
|
|
1360
|
+
}
|
|
1361
|
+
function createActiveSessionTracker(options = {}) {
|
|
1362
|
+
const ttl = Number.isFinite(options.ttlMs) ? Number(options.ttlMs) : DEFAULT_ACTIVE_TTL_MS;
|
|
1363
|
+
const now = typeof options.now === "function" ? options.now : () => Date.now();
|
|
1364
|
+
const reports = /* @__PURE__ */ new Map();
|
|
1365
|
+
function trim(at) {
|
|
1366
|
+
for (const [key, value] of reports) if (at - value.at > ttl) reports.delete(key);
|
|
1367
|
+
while (reports.size > MAX_ACTIVE_REPORTS) {
|
|
1368
|
+
const oldest = reports.keys().next().value;
|
|
1369
|
+
if (oldest === void 0) break;
|
|
1370
|
+
reports.delete(oldest);
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
function report(clientId, sessionId, at = now()) {
|
|
1374
|
+
const key = typeof clientId === "string" && clientId ? clientId.slice(0, 64) : "default";
|
|
1375
|
+
if (sessionId === null || sessionId === void 0 || sessionId === "") {
|
|
1376
|
+
reports.delete(key);
|
|
1377
|
+
return true;
|
|
1378
|
+
}
|
|
1379
|
+
if (!isUsableSessionId(sessionId)) return false;
|
|
1380
|
+
reports.set(key, { id: String(sessionId), at });
|
|
1381
|
+
trim(at);
|
|
1382
|
+
return true;
|
|
1383
|
+
}
|
|
1384
|
+
function activeIds(at = now()) {
|
|
1385
|
+
const out = /* @__PURE__ */ new Set();
|
|
1386
|
+
for (const [key, value] of reports) {
|
|
1387
|
+
if (at - value.at > ttl) {
|
|
1388
|
+
reports.delete(key);
|
|
1389
|
+
continue;
|
|
1390
|
+
}
|
|
1391
|
+
out.add(value.id);
|
|
1392
|
+
}
|
|
1393
|
+
return out;
|
|
1394
|
+
}
|
|
1395
|
+
return {
|
|
1396
|
+
report,
|
|
1397
|
+
activeIds,
|
|
1398
|
+
get size() {
|
|
1399
|
+
return reports.size;
|
|
1400
|
+
},
|
|
1401
|
+
clear() {
|
|
1402
|
+
reports.clear();
|
|
1403
|
+
}
|
|
1404
|
+
};
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1353
1407
|
// src/handle-era-paths.js
|
|
1354
1408
|
import { readdir as readdir2, stat as stat2 } from "node:fs/promises";
|
|
1355
1409
|
import { basename, join as join10 } from "node:path";
|
|
@@ -1985,7 +2039,7 @@ function emptyScanCandidate(sizeBytes) {
|
|
|
1985
2039
|
}
|
|
1986
2040
|
|
|
1987
2041
|
// src/index.js
|
|
1988
|
-
var BUILD_STAMP = true ? "3.7.
|
|
2042
|
+
var BUILD_STAMP = true ? "3.7.4+a351e274" : "dev";
|
|
1989
2043
|
var name = "dsh-sessions-manager";
|
|
1990
2044
|
var inject = ["webServer", "workspaceRegistry", "sessionPersistence", "sessionQuery", "storageDomain"];
|
|
1991
2045
|
var MAX_TITLE = 80;
|
|
@@ -2052,7 +2106,7 @@ function requireSessionId(value) {
|
|
|
2052
2106
|
}
|
|
2053
2107
|
return value;
|
|
2054
2108
|
}
|
|
2055
|
-
function
|
|
2109
|
+
function legacyActiveSessionId(context) {
|
|
2056
2110
|
try {
|
|
2057
2111
|
const a = context.get("activeSession");
|
|
2058
2112
|
if (a != null) return a && a.id != null ? a.id : typeof a === "string" ? a : null;
|
|
@@ -2070,6 +2124,12 @@ function getActiveSessionId(context) {
|
|
|
2070
2124
|
}
|
|
2071
2125
|
return null;
|
|
2072
2126
|
}
|
|
2127
|
+
function getActiveSessionIds(context, tracker) {
|
|
2128
|
+
const reported = tracker ? tracker.activeIds() : null;
|
|
2129
|
+
if (reported && reported.size) return reported;
|
|
2130
|
+
const legacy = legacyActiveSessionId(context);
|
|
2131
|
+
return legacy != null ? /* @__PURE__ */ new Set([String(legacy)]) : /* @__PURE__ */ new Set();
|
|
2132
|
+
}
|
|
2073
2133
|
function apply(ctx) {
|
|
2074
2134
|
const w = ctx.workspaceRegistry;
|
|
2075
2135
|
const sp = ctx.sessionPersistence;
|
|
@@ -2081,6 +2141,7 @@ function apply(ctx) {
|
|
|
2081
2141
|
const metaCache = createSessionMetaCache();
|
|
2082
2142
|
const titleIndex = createTitleIndexStore({ dir: TRASH_DIR, file: join12(TRASH_DIR, "title-index.json") });
|
|
2083
2143
|
const emptyIndex = createEmptyScanStore({ dir: TRASH_DIR });
|
|
2144
|
+
const activeTracker = createActiveSessionTracker();
|
|
2084
2145
|
const EMPTY_VERDICT_TTL_MS = 14 * 24 * 3600 * 1e3;
|
|
2085
2146
|
async function hydrateFromPersist(ids, statsById) {
|
|
2086
2147
|
const hits = /* @__PURE__ */ new Map();
|
|
@@ -2756,8 +2817,9 @@ function apply(ctx) {
|
|
|
2756
2817
|
}
|
|
2757
2818
|
async function moveOne(sid, targetPath) {
|
|
2758
2819
|
requireCapability(capabilities, "move");
|
|
2759
|
-
const
|
|
2760
|
-
|
|
2820
|
+
const activeIds = getActiveSessionIds(ctx, activeTracker);
|
|
2821
|
+
const activeId = activeIds.values().next().value != null ? activeIds.values().next().value : null;
|
|
2822
|
+
if (activeIds.has(String(sid)) || activeId != null && String(activeId) === String(sid)) {
|
|
2761
2823
|
const error = new Error("\u4F1A\u8BDD\u6B63\u88AB DSH \u6253\u5F00\uFF0C\u6682\u65F6\u65E0\u6CD5\u79FB\u52A8\uFF1B\u8BF7\u91CD\u542F DSH \u540E\u518D\u8BD5\u3002");
|
|
2762
2824
|
error.status = 409;
|
|
2763
2825
|
error.code = "DSM_SESSION_BUSY";
|
|
@@ -3300,7 +3362,7 @@ function apply(ctx) {
|
|
|
3300
3362
|
const candidates = pickInactiveCandidates(items, {
|
|
3301
3363
|
inactiveDays: days,
|
|
3302
3364
|
skipStarred: store.settings.skipStarred,
|
|
3303
|
-
|
|
3365
|
+
activeSessionIds: [...getActiveSessionIds(ctx, activeTracker)],
|
|
3304
3366
|
now
|
|
3305
3367
|
});
|
|
3306
3368
|
let archived = 0;
|
|
@@ -3636,6 +3698,20 @@ function apply(ctx) {
|
|
|
3636
3698
|
path: "/archived-sessions/capabilities",
|
|
3637
3699
|
handler: async (req, res) => json(res, { ...capabilities, buildStamp: BUILD_STAMP })
|
|
3638
3700
|
}));
|
|
3701
|
+
disposers.push(ctx.webServer.register({
|
|
3702
|
+
kind: "exact",
|
|
3703
|
+
path: "/archived-sessions/active-session",
|
|
3704
|
+
handler: async (req, res) => {
|
|
3705
|
+
const body = await readJsonBody(req);
|
|
3706
|
+
const clientId = body && typeof body.clientId === "string" ? body.clientId : "default";
|
|
3707
|
+
const sid = body && typeof body.sessionId === "string" && body.sessionId ? body.sessionId : null;
|
|
3708
|
+
const accepted = activeTracker.report(clientId, sid);
|
|
3709
|
+
json(res, {
|
|
3710
|
+
ok: accepted,
|
|
3711
|
+
activeSessionIds: [...activeTracker.activeIds()]
|
|
3712
|
+
});
|
|
3713
|
+
}
|
|
3714
|
+
}));
|
|
3639
3715
|
disposers.push(ctx.webServer.register({
|
|
3640
3716
|
kind: "exact",
|
|
3641
3717
|
path: "/archived-sessions/list",
|