claude-memory-layer 1.0.32 → 1.0.33
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/cli/index.js +1110 -72
- package/dist/cli/index.js.map +4 -4
- package/dist/core/index.js +414 -25
- package/dist/core/index.js.map +2 -2
- package/dist/hooks/post-tool-use.js +416 -27
- package/dist/hooks/post-tool-use.js.map +2 -2
- package/dist/hooks/semantic-daemon.js +416 -27
- package/dist/hooks/semantic-daemon.js.map +2 -2
- package/dist/hooks/session-end.js +416 -27
- package/dist/hooks/session-end.js.map +2 -2
- package/dist/hooks/session-start.js +416 -27
- package/dist/hooks/session-start.js.map +2 -2
- package/dist/hooks/stop.js +416 -27
- package/dist/hooks/stop.js.map +2 -2
- package/dist/hooks/user-prompt-submit.js +504 -34
- package/dist/hooks/user-prompt-submit.js.map +2 -2
- package/dist/index.js +416 -27
- package/dist/index.js.map +2 -2
- package/dist/mcp/index.js +407 -32
- package/dist/mcp/index.js.map +2 -2
- package/dist/server/api/index.js +850 -44
- package/dist/server/api/index.js.map +3 -3
- package/dist/server/index.js +1073 -64
- package/dist/server/index.js.map +3 -3
- package/dist/services/memory-service.js +416 -27
- package/dist/services/memory-service.js.map +2 -2
- package/dist/ui/assets/js/bootstrap.js +2 -0
- package/dist/ui/assets/js/overview.js +166 -3
- package/dist/ui/assets/js/state.js +3 -0
- package/dist/ui/index.html +20 -0
- package/dist/ui/style.css +193 -0
- package/package.json +5 -1
package/dist/mcp/index.js
CHANGED
|
@@ -10308,12 +10308,12 @@ var tools = [
|
|
|
10308
10308
|
projectPath: projectPathProperty,
|
|
10309
10309
|
refreshLatest: {
|
|
10310
10310
|
type: "boolean",
|
|
10311
|
-
description: "
|
|
10311
|
+
description: "Import latest local session history before retrieval. Generic continuation queries auto-refresh when absolute projectPath is supplied and no sessionId filter is set; set false to opt out. Auto-refresh and explicit true both mutate project memory; explicit true also requires absolute projectPath."
|
|
10312
10312
|
},
|
|
10313
10313
|
refreshSources: {
|
|
10314
10314
|
type: "array",
|
|
10315
10315
|
items: { type: "string", enum: ["claude", "codex", "hermes"] },
|
|
10316
|
-
description: "Sources to refresh when refreshLatest is true (default: hermes and codex)"
|
|
10316
|
+
description: "Sources to refresh when refreshLatest is true or auto-refresh runs (default: hermes and codex)"
|
|
10317
10317
|
},
|
|
10318
10318
|
refreshSessionLimit: {
|
|
10319
10319
|
type: "number",
|
|
@@ -12667,10 +12667,15 @@ function sqliteClose(db) {
|
|
|
12667
12667
|
function toDateFromSQLite(value) {
|
|
12668
12668
|
if (value instanceof Date)
|
|
12669
12669
|
return value;
|
|
12670
|
-
if (typeof value === "string")
|
|
12671
|
-
return new Date(value);
|
|
12672
12670
|
if (typeof value === "number")
|
|
12673
12671
|
return new Date(value);
|
|
12672
|
+
if (typeof value === "string") {
|
|
12673
|
+
const trimmed = value.trim();
|
|
12674
|
+
if (/^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?$/.test(trimmed)) {
|
|
12675
|
+
return /* @__PURE__ */ new Date(trimmed.replace(" ", "T") + "Z");
|
|
12676
|
+
}
|
|
12677
|
+
return new Date(trimmed);
|
|
12678
|
+
}
|
|
12674
12679
|
return new Date(String(value));
|
|
12675
12680
|
}
|
|
12676
12681
|
function toSQLiteTimestamp(date) {
|
|
@@ -12736,6 +12741,13 @@ var MarkdownMirror2 = class {
|
|
|
12736
12741
|
};
|
|
12737
12742
|
|
|
12738
12743
|
// src/core/sqlite-event-store.ts
|
|
12744
|
+
function normalizeQueryRewriteKind(value) {
|
|
12745
|
+
const normalized = (value || "").trim().toLowerCase();
|
|
12746
|
+
if (normalized === "follow-up-context" || normalized === "intent-rewrite")
|
|
12747
|
+
return normalized;
|
|
12748
|
+
return "none";
|
|
12749
|
+
}
|
|
12750
|
+
var REWRITTEN_QUERY_REWRITE_KIND_SQL = `LOWER(TRIM(COALESCE(query_rewrite_kind, 'none'))) IN ('follow-up-context', 'intent-rewrite')`;
|
|
12739
12751
|
var SQLiteEventStore = class {
|
|
12740
12752
|
db;
|
|
12741
12753
|
initialized = false;
|
|
@@ -12996,6 +13008,8 @@ var SQLiteEventStore = class {
|
|
|
12996
13008
|
session_id TEXT,
|
|
12997
13009
|
project_hash TEXT,
|
|
12998
13010
|
query_text TEXT NOT NULL,
|
|
13011
|
+
raw_query_text TEXT,
|
|
13012
|
+
query_rewrite_kind TEXT,
|
|
12999
13013
|
strategy TEXT,
|
|
13000
13014
|
candidate_event_ids TEXT,
|
|
13001
13015
|
selected_event_ids TEXT,
|
|
@@ -13037,6 +13051,8 @@ var SQLiteEventStore = class {
|
|
|
13037
13051
|
CREATE INDEX IF NOT EXISTS idx_helpfulness_event ON memory_helpfulness(event_id);
|
|
13038
13052
|
CREATE INDEX IF NOT EXISTS idx_helpfulness_session ON memory_helpfulness(session_id);
|
|
13039
13053
|
CREATE INDEX IF NOT EXISTS idx_helpfulness_score ON memory_helpfulness(helpfulness_score DESC);
|
|
13054
|
+
CREATE INDEX IF NOT EXISTS idx_helpfulness_created_at ON memory_helpfulness(created_at);
|
|
13055
|
+
CREATE INDEX IF NOT EXISTS idx_helpfulness_measured_at ON memory_helpfulness(measured_at);
|
|
13040
13056
|
CREATE INDEX IF NOT EXISTS idx_retrieval_traces_created_at ON retrieval_traces(created_at DESC);
|
|
13041
13057
|
CREATE INDEX IF NOT EXISTS idx_retrieval_traces_project_hash ON retrieval_traces(project_hash);
|
|
13042
13058
|
CREATE INDEX IF NOT EXISTS idx_retrieval_traces_session_id ON retrieval_traces(session_id);
|
|
@@ -13070,6 +13086,18 @@ var SQLiteEventStore = class {
|
|
|
13070
13086
|
sqliteExec(this.db, `ALTER TABLE retrieval_traces ADD COLUMN candidate_details_json TEXT;`);
|
|
13071
13087
|
} catch {
|
|
13072
13088
|
}
|
|
13089
|
+
try {
|
|
13090
|
+
sqliteExec(this.db, `ALTER TABLE retrieval_traces ADD COLUMN raw_query_text TEXT;`);
|
|
13091
|
+
} catch {
|
|
13092
|
+
}
|
|
13093
|
+
try {
|
|
13094
|
+
sqliteExec(this.db, `ALTER TABLE retrieval_traces ADD COLUMN query_rewrite_kind TEXT;`);
|
|
13095
|
+
} catch {
|
|
13096
|
+
}
|
|
13097
|
+
try {
|
|
13098
|
+
sqliteExec(this.db, `CREATE INDEX IF NOT EXISTS idx_retrieval_traces_query_rewrite_kind ON retrieval_traces(query_rewrite_kind);`);
|
|
13099
|
+
} catch {
|
|
13100
|
+
}
|
|
13073
13101
|
const tableInfo = sqliteAll(this.db, "PRAGMA table_info(events)", []);
|
|
13074
13102
|
const columnNames = tableInfo.map((col) => col.name);
|
|
13075
13103
|
if (!columnNames.includes("access_count")) {
|
|
@@ -13855,8 +13883,11 @@ var SQLiteEventStore = class {
|
|
|
13855
13883
|
/**
|
|
13856
13884
|
* Get helpfulness statistics for dashboard
|
|
13857
13885
|
*/
|
|
13858
|
-
async getHelpfulnessStats() {
|
|
13886
|
+
async getHelpfulnessStats(since) {
|
|
13859
13887
|
await this.initialize();
|
|
13888
|
+
const sinceIso = since?.toISOString();
|
|
13889
|
+
const evaluatedWhere = sinceIso ? `WHERE measured_at IS NOT NULL AND datetime(created_at) >= datetime(?)` : `WHERE measured_at IS NOT NULL`;
|
|
13890
|
+
const totalWhere = sinceIso ? `WHERE datetime(created_at) >= datetime(?)` : ``;
|
|
13860
13891
|
const stats = sqliteGet(
|
|
13861
13892
|
this.db,
|
|
13862
13893
|
`SELECT
|
|
@@ -13866,11 +13897,13 @@ var SQLiteEventStore = class {
|
|
|
13866
13897
|
SUM(CASE WHEN helpfulness_score >= 0.4 AND helpfulness_score < 0.7 THEN 1 ELSE 0 END) as neutral,
|
|
13867
13898
|
SUM(CASE WHEN helpfulness_score < 0.4 THEN 1 ELSE 0 END) as unhelpful
|
|
13868
13899
|
FROM memory_helpfulness
|
|
13869
|
-
|
|
13900
|
+
${evaluatedWhere}`,
|
|
13901
|
+
sinceIso ? [sinceIso] : []
|
|
13870
13902
|
);
|
|
13871
13903
|
const totalRow = sqliteGet(
|
|
13872
13904
|
this.db,
|
|
13873
|
-
`SELECT COUNT(*) as total FROM memory_helpfulness
|
|
13905
|
+
`SELECT COUNT(*) as total FROM memory_helpfulness ${totalWhere}`,
|
|
13906
|
+
sinceIso ? [sinceIso] : []
|
|
13874
13907
|
);
|
|
13875
13908
|
return {
|
|
13876
13909
|
avgScore: Math.round((stats?.avg_score || 0) * 100) / 100,
|
|
@@ -13969,18 +14002,21 @@ var SQLiteEventStore = class {
|
|
|
13969
14002
|
async recordRetrievalTrace(input) {
|
|
13970
14003
|
await this.initialize();
|
|
13971
14004
|
const traceId = randomUUID5();
|
|
14005
|
+
const queryRewriteKind = normalizeQueryRewriteKind(input.queryRewriteKind);
|
|
13972
14006
|
sqliteRun(
|
|
13973
14007
|
this.db,
|
|
13974
14008
|
`INSERT INTO retrieval_traces (
|
|
13975
|
-
trace_id, session_id, project_hash, query_text, strategy,
|
|
14009
|
+
trace_id, session_id, project_hash, query_text, raw_query_text, query_rewrite_kind, strategy,
|
|
13976
14010
|
candidate_event_ids, selected_event_ids, candidate_details_json, selected_details_json,
|
|
13977
14011
|
candidate_count, selected_count, confidence, fallback_trace
|
|
13978
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
14012
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
13979
14013
|
[
|
|
13980
14014
|
traceId,
|
|
13981
14015
|
input.sessionId || null,
|
|
13982
14016
|
input.projectHash || null,
|
|
13983
14017
|
input.queryText,
|
|
14018
|
+
input.rawQueryText || null,
|
|
14019
|
+
queryRewriteKind,
|
|
13984
14020
|
input.strategy || null,
|
|
13985
14021
|
JSON.stringify(input.candidateEventIds || []),
|
|
13986
14022
|
JSON.stringify(input.selectedEventIds || []),
|
|
@@ -14006,6 +14042,8 @@ var SQLiteEventStore = class {
|
|
|
14006
14042
|
sessionId: row.session_id || void 0,
|
|
14007
14043
|
projectHash: row.project_hash || void 0,
|
|
14008
14044
|
queryText: row.query_text,
|
|
14045
|
+
rawQueryText: row.raw_query_text || void 0,
|
|
14046
|
+
queryRewriteKind: normalizeQueryRewriteKind(row.query_rewrite_kind),
|
|
14009
14047
|
strategy: row.strategy || void 0,
|
|
14010
14048
|
candidateEventIds: row.candidate_event_ids ? JSON.parse(row.candidate_event_ids) : [],
|
|
14011
14049
|
selectedEventIds: row.selected_event_ids ? JSON.parse(row.selected_event_ids) : [],
|
|
@@ -14032,6 +14070,11 @@ var SQLiteEventStore = class {
|
|
|
14032
14070
|
COUNT(*) as total_queries,
|
|
14033
14071
|
AVG(candidate_count) as avg_candidate_count,
|
|
14034
14072
|
AVG(selected_count) as avg_selected_count,
|
|
14073
|
+
SUM(CASE WHEN ${REWRITTEN_QUERY_REWRITE_KIND_SQL} THEN 1 ELSE 0 END) as rewritten_queries,
|
|
14074
|
+
SUM(CASE WHEN ${REWRITTEN_QUERY_REWRITE_KIND_SQL} AND selected_count > 0 THEN 1 ELSE 0 END) as rewritten_queries_with_selection,
|
|
14075
|
+
SUM(CASE WHEN NOT (${REWRITTEN_QUERY_REWRITE_KIND_SQL}) AND selected_count > 0 THEN 1 ELSE 0 END) as raw_queries_with_selection,
|
|
14076
|
+
AVG(CASE WHEN ${REWRITTEN_QUERY_REWRITE_KIND_SQL} THEN selected_count END) as avg_selected_count_for_rewritten_queries,
|
|
14077
|
+
AVG(CASE WHEN NOT (${REWRITTEN_QUERY_REWRITE_KIND_SQL}) THEN selected_count END) as avg_selected_count_for_raw_queries,
|
|
14035
14078
|
CASE
|
|
14036
14079
|
WHEN SUM(candidate_count) > 0 THEN (SUM(selected_count) * 1.0 / SUM(candidate_count))
|
|
14037
14080
|
ELSE 0
|
|
@@ -14039,15 +14082,41 @@ var SQLiteEventStore = class {
|
|
|
14039
14082
|
FROM retrieval_traces`,
|
|
14040
14083
|
[]
|
|
14041
14084
|
);
|
|
14085
|
+
const totalQueries = Number(row?.total_queries || 0);
|
|
14086
|
+
const rewrittenQueries = Number(row?.rewritten_queries || 0);
|
|
14087
|
+
const rawQueries = Math.max(0, totalQueries - rewrittenQueries);
|
|
14088
|
+
const rewrittenQueriesWithSelection = Number(row?.rewritten_queries_with_selection || 0);
|
|
14089
|
+
const rawQueriesWithSelection = Number(row?.raw_queries_with_selection || 0);
|
|
14042
14090
|
return {
|
|
14043
|
-
totalQueries
|
|
14091
|
+
totalQueries,
|
|
14044
14092
|
avgCandidateCount: Number(row?.avg_candidate_count || 0),
|
|
14045
14093
|
avgSelectedCount: Number(row?.avg_selected_count || 0),
|
|
14046
|
-
selectionRate: Number(row?.selection_rate || 0)
|
|
14094
|
+
selectionRate: Number(row?.selection_rate || 0),
|
|
14095
|
+
rewrittenQueries,
|
|
14096
|
+
rewriteRate: totalQueries > 0 ? rewrittenQueries / totalQueries : 0,
|
|
14097
|
+
rewrittenQueriesWithSelection,
|
|
14098
|
+
rawQueriesWithSelection,
|
|
14099
|
+
rewrittenSelectionRate: rewrittenQueries > 0 ? rewrittenQueriesWithSelection / rewrittenQueries : 0,
|
|
14100
|
+
rawSelectionRate: rawQueries > 0 ? rawQueriesWithSelection / rawQueries : 0,
|
|
14101
|
+
avgSelectedCountForRewrittenQueries: Number(row?.avg_selected_count_for_rewritten_queries || 0),
|
|
14102
|
+
avgSelectedCountForRawQueries: Number(row?.avg_selected_count_for_raw_queries || 0)
|
|
14047
14103
|
};
|
|
14048
14104
|
} catch (err) {
|
|
14049
14105
|
if (err?.message?.includes("no such table")) {
|
|
14050
|
-
return {
|
|
14106
|
+
return {
|
|
14107
|
+
totalQueries: 0,
|
|
14108
|
+
avgCandidateCount: 0,
|
|
14109
|
+
avgSelectedCount: 0,
|
|
14110
|
+
selectionRate: 0,
|
|
14111
|
+
rewrittenQueries: 0,
|
|
14112
|
+
rewriteRate: 0,
|
|
14113
|
+
rewrittenQueriesWithSelection: 0,
|
|
14114
|
+
rawQueriesWithSelection: 0,
|
|
14115
|
+
rewrittenSelectionRate: 0,
|
|
14116
|
+
rawSelectionRate: 0,
|
|
14117
|
+
avgSelectedCountForRewrittenQueries: 0,
|
|
14118
|
+
avgSelectedCountForRawQueries: 0
|
|
14119
|
+
};
|
|
14051
14120
|
}
|
|
14052
14121
|
throw err;
|
|
14053
14122
|
}
|
|
@@ -14869,8 +14938,55 @@ var LOW_SIGNAL_CONTEXT_PATTERNS = [
|
|
|
14869
14938
|
];
|
|
14870
14939
|
var CONTINUATION_QUERY_PATTERNS = [
|
|
14871
14940
|
/^\s*(?:continue|resume|next|what(?:'s| is)? next|next\s+(?:step|task|action)|recommended\s+(?:next\s+)?(?:step|task|action)|what should (?:we|i) do next)\??\s*$/i,
|
|
14872
|
-
/^\s*(?:이어서(?:\s
|
|
14941
|
+
/^\s*(?:응\s*)?(?:이어서(?:\s*진행(?:해줘)?)?|계속(?:\s*해줘)?|다음\s*(?:단계|작업|추천\s*작업|추천|할\s*일)?(?:은|는)?(?:\s*(?:뭐야|진행(?:해줘)?))?\??|남은\s*(?:추가(?:로)?\s*)?(?:(?:할\s*만한\s*)?(?:작업|일)|할\s*일)?(?:은|는)?\s*(?:있어|있나|있나요|뭐야)\??|추천\s*작업(?:은|는)?(?:\s*뭐야)?\??|진행해줘)\s*$/i
|
|
14942
|
+
];
|
|
14943
|
+
var SHORT_REPAIR_FOLLOW_UP_PATTERNS = [
|
|
14944
|
+
/^\s*(?:fix\s+(?:it|that)|repair\s+(?:it|that)|resolve\s+(?:it|that)|that\s+bug|same\s+issue)\s*$/i,
|
|
14945
|
+
/^\s*(?:그거|그것|이거|이것)?\s*(?:고쳐줘|수정해줘|해결해줘|처리해줘)\s*$/i
|
|
14946
|
+
];
|
|
14947
|
+
var CURRENT_STATE_QUERY_PATTERNS = [
|
|
14948
|
+
/\bcurrent\b.*\b(?:state|status|deployment|blocker|pr|pull request)\b/i,
|
|
14949
|
+
/\b(?:still|as current|current)\b.*\b(?:unresolved|open|pending|not completed)\b/i,
|
|
14950
|
+
/\b(?:old|obsolete|stale|resolved|already resolved)\b.*\b(?:current|still|unresolved|open|state|status)\b/i,
|
|
14951
|
+
/(?:현재|아직|이전|오래된|해결된).*(?:상태|미해결|열린|블로커|PR|풀리퀘스트)/i
|
|
14873
14952
|
];
|
|
14953
|
+
var STALE_CONTENT_PATTERNS = [
|
|
14954
|
+
/\b(?:obsolete|superseded|outdated)\b/i,
|
|
14955
|
+
/\bstale\s+(?:operational\s+)?state\b/i,
|
|
14956
|
+
/\bstale\s+after\b/i,
|
|
14957
|
+
/\bno\s+longer\s+(?:valid|current|applies?)\b/i,
|
|
14958
|
+
/\bearlier\s+(?:pull request|pr)\b[\s\S]{0,160}\b(?:open|not completed|had not completed)\b/i,
|
|
14959
|
+
/\bshould\s+not\s+be\s+injected\s+as\s+current\s+context\b/i,
|
|
14960
|
+
/(?:오래된|더 이상 유효하지|현재 상태가 아님)/i
|
|
14961
|
+
];
|
|
14962
|
+
var CONTINUATION_EXPANSION = "current next step plan roadmap status validation replay rerank memory usefulness continuation";
|
|
14963
|
+
var REPAIR_FOLLOW_UP_EXPANSION = "review blocker fix pattern dashboard error state metrics bucket validation sanitize rerun unresolved";
|
|
14964
|
+
var RETRIEVAL_PRIVACY_DECISION_EXPANSION = "retrieval telemetry privacy public api dashboard dashboards rawQueryText queryText raw query text expose safe trace metadata trace id reason strategy rewrite kind aggregate count counts candidate selected public panel";
|
|
14965
|
+
var DECISION_RECALL_TERMS = /* @__PURE__ */ new Set([
|
|
14966
|
+
"decide",
|
|
14967
|
+
"decided",
|
|
14968
|
+
"decision",
|
|
14969
|
+
"agreed",
|
|
14970
|
+
"policy",
|
|
14971
|
+
"constraint"
|
|
14972
|
+
]);
|
|
14973
|
+
var RETRIEVAL_PRIVACY_SURFACE_TERMS = /* @__PURE__ */ new Set([
|
|
14974
|
+
"retrieval",
|
|
14975
|
+
"dashboard",
|
|
14976
|
+
"telemetry",
|
|
14977
|
+
"trace"
|
|
14978
|
+
]);
|
|
14979
|
+
var DECISION_TOPIC_WEAK_TERMS = /* @__PURE__ */ new Set([
|
|
14980
|
+
"api",
|
|
14981
|
+
"dashboard",
|
|
14982
|
+
"retrieval",
|
|
14983
|
+
"trace",
|
|
14984
|
+
"telemetry",
|
|
14985
|
+
"query",
|
|
14986
|
+
"raw",
|
|
14987
|
+
"count",
|
|
14988
|
+
"counts"
|
|
14989
|
+
]);
|
|
14874
14990
|
var GENERIC_TECHNICAL_TERMS = /* @__PURE__ */ new Set([
|
|
14875
14991
|
"api",
|
|
14876
14992
|
"cli",
|
|
@@ -14888,6 +15004,87 @@ var GENERIC_TECHNICAL_TERMS = /* @__PURE__ */ new Set([
|
|
|
14888
15004
|
"db",
|
|
14889
15005
|
"sql"
|
|
14890
15006
|
]);
|
|
15007
|
+
var LOW_INFORMATION_QUERY_TERMS = /* @__PURE__ */ new Set([
|
|
15008
|
+
"the",
|
|
15009
|
+
"and",
|
|
15010
|
+
"or",
|
|
15011
|
+
"for",
|
|
15012
|
+
"from",
|
|
15013
|
+
"with",
|
|
15014
|
+
"without",
|
|
15015
|
+
"about",
|
|
15016
|
+
"what",
|
|
15017
|
+
"when",
|
|
15018
|
+
"where",
|
|
15019
|
+
"which",
|
|
15020
|
+
"who",
|
|
15021
|
+
"why",
|
|
15022
|
+
"how",
|
|
15023
|
+
"did",
|
|
15024
|
+
"does",
|
|
15025
|
+
"do",
|
|
15026
|
+
"we",
|
|
15027
|
+
"i",
|
|
15028
|
+
"in",
|
|
15029
|
+
"to",
|
|
15030
|
+
"of",
|
|
15031
|
+
"on",
|
|
15032
|
+
"as",
|
|
15033
|
+
"be",
|
|
15034
|
+
"was",
|
|
15035
|
+
"were",
|
|
15036
|
+
"decide",
|
|
15037
|
+
"decided",
|
|
15038
|
+
"decision",
|
|
15039
|
+
"agreed",
|
|
15040
|
+
"policy",
|
|
15041
|
+
"constraint",
|
|
15042
|
+
"showing",
|
|
15043
|
+
"can",
|
|
15044
|
+
"you",
|
|
15045
|
+
"me",
|
|
15046
|
+
"show",
|
|
15047
|
+
"tell",
|
|
15048
|
+
"please",
|
|
15049
|
+
"should",
|
|
15050
|
+
"would",
|
|
15051
|
+
"could",
|
|
15052
|
+
"this",
|
|
15053
|
+
"that",
|
|
15054
|
+
"these",
|
|
15055
|
+
"those",
|
|
15056
|
+
"use",
|
|
15057
|
+
"using",
|
|
15058
|
+
"treat",
|
|
15059
|
+
"continue",
|
|
15060
|
+
"resume",
|
|
15061
|
+
"next",
|
|
15062
|
+
"step",
|
|
15063
|
+
"task",
|
|
15064
|
+
"action",
|
|
15065
|
+
"current",
|
|
15066
|
+
"state",
|
|
15067
|
+
"status",
|
|
15068
|
+
"old",
|
|
15069
|
+
"already",
|
|
15070
|
+
"still",
|
|
15071
|
+
"near",
|
|
15072
|
+
"today",
|
|
15073
|
+
"\uC751",
|
|
15074
|
+
"\uADF8\uAC70",
|
|
15075
|
+
"\uADF8\uAC83",
|
|
15076
|
+
"\uC774\uAC70",
|
|
15077
|
+
"\uC774\uAC83",
|
|
15078
|
+
"\uB2E4\uC74C",
|
|
15079
|
+
"\uB2E8\uACC4",
|
|
15080
|
+
"\uC9C4\uD589",
|
|
15081
|
+
"\uC9C4\uD589\uD574\uC918",
|
|
15082
|
+
"\uACC4\uC18D",
|
|
15083
|
+
"\uC774\uC5B4\uC11C",
|
|
15084
|
+
"\uACE0\uCCD0\uC918",
|
|
15085
|
+
"\uC218\uC815\uD574\uC918",
|
|
15086
|
+
"\uD574\uACB0\uD574\uC918"
|
|
15087
|
+
]);
|
|
14891
15088
|
function isCommandArtifactQuery(query) {
|
|
14892
15089
|
const trimmed = query.trim();
|
|
14893
15090
|
if (!trimmed)
|
|
@@ -14933,6 +15130,60 @@ function isGenericContinuationQuery(query) {
|
|
|
14933
15130
|
return false;
|
|
14934
15131
|
return !/[A-Za-z0-9_-]+\.[A-Za-z0-9]+/.test(trimmed) && !/(?:^|\s)(?:feat|fix|chore|refactor|docs)\/[A-Za-z0-9._-]+/.test(trimmed) && !/[A-Za-z]:?[\\/]|\/Users\/|\.\/|\.\.\//.test(trimmed);
|
|
14935
15132
|
}
|
|
15133
|
+
function isShortRepairFollowUpQuery(query) {
|
|
15134
|
+
const trimmed = query.trim();
|
|
15135
|
+
if (!trimmed)
|
|
15136
|
+
return false;
|
|
15137
|
+
if (extractTechnicalQueryTerms(trimmed).length > 0)
|
|
15138
|
+
return false;
|
|
15139
|
+
const tokens = trimmed.match(/[A-Za-z0-9가-힣#._/-]+/g) ?? [];
|
|
15140
|
+
if (tokens.length > 8)
|
|
15141
|
+
return false;
|
|
15142
|
+
return SHORT_REPAIR_FOLLOW_UP_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
15143
|
+
}
|
|
15144
|
+
function isCurrentStateQuery(query) {
|
|
15145
|
+
const trimmed = query.trim();
|
|
15146
|
+
if (!trimmed)
|
|
15147
|
+
return false;
|
|
15148
|
+
return CURRENT_STATE_QUERY_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
15149
|
+
}
|
|
15150
|
+
function isStaleOrSupersededContent(content) {
|
|
15151
|
+
const trimmed = content.trim();
|
|
15152
|
+
if (!trimmed)
|
|
15153
|
+
return false;
|
|
15154
|
+
return STALE_CONTENT_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
15155
|
+
}
|
|
15156
|
+
function buildRetrievalQualityQuery(query) {
|
|
15157
|
+
const trimmed = query.trim();
|
|
15158
|
+
if (!trimmed)
|
|
15159
|
+
return query;
|
|
15160
|
+
if (isRetrievalPrivacyDecisionQuery(trimmed)) {
|
|
15161
|
+
return `${trimmed} ${RETRIEVAL_PRIVACY_DECISION_EXPANSION}`;
|
|
15162
|
+
}
|
|
15163
|
+
if (isGenericContinuationQuery(trimmed)) {
|
|
15164
|
+
return `${trimmed} ${CONTINUATION_EXPANSION}`;
|
|
15165
|
+
}
|
|
15166
|
+
if (isShortRepairFollowUpQuery(trimmed)) {
|
|
15167
|
+
return `${trimmed} ${REPAIR_FOLLOW_UP_EXPANSION}`;
|
|
15168
|
+
}
|
|
15169
|
+
return query;
|
|
15170
|
+
}
|
|
15171
|
+
function isRetrievalPrivacyDecisionQuery(query) {
|
|
15172
|
+
const trimmed = query.trim();
|
|
15173
|
+
if (!trimmed)
|
|
15174
|
+
return false;
|
|
15175
|
+
const terms = new Set(tokenizeQualityText(trimmed));
|
|
15176
|
+
const hasDecisionSignal = hasAnyTerm(terms, DECISION_RECALL_TERMS) || /(?:결정|정책|원칙)/i.test(trimmed);
|
|
15177
|
+
if (!hasDecisionSignal)
|
|
15178
|
+
return false;
|
|
15179
|
+
const hasRawQuerySignal = terms.has("raw") && terms.has("query");
|
|
15180
|
+
const hasPrivacySignal = terms.has("privacy") || terms.has("expose") || terms.has("redacted");
|
|
15181
|
+
const hasRetrievalSurface = hasAnyTerm(terms, RETRIEVAL_PRIVACY_SURFACE_TERMS) || terms.has("api") && terms.has("query");
|
|
15182
|
+
const hasQuerySurface = terms.has("query") && (terms.has("dashboard") || terms.has("trace") || terms.has("telemetry") || terms.has("api"));
|
|
15183
|
+
const hasKoreanRetrievalSurface = /(?:검색|리트리벌|retrieval|대시보드|트레이스|텔레메트리|telemetry)/i.test(trimmed);
|
|
15184
|
+
const hasKoreanPrivacySurface = /(?:원문|쿼리|프라이버시|개인정보|노출|트레이스|메타데이터)/i.test(trimmed);
|
|
15185
|
+
return (hasRetrievalSurface || hasKoreanRetrievalSurface && hasKoreanPrivacySurface) && (hasRawQuerySignal || hasPrivacySignal || hasQuerySurface || hasKoreanPrivacySurface);
|
|
15186
|
+
}
|
|
14936
15187
|
function extractTechnicalQueryTerms(query) {
|
|
14937
15188
|
const matches = query.match(/[A-Za-z][A-Za-z0-9_.:-]{2,}/g) ?? [];
|
|
14938
15189
|
const terms = matches.filter((term) => {
|
|
@@ -14950,9 +15201,87 @@ function hasTechnicalTermOverlap(query, content) {
|
|
|
14950
15201
|
const normalizedContent = content.toLowerCase();
|
|
14951
15202
|
return terms.some((term) => normalizedContent.includes(term));
|
|
14952
15203
|
}
|
|
15204
|
+
function hasDiscriminativeTermOverlap(query, content) {
|
|
15205
|
+
const queryTerms = extractDiscriminativeQueryTerms(query);
|
|
15206
|
+
const contentTerms = new Set(tokenizeQualityText(content));
|
|
15207
|
+
if (isRetrievalPrivacyDecisionQuery(query) && hasRetrievalPrivacyDecisionContent(contentTerms)) {
|
|
15208
|
+
return true;
|
|
15209
|
+
}
|
|
15210
|
+
if (shouldRequireDecisionTopicOverlap(query)) {
|
|
15211
|
+
const topicTerms = queryTerms.filter((term) => !DECISION_TOPIC_WEAK_TERMS.has(term));
|
|
15212
|
+
if (topicTerms.length > 0) {
|
|
15213
|
+
return topicTerms.some((term) => contentTerms.has(term));
|
|
15214
|
+
}
|
|
15215
|
+
}
|
|
15216
|
+
if (queryTerms.length < 3)
|
|
15217
|
+
return true;
|
|
15218
|
+
const requiredHits = queryTerms.length >= 3 ? 2 : 1;
|
|
15219
|
+
let hits = 0;
|
|
15220
|
+
for (const term of queryTerms) {
|
|
15221
|
+
if (contentTerms.has(term))
|
|
15222
|
+
hits += 1;
|
|
15223
|
+
if (hits >= requiredHits)
|
|
15224
|
+
return true;
|
|
15225
|
+
}
|
|
15226
|
+
return false;
|
|
15227
|
+
}
|
|
14953
15228
|
function shouldApplyTechnicalGuard(query) {
|
|
14954
15229
|
return extractTechnicalQueryTerms(query).length > 0;
|
|
14955
15230
|
}
|
|
15231
|
+
function hasAnyTerm(terms, expectedTerms) {
|
|
15232
|
+
let found = false;
|
|
15233
|
+
expectedTerms.forEach((term) => {
|
|
15234
|
+
if (terms.has(term))
|
|
15235
|
+
found = true;
|
|
15236
|
+
});
|
|
15237
|
+
return found;
|
|
15238
|
+
}
|
|
15239
|
+
function shouldRequireDecisionTopicOverlap(query) {
|
|
15240
|
+
if (isRetrievalPrivacyDecisionQuery(query))
|
|
15241
|
+
return false;
|
|
15242
|
+
const trimmed = query.trim();
|
|
15243
|
+
if (!trimmed)
|
|
15244
|
+
return false;
|
|
15245
|
+
const terms = new Set(tokenizeQualityText(trimmed));
|
|
15246
|
+
return hasAnyTerm(terms, DECISION_RECALL_TERMS) || /(?:결정|정책|원칙)/i.test(trimmed);
|
|
15247
|
+
}
|
|
15248
|
+
function extractDiscriminativeQueryTerms(query) {
|
|
15249
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15250
|
+
const terms = [];
|
|
15251
|
+
for (const token of tokenizeQualityText(query)) {
|
|
15252
|
+
if (LOW_INFORMATION_QUERY_TERMS.has(token))
|
|
15253
|
+
continue;
|
|
15254
|
+
if (GENERIC_TECHNICAL_TERMS.has(token))
|
|
15255
|
+
continue;
|
|
15256
|
+
if (seen.has(token))
|
|
15257
|
+
continue;
|
|
15258
|
+
seen.add(token);
|
|
15259
|
+
terms.push(token);
|
|
15260
|
+
}
|
|
15261
|
+
return terms;
|
|
15262
|
+
}
|
|
15263
|
+
function hasRetrievalPrivacyDecisionContent(contentTerms) {
|
|
15264
|
+
const hasDashboardTraceMetadata = contentTerms.has("dashboard") && (contentTerms.has("trace") || contentTerms.has("metadata")) && (contentTerms.has("safe") || contentTerms.has("strategy") || contentTerms.has("rewrite") || contentTerms.has("candidate") || contentTerms.has("selected") || contentTerms.has("count") || contentTerms.has("reason"));
|
|
15265
|
+
const hasRawQueryPrivacyPolicy = contentTerms.has("retrieval") && (contentTerms.has("privacy") || contentTerms.has("expose") || contentTerms.has("raw") && contentTerms.has("query") && (contentTerms.has("dashboard") || contentTerms.has("telemetry") || contentTerms.has("api") || contentTerms.has("public")));
|
|
15266
|
+
return hasDashboardTraceMetadata || hasRawQueryPrivacyPolicy;
|
|
15267
|
+
}
|
|
15268
|
+
function tokenizeQualityText(text) {
|
|
15269
|
+
return text.replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase().replace(/[^A-Za-z0-9가-힣\s_.:-]/g, " ").split(/\s+/).flatMap((token) => token.split(/(?=[._:-])|(?<=[._:-])/g)).map((token) => normalizeQualityToken(token.replace(/^[._:-]+|[._:-]+$/g, ""))).filter((token) => token.length >= 2);
|
|
15270
|
+
}
|
|
15271
|
+
function normalizeQualityToken(token) {
|
|
15272
|
+
if (token === "apis")
|
|
15273
|
+
return "api";
|
|
15274
|
+
if (token === "ids")
|
|
15275
|
+
return "id";
|
|
15276
|
+
if (LOW_INFORMATION_QUERY_TERMS.has(token) || GENERIC_TECHNICAL_TERMS.has(token))
|
|
15277
|
+
return token;
|
|
15278
|
+
if (token.length > 4 && token.endsWith("ies"))
|
|
15279
|
+
return `${token.slice(0, -3)}y`;
|
|
15280
|
+
if (token.length > 3 && token.endsWith("s") && !token.endsWith("ss") && !token.endsWith("us") && !token.endsWith("is")) {
|
|
15281
|
+
return token.slice(0, -1);
|
|
15282
|
+
}
|
|
15283
|
+
return token;
|
|
15284
|
+
}
|
|
14956
15285
|
|
|
14957
15286
|
// src/core/retriever.ts
|
|
14958
15287
|
var DEFAULT_OPTIONS = {
|
|
@@ -15005,6 +15334,7 @@ var Retriever = class {
|
|
|
15005
15334
|
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
15006
15335
|
const sessionFilter = opts.scope?.sessionId ?? opts.sessionId;
|
|
15007
15336
|
const fallbackTrace = [];
|
|
15337
|
+
const qualityQuery = buildRetrievalQualityQuery(query);
|
|
15008
15338
|
if (isCommandArtifactQuery(query)) {
|
|
15009
15339
|
fallbackTrace.push("guard:command-artifact-query");
|
|
15010
15340
|
const emptyMatch = this.matcher.matchSearchResults([], () => 0);
|
|
@@ -15021,6 +15351,7 @@ var Retriever = class {
|
|
|
15021
15351
|
const fallbackEnabled = (opts.strategy ?? "auto") === "auto";
|
|
15022
15352
|
const primaryStrategy = opts.strategy === "auto" ? "fast" : opts.strategy || "fast";
|
|
15023
15353
|
let current = await this.runStage(query, {
|
|
15354
|
+
qualityQuery,
|
|
15024
15355
|
strategy: primaryStrategy,
|
|
15025
15356
|
topK: opts.topK,
|
|
15026
15357
|
minScore: opts.minScore,
|
|
@@ -15038,6 +15369,7 @@ var Retriever = class {
|
|
|
15038
15369
|
fallbackTrace.push(`stage:primary:${primaryStrategy}`);
|
|
15039
15370
|
if (fallbackEnabled && this.shouldFallback(current.matchResult, current.results) && primaryStrategy !== "deep") {
|
|
15040
15371
|
current = await this.runStage(query, {
|
|
15372
|
+
qualityQuery,
|
|
15041
15373
|
strategy: "deep",
|
|
15042
15374
|
topK: opts.topK,
|
|
15043
15375
|
minScore: opts.minScore,
|
|
@@ -15055,6 +15387,7 @@ var Retriever = class {
|
|
|
15055
15387
|
}
|
|
15056
15388
|
if (fallbackEnabled && this.shouldFallback(current.matchResult, current.results)) {
|
|
15057
15389
|
current = await this.runStage(query, {
|
|
15390
|
+
qualityQuery,
|
|
15058
15391
|
strategy: "deep",
|
|
15059
15392
|
topK: opts.topK,
|
|
15060
15393
|
minScore: Math.max(0.5, opts.minScore - 0.15),
|
|
@@ -15071,11 +15404,21 @@ var Retriever = class {
|
|
|
15071
15404
|
fallbackTrace.push("fallback:scope-expanded");
|
|
15072
15405
|
}
|
|
15073
15406
|
if (fallbackEnabled && this.shouldFallback(current.matchResult, current.results)) {
|
|
15074
|
-
const summary = await this.buildSummaryFallback(
|
|
15407
|
+
const summary = await this.buildSummaryFallback(qualityQuery, opts.topK);
|
|
15408
|
+
const scopedSummary = await this.applyScopeFilters(summary, {
|
|
15409
|
+
scope: opts.scope,
|
|
15410
|
+
projectScopeMode: opts.projectScopeMode,
|
|
15411
|
+
projectHash: opts.projectHash,
|
|
15412
|
+
allowedProjectHashes: opts.allowedProjectHashes
|
|
15413
|
+
});
|
|
15414
|
+
const filteredSummary = this.applyQualityFilters(scopedSummary, {
|
|
15415
|
+
query,
|
|
15416
|
+
minScore: opts.minScore
|
|
15417
|
+
});
|
|
15075
15418
|
current = {
|
|
15076
|
-
results:
|
|
15077
|
-
candidateResults:
|
|
15078
|
-
matchResult: this.matcher.matchSearchResults(
|
|
15419
|
+
results: filteredSummary,
|
|
15420
|
+
candidateResults: filteredSummary,
|
|
15421
|
+
matchResult: this.matcher.matchSearchResults(filteredSummary, () => 0)
|
|
15079
15422
|
};
|
|
15080
15423
|
fallbackTrace.push("fallback:summary");
|
|
15081
15424
|
}
|
|
@@ -15100,7 +15443,10 @@ var Retriever = class {
|
|
|
15100
15443
|
semanticScore: r.semanticScore,
|
|
15101
15444
|
lexicalScore: r.lexicalScore,
|
|
15102
15445
|
recencyScore: r.recencyScore
|
|
15103
|
-
}))
|
|
15446
|
+
})),
|
|
15447
|
+
rawQueryText: current.queryRewriteKind ? query : void 0,
|
|
15448
|
+
effectiveQueryText: current.effectiveQueryText,
|
|
15449
|
+
queryRewriteKind: current.queryRewriteKind
|
|
15104
15450
|
};
|
|
15105
15451
|
}
|
|
15106
15452
|
async retrieveUnified(query, options = {}) {
|
|
@@ -15138,8 +15484,11 @@ var Retriever = class {
|
|
|
15138
15484
|
}
|
|
15139
15485
|
}
|
|
15140
15486
|
async runStage(query, input) {
|
|
15141
|
-
|
|
15142
|
-
let
|
|
15487
|
+
const searchQuery = input.qualityQuery ?? query;
|
|
15488
|
+
let rerankQuery = searchQuery;
|
|
15489
|
+
let effectiveQueryText;
|
|
15490
|
+
let queryRewriteKind;
|
|
15491
|
+
let initialResults = await this.searchByStrategy(searchQuery, {
|
|
15143
15492
|
strategy: input.strategy,
|
|
15144
15493
|
topK: input.topK,
|
|
15145
15494
|
minScore: input.minScore,
|
|
@@ -15147,9 +15496,12 @@ var Retriever = class {
|
|
|
15147
15496
|
});
|
|
15148
15497
|
if (input.intentRewrite && input.strategy === "deep" && this.queryRewriter) {
|
|
15149
15498
|
const rewritten = (await this.queryRewriter(query))?.trim();
|
|
15150
|
-
|
|
15151
|
-
|
|
15152
|
-
|
|
15499
|
+
const normalizedQuery = query.trim();
|
|
15500
|
+
if (rewritten && rewritten !== normalizedQuery) {
|
|
15501
|
+
effectiveQueryText = `${normalizedQuery} ${rewritten}`.trim();
|
|
15502
|
+
queryRewriteKind = "intent-rewrite";
|
|
15503
|
+
rerankQuery = buildRetrievalQualityQuery(effectiveQueryText);
|
|
15504
|
+
const rewrittenResults = await this.searchByStrategy(buildRetrievalQualityQuery(rewritten), {
|
|
15153
15505
|
strategy: "deep",
|
|
15154
15506
|
topK: input.topK,
|
|
15155
15507
|
minScore: Math.max(0.5, input.minScore - 0.1),
|
|
@@ -15176,10 +15528,14 @@ var Retriever = class {
|
|
|
15176
15528
|
});
|
|
15177
15529
|
const top = qualityFiltered.slice(0, input.topK);
|
|
15178
15530
|
const matchResult = this.matcher.matchSearchResults(top, () => 0);
|
|
15179
|
-
return { results: top, candidateResults: qualityFiltered, matchResult };
|
|
15531
|
+
return { results: top, candidateResults: qualityFiltered, matchResult, effectiveQueryText, queryRewriteKind };
|
|
15180
15532
|
}
|
|
15181
15533
|
applyQualityFilters(results, options) {
|
|
15182
15534
|
let filtered = [...results];
|
|
15535
|
+
if (isCurrentStateQuery(options.query)) {
|
|
15536
|
+
filtered = filtered.filter((result) => !isStaleOrSupersededContent(result.content));
|
|
15537
|
+
}
|
|
15538
|
+
filtered = filtered.filter((result) => hasDiscriminativeTermOverlap(options.query, result.content));
|
|
15183
15539
|
if (shouldApplyTechnicalGuard(options.query)) {
|
|
15184
15540
|
filtered = filtered.filter((result) => hasTechnicalTermOverlap(options.query, result.content));
|
|
15185
15541
|
}
|
|
@@ -15487,7 +15843,21 @@ _Context:_ ${sessionContext}`;
|
|
|
15487
15843
|
});
|
|
15488
15844
|
}
|
|
15489
15845
|
tokenize(text) {
|
|
15490
|
-
return text.toLowerCase().replace(/[^\p{L}\p{N}\s]/gu, " ").split(/\s+/).filter((t) => t.length >= 2).slice(0, 64);
|
|
15846
|
+
return text.replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase().replace(/[^\p{L}\p{N}\s]/gu, " ").split(/\s+/).map((token) => this.normalizeToken(token)).filter((t) => t.length >= 2).slice(0, 64);
|
|
15847
|
+
}
|
|
15848
|
+
normalizeToken(token) {
|
|
15849
|
+
if (token === "apis")
|
|
15850
|
+
return "api";
|
|
15851
|
+
if (token === "ids")
|
|
15852
|
+
return "id";
|
|
15853
|
+
if (token === "does")
|
|
15854
|
+
return token;
|
|
15855
|
+
if (token.length > 4 && token.endsWith("ies"))
|
|
15856
|
+
return `${token.slice(0, -3)}y`;
|
|
15857
|
+
if (token.length > 3 && token.endsWith("s") && !token.endsWith("ss") && !token.endsWith("us") && !token.endsWith("is") && !token.endsWith("ps")) {
|
|
15858
|
+
return token.slice(0, -1);
|
|
15859
|
+
}
|
|
15860
|
+
return token;
|
|
15491
15861
|
}
|
|
15492
15862
|
keywordOverlap(a, b) {
|
|
15493
15863
|
if (a.length === 0 || b.length === 0)
|
|
@@ -15550,9 +15920,9 @@ var RetrievalAnalyticsService = class {
|
|
|
15550
15920
|
await this.deps.initialize();
|
|
15551
15921
|
return this.deps.retrievalStore.getHelpfulMemories(limit);
|
|
15552
15922
|
}
|
|
15553
|
-
async getHelpfulnessStats() {
|
|
15923
|
+
async getHelpfulnessStats(since) {
|
|
15554
15924
|
await this.deps.initialize();
|
|
15555
|
-
return this.deps.retrievalStore.getHelpfulnessStats();
|
|
15925
|
+
return this.deps.retrievalStore.getHelpfulnessStats(since);
|
|
15556
15926
|
}
|
|
15557
15927
|
/**
|
|
15558
15928
|
* Extract topic keywords from event content (markdown headings and key terms).
|
|
@@ -15977,7 +16347,9 @@ var RetrievalOrchestrator = class {
|
|
|
15977
16347
|
await this.deps.traceStore.recordRetrievalTrace({
|
|
15978
16348
|
sessionId: options?.sessionId,
|
|
15979
16349
|
projectHash: projectHash || void 0,
|
|
15980
|
-
queryText: query,
|
|
16350
|
+
queryText: result.effectiveQueryText || query,
|
|
16351
|
+
rawQueryText: result.rawQueryText || (result.queryRewriteKind ? query : void 0),
|
|
16352
|
+
queryRewriteKind: result.queryRewriteKind || "none",
|
|
15981
16353
|
strategy: options?.strategy || "auto",
|
|
15982
16354
|
candidateEventIds,
|
|
15983
16355
|
selectedEventIds,
|
|
@@ -17992,8 +18364,8 @@ var MemoryService = class {
|
|
|
17992
18364
|
/**
|
|
17993
18365
|
* Get helpfulness statistics for dashboard
|
|
17994
18366
|
*/
|
|
17995
|
-
async getHelpfulnessStats() {
|
|
17996
|
-
return this.retrievalAnalyticsService.getHelpfulnessStats();
|
|
18367
|
+
async getHelpfulnessStats(since) {
|
|
18368
|
+
return this.retrievalAnalyticsService.getHelpfulnessStats(since);
|
|
17997
18369
|
}
|
|
17998
18370
|
/**
|
|
17999
18371
|
* Mark a consolidated memory as accessed
|
|
@@ -20214,8 +20586,10 @@ async function handleMemContextPack(memoryService, args) {
|
|
|
20214
20586
|
const sessionId = optionalString(args.sessionId);
|
|
20215
20587
|
const projectPath = optionalString(args.projectPath);
|
|
20216
20588
|
const genericContinuationQuery = isGenericContinuationQuery(query);
|
|
20589
|
+
const explicitFreshnessRefresh = args.refreshLatest === true;
|
|
20590
|
+
const autoFreshnessRefresh = args.refreshLatest !== false && !explicitFreshnessRefresh && genericContinuationQuery && sessionId === void 0 && projectPath !== void 0 && path14.isAbsolute(projectPath);
|
|
20217
20591
|
const retrievalTopK = Math.min(topK * 3, 12);
|
|
20218
|
-
const freshnessRun =
|
|
20592
|
+
const freshnessRun = explicitFreshnessRefresh || autoFreshnessRefresh ? await runLatestImport(memoryService, {
|
|
20219
20593
|
projectPath: projectPath || "",
|
|
20220
20594
|
sources: sourceListArg(args.refreshSources),
|
|
20221
20595
|
sessionLimit: numberArg(args.refreshSessionLimit, 1, 1, 10),
|
|
@@ -20251,8 +20625,9 @@ async function handleMemContextPack(memoryService, args) {
|
|
|
20251
20625
|
`- Recent sessions shown: ${Math.min(sessionLimit, sessions.length)}`
|
|
20252
20626
|
];
|
|
20253
20627
|
if (freshnessRun) {
|
|
20628
|
+
const refreshMode = autoFreshnessRefresh ? "auto" : "attempted";
|
|
20254
20629
|
lines.push(
|
|
20255
|
-
`- Freshness refresh:
|
|
20630
|
+
`- Freshness refresh: ${refreshMode} before retrieval (${freshnessRun.sources.join(", ")})`,
|
|
20256
20631
|
`- Refresh limits: sessions=${freshnessRun.sessionLimit} messages=${freshnessRun.messageLimit} force=${freshnessRun.force ? "yes" : "no"} embeddings=${freshnessRun.processEmbeddings ? `processed ${freshnessRun.embeddingsProcessed ?? 0}` : "skipped"}`
|
|
20257
20632
|
);
|
|
20258
20633
|
}
|