memorix 0.11.0 → 0.11.1
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 +223 -10
- package/dist/cli/index.js.map +1 -1
- package/dist/dashboard/static/app.js +355 -185
- package/dist/dashboard/static/style.css +1707 -1524
- package/dist/index.js +223 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -10611,6 +10611,205 @@ var init_project_affinity = __esm({
|
|
|
10611
10611
|
}
|
|
10612
10612
|
});
|
|
10613
10613
|
|
|
10614
|
+
// src/search/intent-detector.ts
|
|
10615
|
+
function detectQueryIntent(query) {
|
|
10616
|
+
if (!query || query.length < 2) {
|
|
10617
|
+
return {
|
|
10618
|
+
intent: "general",
|
|
10619
|
+
confidence: 0,
|
|
10620
|
+
typeBoosts: {},
|
|
10621
|
+
preferChronological: false
|
|
10622
|
+
};
|
|
10623
|
+
}
|
|
10624
|
+
let bestIntent = "general";
|
|
10625
|
+
let bestScore = 0;
|
|
10626
|
+
let totalMatches = 0;
|
|
10627
|
+
for (const { intent, patterns, weight } of INTENT_PATTERNS) {
|
|
10628
|
+
let matchCount = 0;
|
|
10629
|
+
for (const pattern of patterns) {
|
|
10630
|
+
if (pattern.test(query)) matchCount++;
|
|
10631
|
+
}
|
|
10632
|
+
if (matchCount > 0) {
|
|
10633
|
+
const score = matchCount * weight;
|
|
10634
|
+
totalMatches += matchCount;
|
|
10635
|
+
if (score > bestScore) {
|
|
10636
|
+
bestScore = score;
|
|
10637
|
+
bestIntent = intent;
|
|
10638
|
+
}
|
|
10639
|
+
}
|
|
10640
|
+
}
|
|
10641
|
+
const confidence = totalMatches === 0 ? 0 : Math.min(1, bestScore / 2);
|
|
10642
|
+
return {
|
|
10643
|
+
intent: bestIntent,
|
|
10644
|
+
confidence,
|
|
10645
|
+
typeBoosts: INTENT_TYPE_BOOSTS[bestIntent],
|
|
10646
|
+
fieldBoosts: INTENT_FIELD_BOOSTS[bestIntent],
|
|
10647
|
+
preferChronological: bestIntent === "when"
|
|
10648
|
+
};
|
|
10649
|
+
}
|
|
10650
|
+
function applyIntentBoost(score, type, intentResult) {
|
|
10651
|
+
if (intentResult.confidence < 0.3) return score;
|
|
10652
|
+
const boost = intentResult.typeBoosts[type] ?? 1;
|
|
10653
|
+
const effectiveBoost = 1 + (boost - 1) * intentResult.confidence;
|
|
10654
|
+
return score * effectiveBoost;
|
|
10655
|
+
}
|
|
10656
|
+
var INTENT_PATTERNS, INTENT_TYPE_BOOSTS, INTENT_FIELD_BOOSTS;
|
|
10657
|
+
var init_intent_detector = __esm({
|
|
10658
|
+
"src/search/intent-detector.ts"() {
|
|
10659
|
+
"use strict";
|
|
10660
|
+
init_esm_shims();
|
|
10661
|
+
INTENT_PATTERNS = [
|
|
10662
|
+
{
|
|
10663
|
+
intent: "why",
|
|
10664
|
+
patterns: [
|
|
10665
|
+
/\bwhy\b/i,
|
|
10666
|
+
/\breason(?:s|ing)?\b/i,
|
|
10667
|
+
/\brationale\b/i,
|
|
10668
|
+
/\bmotivat(?:ion|ed)\b/i,
|
|
10669
|
+
/\bjustif(?:y|ication)\b/i,
|
|
10670
|
+
/\bchose|chosen|picked\b/i,
|
|
10671
|
+
/\bdecid(?:e[ds]?|ing)\b/i,
|
|
10672
|
+
/\btrade-?off\b/i,
|
|
10673
|
+
/为什么/,
|
|
10674
|
+
/原因/,
|
|
10675
|
+
/理由/,
|
|
10676
|
+
/为何/
|
|
10677
|
+
],
|
|
10678
|
+
weight: 1
|
|
10679
|
+
},
|
|
10680
|
+
{
|
|
10681
|
+
intent: "when",
|
|
10682
|
+
patterns: [
|
|
10683
|
+
/\bwhen\b/i,
|
|
10684
|
+
/\btimeline\b/i,
|
|
10685
|
+
/\bhistory\b/i,
|
|
10686
|
+
/\blast\s+(week|month|time|session)\b/i,
|
|
10687
|
+
/\brecent(?:ly)?\b/i,
|
|
10688
|
+
/\byesterday\b/i,
|
|
10689
|
+
/\btoday\b/i,
|
|
10690
|
+
/\bchronolog/i,
|
|
10691
|
+
/什么时候/,
|
|
10692
|
+
/何时/,
|
|
10693
|
+
/最近/,
|
|
10694
|
+
/上次/
|
|
10695
|
+
],
|
|
10696
|
+
weight: 0.9
|
|
10697
|
+
},
|
|
10698
|
+
{
|
|
10699
|
+
intent: "how",
|
|
10700
|
+
patterns: [
|
|
10701
|
+
/\bhow\s+(does|do|to|is|can|did|should|would)\b/i,
|
|
10702
|
+
/\barchitecture\b/i,
|
|
10703
|
+
/\bmechanism\b/i,
|
|
10704
|
+
/\bimplement(?:ation|ed|ing)?\b/i,
|
|
10705
|
+
/\bwork(?:s|ing|ed)?\b/i,
|
|
10706
|
+
/\bexplain\b/i,
|
|
10707
|
+
/\bunderstand\b/i,
|
|
10708
|
+
/怎么/,
|
|
10709
|
+
/如何/,
|
|
10710
|
+
/机制/,
|
|
10711
|
+
/原理/,
|
|
10712
|
+
/架构/
|
|
10713
|
+
],
|
|
10714
|
+
weight: 0.85
|
|
10715
|
+
},
|
|
10716
|
+
{
|
|
10717
|
+
intent: "what_changed",
|
|
10718
|
+
patterns: [
|
|
10719
|
+
/\bwhat\s+changed\b/i,
|
|
10720
|
+
/\bwhat\s+was\s+(modified|updated|changed)\b/i,
|
|
10721
|
+
/\bdiff(?:erence)?\b/i,
|
|
10722
|
+
/\bchangelog\b/i,
|
|
10723
|
+
/\bmodifi(?:ed|cation)\b/i,
|
|
10724
|
+
/\bupdat(?:e[ds]?|ing)\b/i,
|
|
10725
|
+
/\brefactor(?:ed|ing)?\b/i,
|
|
10726
|
+
/改了/,
|
|
10727
|
+
/修改/,
|
|
10728
|
+
/变更/,
|
|
10729
|
+
/变化/
|
|
10730
|
+
],
|
|
10731
|
+
weight: 0.8
|
|
10732
|
+
},
|
|
10733
|
+
{
|
|
10734
|
+
intent: "problem",
|
|
10735
|
+
patterns: [
|
|
10736
|
+
/\bbug(?:s|gy)?\b/i,
|
|
10737
|
+
/\berror(?:s)?\b/i,
|
|
10738
|
+
/\bfix(?:e[ds]|ing)?\b/i,
|
|
10739
|
+
/\bissue(?:s)?\b/i,
|
|
10740
|
+
/\bproblem(?:s)?\b/i,
|
|
10741
|
+
/\bcrash(?:e[ds]|ing)?\b/i,
|
|
10742
|
+
/\bfail(?:e[ds]|ure|ing)?\b/i,
|
|
10743
|
+
/\bbroken\b/i,
|
|
10744
|
+
/\bgotcha\b/i,
|
|
10745
|
+
/\bpitfall\b/i,
|
|
10746
|
+
/\bworkaround\b/i,
|
|
10747
|
+
/\btroubleshoot/i,
|
|
10748
|
+
/\bdebug(?:ging)?\b/i,
|
|
10749
|
+
/报错/,
|
|
10750
|
+
/问题/,
|
|
10751
|
+
/修复/,
|
|
10752
|
+
/故障/,
|
|
10753
|
+
/异常/
|
|
10754
|
+
],
|
|
10755
|
+
weight: 0.9
|
|
10756
|
+
}
|
|
10757
|
+
];
|
|
10758
|
+
INTENT_TYPE_BOOSTS = {
|
|
10759
|
+
why: {
|
|
10760
|
+
"decision": 3,
|
|
10761
|
+
"why-it-exists": 3,
|
|
10762
|
+
"trade-off": 2.5,
|
|
10763
|
+
"how-it-works": 1.2
|
|
10764
|
+
},
|
|
10765
|
+
when: {
|
|
10766
|
+
// Temporal queries don't strongly prefer any type — they prefer recency
|
|
10767
|
+
"what-changed": 1.5,
|
|
10768
|
+
"session-request": 1.3
|
|
10769
|
+
},
|
|
10770
|
+
how: {
|
|
10771
|
+
"how-it-works": 3,
|
|
10772
|
+
"discovery": 2,
|
|
10773
|
+
"decision": 1.3
|
|
10774
|
+
},
|
|
10775
|
+
what_changed: {
|
|
10776
|
+
"what-changed": 3,
|
|
10777
|
+
"discovery": 1.5,
|
|
10778
|
+
"session-request": 1.2
|
|
10779
|
+
},
|
|
10780
|
+
problem: {
|
|
10781
|
+
"problem-solution": 3,
|
|
10782
|
+
"gotcha": 2.5,
|
|
10783
|
+
"discovery": 1.3
|
|
10784
|
+
},
|
|
10785
|
+
general: {
|
|
10786
|
+
// No special boosting
|
|
10787
|
+
}
|
|
10788
|
+
};
|
|
10789
|
+
INTENT_FIELD_BOOSTS = {
|
|
10790
|
+
why: {
|
|
10791
|
+
title: 2,
|
|
10792
|
+
entityName: 1.5,
|
|
10793
|
+
narrative: 2.5,
|
|
10794
|
+
// WHY queries need narrative context
|
|
10795
|
+
facts: 1.5,
|
|
10796
|
+
concepts: 1,
|
|
10797
|
+
filesModified: 0.3
|
|
10798
|
+
},
|
|
10799
|
+
problem: {
|
|
10800
|
+
title: 3,
|
|
10801
|
+
entityName: 2,
|
|
10802
|
+
narrative: 2,
|
|
10803
|
+
facts: 2,
|
|
10804
|
+
// Bug details often in facts
|
|
10805
|
+
concepts: 1,
|
|
10806
|
+
filesModified: 1.5
|
|
10807
|
+
// File paths help find the right bug fix
|
|
10808
|
+
}
|
|
10809
|
+
};
|
|
10810
|
+
}
|
|
10811
|
+
});
|
|
10812
|
+
|
|
10614
10813
|
// src/project/aliases.ts
|
|
10615
10814
|
var aliases_exports = {};
|
|
10616
10815
|
__export(aliases_exports, {
|
|
@@ -13913,22 +14112,25 @@ async function searchObservations(options2) {
|
|
|
13913
14112
|
filters["type"] = options2.type;
|
|
13914
14113
|
}
|
|
13915
14114
|
const hasQuery = options2.query && options2.query.trim().length > 0;
|
|
14115
|
+
const intentResult = hasQuery ? detectQueryIntent(options2.query) : null;
|
|
13916
14116
|
const requestLimit = projectIds && projectIds.length > 1 ? (options2.limit ?? 20) * 3 : options2.limit ?? 20;
|
|
14117
|
+
const defaultBoost = {
|
|
14118
|
+
title: 3,
|
|
14119
|
+
entityName: 2,
|
|
14120
|
+
concepts: 1.5,
|
|
14121
|
+
narrative: 1,
|
|
14122
|
+
facts: 1,
|
|
14123
|
+
filesModified: 0.5
|
|
14124
|
+
};
|
|
14125
|
+
const fieldBoost = (intentResult?.confidence ?? 0) > 0.3 && intentResult?.fieldBoosts ? intentResult.fieldBoosts : defaultBoost;
|
|
13917
14126
|
let searchParams = {
|
|
13918
14127
|
term: options2.query,
|
|
13919
14128
|
limit: requestLimit,
|
|
13920
14129
|
...Object.keys(filters).length > 0 ? { where: filters } : {},
|
|
13921
14130
|
// Search specific fields (not tokens, accessCount, etc.)
|
|
13922
14131
|
properties: ["title", "entityName", "narrative", "facts", "concepts", "filesModified"],
|
|
13923
|
-
// Field boosting:
|
|
13924
|
-
boost:
|
|
13925
|
-
title: 3,
|
|
13926
|
-
entityName: 2,
|
|
13927
|
-
concepts: 1.5,
|
|
13928
|
-
narrative: 1,
|
|
13929
|
-
facts: 1,
|
|
13930
|
-
filesModified: 0.5
|
|
13931
|
-
},
|
|
14132
|
+
// Field boosting: intent-aware or default
|
|
14133
|
+
boost: fieldBoost,
|
|
13932
14134
|
// Fuzzy tolerance: allow 1-char typos for short queries, 2 for longer
|
|
13933
14135
|
...hasQuery ? { tolerance: options2.query.length > 6 ? 2 : 1 } : {}
|
|
13934
14136
|
};
|
|
@@ -14002,7 +14204,17 @@ async function searchObservations(options2) {
|
|
|
14002
14204
|
score: (hit.score ?? 1) * recencyBoost
|
|
14003
14205
|
};
|
|
14004
14206
|
});
|
|
14005
|
-
|
|
14207
|
+
if (intentResult && intentResult.confidence > 0.3) {
|
|
14208
|
+
intermediate = intermediate.map((entry) => ({
|
|
14209
|
+
...entry,
|
|
14210
|
+
score: applyIntentBoost(entry.score, entry.type, intentResult)
|
|
14211
|
+
}));
|
|
14212
|
+
}
|
|
14213
|
+
if (intentResult?.preferChronological) {
|
|
14214
|
+
intermediate.sort((a3, b3) => new Date(b3.rawTime).getTime() - new Date(a3.rawTime).getTime());
|
|
14215
|
+
} else {
|
|
14216
|
+
intermediate.sort((a3, b3) => b3.score - a3.score);
|
|
14217
|
+
}
|
|
14006
14218
|
if (options2.projectId && intermediate.length > 0) {
|
|
14007
14219
|
const projectName = options2.projectId.split("/").pop() ?? options2.projectId;
|
|
14008
14220
|
const affinityContext = {
|
|
@@ -14209,6 +14421,7 @@ var init_orama_store = __esm({
|
|
|
14209
14421
|
init_types2();
|
|
14210
14422
|
init_provider();
|
|
14211
14423
|
init_project_affinity();
|
|
14424
|
+
init_intent_detector();
|
|
14212
14425
|
db = null;
|
|
14213
14426
|
embeddingEnabled = false;
|
|
14214
14427
|
}
|