dsh-reference-session-collector 0.2.0-beta.0 → 0.2.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/lib/index.d.ts +6 -0
- package/lib/index.js +14 -11
- package/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/surface.ts +18 -7
package/lib/index.d.ts
CHANGED
|
@@ -388,6 +388,12 @@ interface GroupedSearchRequest {
|
|
|
388
388
|
limit?: number;
|
|
389
389
|
/** R3:true=snippet 取材切 redacted_search_text(命中/排序不变,fts 仍原文)。 */
|
|
390
390
|
redact?: boolean;
|
|
391
|
+
/**
|
|
392
|
+
* 命中展开(steward「分开显示」开关,wire `expand=1`):true=每条候选行
|
|
393
|
+
* 各自成命中(同会话多行按全局分数序出现);缺省 false=会话分组各取
|
|
394
|
+
* 最强命中(既有聚合臂行为零改动,limit 语义随之从会话数变行数)。
|
|
395
|
+
*/
|
|
396
|
+
expand?: boolean;
|
|
391
397
|
}
|
|
392
398
|
/** 分组命中(wire 蛇形,会话级最强命中)。 */
|
|
393
399
|
interface GroupedSearchHit {
|
package/lib/index.js
CHANGED
|
@@ -385,18 +385,20 @@ function searchGrouped(ctx, request) {
|
|
|
385
385
|
WHERE segments_fts MATCH ?
|
|
386
386
|
AND seg.kind IN (${placeholders}) ${surfaceClause} ${archivedClause} ${dateClause}
|
|
387
387
|
ORDER BY rank LIMIT ?`;
|
|
388
|
-
const
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
388
|
+
const scored = ctx.store.db.prepare(sql).all(match, ...kinds, ...dateParams, SEARCH_SCAN_LIMIT).map((doc) => ({
|
|
389
|
+
doc,
|
|
390
|
+
score: -Number(doc.rank) * (SEARCH_TYPE_WEIGHT[doc.kind] ?? 1)
|
|
391
|
+
}));
|
|
392
|
+
let grouped;
|
|
393
|
+
if (request.expand === true) grouped = scored;
|
|
394
|
+
else {
|
|
395
|
+
const bestBySession = /* @__PURE__ */ new Map();
|
|
396
|
+
for (const entry of scored) {
|
|
397
|
+
const best = bestBySession.get(entry.doc.session_id);
|
|
398
|
+
if (best === void 0 || entry.score > best.score) bestBySession.set(entry.doc.session_id, entry);
|
|
399
|
+
}
|
|
400
|
+
grouped = [...bestBySession.values()];
|
|
398
401
|
}
|
|
399
|
-
const grouped = [...bestBySession.values()];
|
|
400
402
|
if (request.sortBy === "time") grouped.sort((a, b) => b.doc.updated_at - a.doc.updated_at || b.score - a.score);
|
|
401
403
|
else grouped.sort((a, b) => b.score - a.score);
|
|
402
404
|
const hits = grouped.slice(0, limit).map(({ doc }) => ({
|
|
@@ -2388,6 +2390,7 @@ async function handleDrsRequest(deps, req, res) {
|
|
|
2388
2390
|
...url.searchParams.get("surface") === "0" ? { surfaceOnly: false } : {},
|
|
2389
2391
|
...url.searchParams.get("sort") === "time" ? { sortBy: "time" } : {},
|
|
2390
2392
|
...limitRaw !== null && Number.isFinite(Number(limitRaw)) ? { limit: Number(limitRaw) } : {},
|
|
2393
|
+
...url.searchParams.get("expand") === "1" ? { expand: true } : {},
|
|
2391
2394
|
...redact ? { redact: true } : {}
|
|
2392
2395
|
})
|
|
2393
2396
|
});
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -309,6 +309,7 @@ export async function handleDrsRequest(deps: DrsHandlerDeps, req: IncomingMessag
|
|
|
309
309
|
...(url.searchParams.get('surface') === '0' ? { surfaceOnly: false } : {}),
|
|
310
310
|
...(url.searchParams.get('sort') === 'time' ? { sortBy: 'time' as const } : {}),
|
|
311
311
|
...(limitRaw !== null && Number.isFinite(Number(limitRaw)) ? { limit: Number(limitRaw) } : {}),
|
|
312
|
+
...(url.searchParams.get('expand') === '1' ? { expand: true } : {}),
|
|
312
313
|
...(redact ? { redact: true } : {}),
|
|
313
314
|
})
|
|
314
315
|
writeJson(res, 200, { ok: true, ...grouped })
|
package/src/surface.ts
CHANGED
|
@@ -379,6 +379,12 @@ export interface GroupedSearchRequest {
|
|
|
379
379
|
limit?: number
|
|
380
380
|
/** R3:true=snippet 取材切 redacted_search_text(命中/排序不变,fts 仍原文)。 */
|
|
381
381
|
redact?: boolean
|
|
382
|
+
/**
|
|
383
|
+
* 命中展开(steward「分开显示」开关,wire `expand=1`):true=每条候选行
|
|
384
|
+
* 各自成命中(同会话多行按全局分数序出现);缺省 false=会话分组各取
|
|
385
|
+
* 最强命中(既有聚合臂行为零改动,limit 语义随之从会话数变行数)。
|
|
386
|
+
*/
|
|
387
|
+
expand?: boolean
|
|
382
388
|
}
|
|
383
389
|
|
|
384
390
|
/** 分组命中(wire 蛇形,会话级最强命中)。 */
|
|
@@ -445,14 +451,19 @@ export function searchGrouped(ctx: QueryContext, request: GroupedSearchRequest):
|
|
|
445
451
|
title: string
|
|
446
452
|
updated_at: number
|
|
447
453
|
}[]
|
|
448
|
-
const
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
+
const scored = docs.map(doc => ({ doc, score: -Number(doc.rank) * (SEARCH_TYPE_WEIGHT[doc.kind] ?? 1) }))
|
|
455
|
+
let grouped: typeof scored
|
|
456
|
+
if (request.expand === true) {
|
|
457
|
+
// 命中展开:不折叠,每条候选行都是命中(同会话多行各自显示)。
|
|
458
|
+
grouped = scored
|
|
459
|
+
} else {
|
|
460
|
+
const bestBySession = new Map<string, { doc: typeof docs[number]; score: number }>()
|
|
461
|
+
for (const entry of scored) {
|
|
462
|
+
const best = bestBySession.get(entry.doc.session_id)
|
|
463
|
+
if (best === undefined || entry.score > best.score) bestBySession.set(entry.doc.session_id, entry)
|
|
464
|
+
}
|
|
465
|
+
grouped = [...bestBySession.values()]
|
|
454
466
|
}
|
|
455
|
-
const grouped = [...bestBySession.values()]
|
|
456
467
|
if (request.sortBy === 'time') {
|
|
457
468
|
grouped.sort((a, b) => (b.doc.updated_at - a.doc.updated_at) || (b.score - a.score))
|
|
458
469
|
} else {
|