dsh-session-recall 0.6.0 → 0.7.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/README.md +1 -1
- package/lib/index.d.ts +6 -0
- package/lib/index.js +46 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ If you need agent memory orchestration, use a memory framework; if you need boun
|
|
|
21
21
|
| Capability focus | Memory frameworks | Generic transcript search | `dsh-session-recall` |
|
|
22
22
|
|---|---|---|---|
|
|
23
23
|
| Retrieval target | Derived memory objects | Varies by implementation | **Original session transcript events** |
|
|
24
|
-
| Scope control | Framework-specific | Often coarse | **cwd-scoped default + explicit `all_projects` gate** |
|
|
24
|
+
| Scope control | Framework-specific | Often coarse | **cwd-scoped default + explicit `all_projects`, `since_days`, `tools`, `errors_only` gate** |
|
|
25
25
|
| CJK behavior | Framework-specific | Often tokenizer-limited | **FTS + CJK zero-hit substring fallback** |
|
|
26
26
|
| Output contract | Usually framework-native | Varies | **Typed `recall` result with stable fields/hints** |
|
|
27
27
|
|
package/lib/index.d.ts
CHANGED
|
@@ -136,6 +136,12 @@ interface RecallArgs {
|
|
|
136
136
|
all_projects?: boolean;
|
|
137
137
|
limit?: number;
|
|
138
138
|
cursor?: string;
|
|
139
|
+
/** Only return sessions/entries newer than this many days. */
|
|
140
|
+
since_days?: number;
|
|
141
|
+
/** Only return tool-related events whose tool name matches one of these (substring, case-insensitive). */
|
|
142
|
+
tools?: readonly string[];
|
|
143
|
+
/** Only return failed tool calls (tool results carrying an error). */
|
|
144
|
+
errors_only?: boolean;
|
|
139
145
|
}
|
|
140
146
|
//#endregion
|
|
141
147
|
//#region src/rank.d.ts
|
package/lib/index.js
CHANGED
|
@@ -297,6 +297,34 @@ function cjkZeroHitHint(query, zeroHits, enabled) {
|
|
|
297
297
|
* calling agent's own project cwd unless the model explicitly widens the
|
|
298
298
|
* scope and the deployment allows it.
|
|
299
299
|
*/
|
|
300
|
+
/** Whether a best-match event type is a tool result (vs user/assistant message). */
|
|
301
|
+
function isToolResultType(type) {
|
|
302
|
+
return type === "tool/result" || type.startsWith("tool/");
|
|
303
|
+
}
|
|
304
|
+
/** Apply the dimensional post-filters (sinceDays / tools / errorsOnly) to recall items. */
|
|
305
|
+
function applyDimensionFilters(items, args, now = Date.now()) {
|
|
306
|
+
let out = [...items];
|
|
307
|
+
if (args.since_days !== void 0 && args.since_days > 0) {
|
|
308
|
+
const cutoff = now - args.since_days * 864e5;
|
|
309
|
+
out = out.filter((item) => {
|
|
310
|
+
return Math.max(item.createdAt ?? 0, item.bestMatch?.time ?? 0) >= cutoff;
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
if (args.tools !== void 0 && args.tools.length > 0) {
|
|
314
|
+
const needles = args.tools.map((t) => t.toLowerCase());
|
|
315
|
+
out = out.filter((item) => {
|
|
316
|
+
if (!isToolResultType(item.bestMatch?.type ?? "")) return false;
|
|
317
|
+
const snippet = (item.bestMatch?.snippet ?? "").toLowerCase();
|
|
318
|
+
return needles.some((n) => snippet.includes(n));
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
if (args.errors_only === true) out = out.filter((item) => {
|
|
322
|
+
if ((item.bestMatch?.type ?? "") !== "tool/result") return false;
|
|
323
|
+
const snippet = item.bestMatch?.snippet ?? "";
|
|
324
|
+
return snippet.includes("[error]") || /\berror\b|\bfailed\b/i.test(snippet);
|
|
325
|
+
});
|
|
326
|
+
return out;
|
|
327
|
+
}
|
|
300
328
|
/** Walk a lineage trace and collect every session id in the tree. */
|
|
301
329
|
function collectLineageIds(trace) {
|
|
302
330
|
const ids = /* @__PURE__ */ new Set();
|
|
@@ -317,7 +345,7 @@ const RECALL_TOOL_DESCRIPTION = [
|
|
|
317
345
|
"Matches whole words/phrases for English and code identifiers; a zero-hit Chinese (CJK) query automatically falls back to a substring scan in which every whitespace-separated term must match. Returns the best-matching event snippet per session plus the session id.",
|
|
318
346
|
"Then use the read tool on files, or ask the user, to go deeper — this tool only points at history, it does not resume sessions.",
|
|
319
347
|
"To save a full evidence report of a hit session, call the transcript_export tool (from dsh-session-export) with its sessionId when available.",
|
|
320
|
-
"Scoping: by default only sessions started in the current project directory; pass all_projects=true to search everywhere (the deployment may ignore it or require user approval).",
|
|
348
|
+
"Scoping: by default only sessions started in the current project directory; pass all_projects=true to search everywhere (the deployment may ignore it or require user approval). Narrow further with since_days (only sessions newer than N days), tools (only tool events whose tool name matches, e.g. tools=[\"bash\"]), or errors_only=true (only failed tool calls).",
|
|
321
349
|
"When the deployment enables redaction, secret-looking text in snippets appears as [REDACTED] or a #hash marker — treat it as removed; do not try to reconstruct or echo it.",
|
|
322
350
|
"The first search after startup may be slow while the index builds."
|
|
323
351
|
].join(" ");
|
|
@@ -600,6 +628,19 @@ function createRecallTool(config, engine, approver) {
|
|
|
600
628
|
cursor: {
|
|
601
629
|
type: "string",
|
|
602
630
|
description: "Opaque continuation cursor from a previous recall result with hasMore=true."
|
|
631
|
+
},
|
|
632
|
+
since_days: {
|
|
633
|
+
type: "integer",
|
|
634
|
+
description: "Only return sessions newer than this many days (0 = no time filter)."
|
|
635
|
+
},
|
|
636
|
+
tools: {
|
|
637
|
+
type: "array",
|
|
638
|
+
items: { type: "string" },
|
|
639
|
+
description: "Only return tool events whose tool name contains one of these substrings (case-insensitive), e.g. [\"bash\",\"read\"]."
|
|
640
|
+
},
|
|
641
|
+
errors_only: {
|
|
642
|
+
type: "boolean",
|
|
643
|
+
description: "Only return failed tool calls (tool results carrying an error)."
|
|
603
644
|
}
|
|
604
645
|
},
|
|
605
646
|
output: {
|
|
@@ -675,7 +716,7 @@ function createRecallTool(config, engine, approver) {
|
|
|
675
716
|
redacted: 0,
|
|
676
717
|
diagnostics: null
|
|
677
718
|
};
|
|
678
|
-
let items = eventItems(page, sessionId);
|
|
719
|
+
let items = applyDimensionFilters(eventItems(page, sessionId), args);
|
|
679
720
|
let hint = null;
|
|
680
721
|
let diagnostics = {
|
|
681
722
|
source: "fts",
|
|
@@ -690,7 +731,7 @@ function createRecallTool(config, engine, approver) {
|
|
|
690
731
|
scanBudget: cfg.cjkFallbackScanMax,
|
|
691
732
|
ranked: false
|
|
692
733
|
};
|
|
693
|
-
if (docs.length > 0) items = docs.slice(0, limit).map((doc) => ({
|
|
734
|
+
if (docs.length > 0) items = applyDimensionFilters(docs.slice(0, limit).map((doc) => ({
|
|
694
735
|
sessionId,
|
|
695
736
|
id8: id8(sessionId),
|
|
696
737
|
title: null,
|
|
@@ -704,7 +745,7 @@ function createRecallTool(config, engine, approver) {
|
|
|
704
745
|
time: doc.time,
|
|
705
746
|
snippet: snippetAround(doc.text, highlight, CJK_SNIPPET_CHARS)
|
|
706
747
|
}
|
|
707
|
-
}));
|
|
748
|
+
})), args);
|
|
708
749
|
hint = items.length > 0 ? cjkFallbackHint(items.length, cfg.cjkHint) : cjkZeroHitHint(query, true, cfg.cjkHint);
|
|
709
750
|
} else if (items.length === 0) hint = cjkZeroHitHint(query, true, cfg.cjkHint);
|
|
710
751
|
const red = applyRedaction(items);
|
|
@@ -738,6 +779,7 @@ function createRecallTool(config, engine, approver) {
|
|
|
738
779
|
const ranked = rankingActive(rankingOptions);
|
|
739
780
|
let items = rankItems(toItems(page.items, titles).filter((item) => cwdAllowed(item.cwd, cfg)), rankingOptions);
|
|
740
781
|
if (allowedIds != null) items = items.filter((item) => allowedIds.has(item.sessionId));
|
|
782
|
+
items = applyDimensionFilters(items, args);
|
|
741
783
|
let hint = null;
|
|
742
784
|
let fallbackRan = false;
|
|
743
785
|
let diagnostics = {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-session-recall",
|
|
3
3
|
"description": "Deterministic cross-session transcript retrieval for DeepSeek Harness: the model-facing `recall` tool searches past session logs with explicit scope control",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.7.0",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|