@velvetmonkey/flywheel-crank 0.7.3 → 0.8.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/dist/index.js +450 -20
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -518,6 +518,7 @@ import path4 from "path";
|
|
|
518
518
|
|
|
519
519
|
// src/core/stemmer.ts
|
|
520
520
|
var STOPWORDS = /* @__PURE__ */ new Set([
|
|
521
|
+
// Articles, pronouns, prepositions (basic)
|
|
521
522
|
"the",
|
|
522
523
|
"a",
|
|
523
524
|
"an",
|
|
@@ -618,11 +619,385 @@ var STOPWORDS = /* @__PURE__ */ new Set([
|
|
|
618
619
|
"there",
|
|
619
620
|
"any",
|
|
620
621
|
"now",
|
|
621
|
-
"new",
|
|
622
622
|
"even",
|
|
623
623
|
"much",
|
|
624
624
|
"back",
|
|
625
|
-
|
|
625
|
+
// Common verbs (critical for reducing false positives)
|
|
626
|
+
// These create matches like "Completed" → "Complete Guide"
|
|
627
|
+
"going",
|
|
628
|
+
"went",
|
|
629
|
+
"gone",
|
|
630
|
+
"come",
|
|
631
|
+
"came",
|
|
632
|
+
"coming",
|
|
633
|
+
"work",
|
|
634
|
+
"worked",
|
|
635
|
+
"working",
|
|
636
|
+
"works",
|
|
637
|
+
"make",
|
|
638
|
+
"made",
|
|
639
|
+
"making",
|
|
640
|
+
"makes",
|
|
641
|
+
"take",
|
|
642
|
+
"took",
|
|
643
|
+
"taken",
|
|
644
|
+
"taking",
|
|
645
|
+
"takes",
|
|
646
|
+
"give",
|
|
647
|
+
"gave",
|
|
648
|
+
"given",
|
|
649
|
+
"giving",
|
|
650
|
+
"gives",
|
|
651
|
+
"find",
|
|
652
|
+
"found",
|
|
653
|
+
"finding",
|
|
654
|
+
"finds",
|
|
655
|
+
"know",
|
|
656
|
+
"knew",
|
|
657
|
+
"known",
|
|
658
|
+
"knowing",
|
|
659
|
+
"knows",
|
|
660
|
+
"think",
|
|
661
|
+
"thought",
|
|
662
|
+
"thinking",
|
|
663
|
+
"thinks",
|
|
664
|
+
"look",
|
|
665
|
+
"looked",
|
|
666
|
+
"looking",
|
|
667
|
+
"looks",
|
|
668
|
+
"want",
|
|
669
|
+
"wanted",
|
|
670
|
+
"wanting",
|
|
671
|
+
"wants",
|
|
672
|
+
"tell",
|
|
673
|
+
"told",
|
|
674
|
+
"telling",
|
|
675
|
+
"tells",
|
|
676
|
+
"keep",
|
|
677
|
+
"kept",
|
|
678
|
+
"keeping",
|
|
679
|
+
"keeps",
|
|
680
|
+
"start",
|
|
681
|
+
"started",
|
|
682
|
+
"starting",
|
|
683
|
+
"starts",
|
|
684
|
+
"complete",
|
|
685
|
+
"completed",
|
|
686
|
+
"completing",
|
|
687
|
+
"completes",
|
|
688
|
+
"finish",
|
|
689
|
+
"finished",
|
|
690
|
+
"finishing",
|
|
691
|
+
"finishes",
|
|
692
|
+
"begin",
|
|
693
|
+
"began",
|
|
694
|
+
"begun",
|
|
695
|
+
"beginning",
|
|
696
|
+
"begins",
|
|
697
|
+
"end",
|
|
698
|
+
"ended",
|
|
699
|
+
"ending",
|
|
700
|
+
"ends",
|
|
701
|
+
"add",
|
|
702
|
+
"added",
|
|
703
|
+
"adding",
|
|
704
|
+
"adds",
|
|
705
|
+
"update",
|
|
706
|
+
"updated",
|
|
707
|
+
"updating",
|
|
708
|
+
"updates",
|
|
709
|
+
"change",
|
|
710
|
+
"changed",
|
|
711
|
+
"changing",
|
|
712
|
+
"changes",
|
|
713
|
+
"remove",
|
|
714
|
+
"removed",
|
|
715
|
+
"removing",
|
|
716
|
+
"removes",
|
|
717
|
+
"fix",
|
|
718
|
+
"fixed",
|
|
719
|
+
"fixing",
|
|
720
|
+
"fixes",
|
|
721
|
+
"create",
|
|
722
|
+
"created",
|
|
723
|
+
"creating",
|
|
724
|
+
"creates",
|
|
725
|
+
"build",
|
|
726
|
+
"built",
|
|
727
|
+
"building",
|
|
728
|
+
"builds",
|
|
729
|
+
"run",
|
|
730
|
+
"ran",
|
|
731
|
+
"running",
|
|
732
|
+
"runs",
|
|
733
|
+
"test",
|
|
734
|
+
"tested",
|
|
735
|
+
"testing",
|
|
736
|
+
"tests",
|
|
737
|
+
"release",
|
|
738
|
+
"released",
|
|
739
|
+
"releasing",
|
|
740
|
+
"releases",
|
|
741
|
+
"use",
|
|
742
|
+
"used",
|
|
743
|
+
"using",
|
|
744
|
+
"uses",
|
|
745
|
+
"get",
|
|
746
|
+
"got",
|
|
747
|
+
"gotten",
|
|
748
|
+
"getting",
|
|
749
|
+
"gets",
|
|
750
|
+
"set",
|
|
751
|
+
"setting",
|
|
752
|
+
"sets",
|
|
753
|
+
"put",
|
|
754
|
+
"putting",
|
|
755
|
+
"puts",
|
|
756
|
+
"try",
|
|
757
|
+
"tried",
|
|
758
|
+
"trying",
|
|
759
|
+
"tries",
|
|
760
|
+
"move",
|
|
761
|
+
"moved",
|
|
762
|
+
"moving",
|
|
763
|
+
"moves",
|
|
764
|
+
"show",
|
|
765
|
+
"showed",
|
|
766
|
+
"shown",
|
|
767
|
+
"showing",
|
|
768
|
+
"shows",
|
|
769
|
+
"help",
|
|
770
|
+
"helped",
|
|
771
|
+
"helping",
|
|
772
|
+
"helps",
|
|
773
|
+
"read",
|
|
774
|
+
"reading",
|
|
775
|
+
"reads",
|
|
776
|
+
"write",
|
|
777
|
+
"wrote",
|
|
778
|
+
"written",
|
|
779
|
+
"writing",
|
|
780
|
+
"writes",
|
|
781
|
+
"call",
|
|
782
|
+
"called",
|
|
783
|
+
"calling",
|
|
784
|
+
"calls",
|
|
785
|
+
"feel",
|
|
786
|
+
"felt",
|
|
787
|
+
"feeling",
|
|
788
|
+
"feels",
|
|
789
|
+
"seem",
|
|
790
|
+
"seemed",
|
|
791
|
+
"seeming",
|
|
792
|
+
"seems",
|
|
793
|
+
"turn",
|
|
794
|
+
"turned",
|
|
795
|
+
"turning",
|
|
796
|
+
"turns",
|
|
797
|
+
"leave",
|
|
798
|
+
"left",
|
|
799
|
+
"leaving",
|
|
800
|
+
"leaves",
|
|
801
|
+
"play",
|
|
802
|
+
"played",
|
|
803
|
+
"playing",
|
|
804
|
+
"plays",
|
|
805
|
+
"hold",
|
|
806
|
+
"held",
|
|
807
|
+
"holding",
|
|
808
|
+
"holds",
|
|
809
|
+
"bring",
|
|
810
|
+
"brought",
|
|
811
|
+
"bringing",
|
|
812
|
+
"brings",
|
|
813
|
+
"happen",
|
|
814
|
+
"happened",
|
|
815
|
+
"happening",
|
|
816
|
+
"happens",
|
|
817
|
+
"include",
|
|
818
|
+
"included",
|
|
819
|
+
"including",
|
|
820
|
+
"includes",
|
|
821
|
+
"continue",
|
|
822
|
+
"continued",
|
|
823
|
+
"continuing",
|
|
824
|
+
"continues",
|
|
825
|
+
"send",
|
|
826
|
+
"sent",
|
|
827
|
+
"sending",
|
|
828
|
+
"sends",
|
|
829
|
+
"receive",
|
|
830
|
+
"received",
|
|
831
|
+
"receiving",
|
|
832
|
+
"receives",
|
|
833
|
+
"follow",
|
|
834
|
+
"followed",
|
|
835
|
+
"following",
|
|
836
|
+
"follows",
|
|
837
|
+
"stop",
|
|
838
|
+
"stopped",
|
|
839
|
+
"stopping",
|
|
840
|
+
"stops",
|
|
841
|
+
"open",
|
|
842
|
+
"opened",
|
|
843
|
+
"opening",
|
|
844
|
+
"opens",
|
|
845
|
+
"close",
|
|
846
|
+
"closed",
|
|
847
|
+
"closing",
|
|
848
|
+
"closes",
|
|
849
|
+
"done",
|
|
850
|
+
"doing",
|
|
851
|
+
// Time words
|
|
852
|
+
"today",
|
|
853
|
+
"tomorrow",
|
|
854
|
+
"yesterday",
|
|
855
|
+
"daily",
|
|
856
|
+
"weekly",
|
|
857
|
+
"monthly",
|
|
858
|
+
"yearly",
|
|
859
|
+
"annually",
|
|
860
|
+
"morning",
|
|
861
|
+
"afternoon",
|
|
862
|
+
"evening",
|
|
863
|
+
"night",
|
|
864
|
+
"week",
|
|
865
|
+
"month",
|
|
866
|
+
"year",
|
|
867
|
+
"hour",
|
|
868
|
+
"minute",
|
|
869
|
+
"second",
|
|
870
|
+
"time",
|
|
871
|
+
"date",
|
|
872
|
+
"day",
|
|
873
|
+
"days",
|
|
874
|
+
"weeks",
|
|
875
|
+
"months",
|
|
876
|
+
"years",
|
|
877
|
+
"currently",
|
|
878
|
+
"recently",
|
|
879
|
+
"later",
|
|
880
|
+
"earlier",
|
|
881
|
+
"soon",
|
|
882
|
+
"always",
|
|
883
|
+
"never",
|
|
884
|
+
"sometimes",
|
|
885
|
+
"often",
|
|
886
|
+
"usually",
|
|
887
|
+
"rarely",
|
|
888
|
+
// Generic/filler words
|
|
889
|
+
"thing",
|
|
890
|
+
"things",
|
|
891
|
+
"stuff",
|
|
892
|
+
"something",
|
|
893
|
+
"anything",
|
|
894
|
+
"nothing",
|
|
895
|
+
"everything",
|
|
896
|
+
"someone",
|
|
897
|
+
"anyone",
|
|
898
|
+
"noone",
|
|
899
|
+
"everyone",
|
|
900
|
+
"somewhere",
|
|
901
|
+
"anywhere",
|
|
902
|
+
"nowhere",
|
|
903
|
+
"everywhere",
|
|
904
|
+
"good",
|
|
905
|
+
"better",
|
|
906
|
+
"best",
|
|
907
|
+
"great",
|
|
908
|
+
"nice",
|
|
909
|
+
"okay",
|
|
910
|
+
"fine",
|
|
911
|
+
"right",
|
|
912
|
+
"wrong",
|
|
913
|
+
"bad",
|
|
914
|
+
"worse",
|
|
915
|
+
"worst",
|
|
916
|
+
"lot",
|
|
917
|
+
"lots",
|
|
918
|
+
"many",
|
|
919
|
+
"several",
|
|
920
|
+
"various",
|
|
921
|
+
"different",
|
|
922
|
+
"similar",
|
|
923
|
+
"another",
|
|
924
|
+
"next",
|
|
925
|
+
"last",
|
|
926
|
+
"first",
|
|
927
|
+
"second",
|
|
928
|
+
"third",
|
|
929
|
+
"new",
|
|
930
|
+
"old",
|
|
931
|
+
"big",
|
|
932
|
+
"small",
|
|
933
|
+
"large",
|
|
934
|
+
"little",
|
|
935
|
+
"long",
|
|
936
|
+
"short",
|
|
937
|
+
"high",
|
|
938
|
+
"low",
|
|
939
|
+
"full",
|
|
940
|
+
"empty",
|
|
941
|
+
"whole",
|
|
942
|
+
"part",
|
|
943
|
+
"real",
|
|
944
|
+
"true",
|
|
945
|
+
"false",
|
|
946
|
+
"actual",
|
|
947
|
+
"main",
|
|
948
|
+
"important",
|
|
949
|
+
// Descriptive/qualifier words
|
|
950
|
+
"really",
|
|
951
|
+
"actually",
|
|
952
|
+
"basically",
|
|
953
|
+
"probably",
|
|
954
|
+
"definitely",
|
|
955
|
+
"certainly",
|
|
956
|
+
"possibly",
|
|
957
|
+
"maybe",
|
|
958
|
+
"perhaps",
|
|
959
|
+
"like",
|
|
960
|
+
"likely",
|
|
961
|
+
"unlikely",
|
|
962
|
+
"almost",
|
|
963
|
+
"nearly",
|
|
964
|
+
"quite",
|
|
965
|
+
"rather",
|
|
966
|
+
"pretty",
|
|
967
|
+
"still",
|
|
968
|
+
"already",
|
|
969
|
+
"yet",
|
|
970
|
+
"though",
|
|
971
|
+
"although",
|
|
972
|
+
"however",
|
|
973
|
+
"therefore",
|
|
974
|
+
"thus",
|
|
975
|
+
"hence",
|
|
976
|
+
"truly",
|
|
977
|
+
"simply",
|
|
978
|
+
"easily",
|
|
979
|
+
"quickly",
|
|
980
|
+
"slowly",
|
|
981
|
+
"well",
|
|
982
|
+
"just",
|
|
983
|
+
"ever",
|
|
984
|
+
"either",
|
|
985
|
+
"neither",
|
|
986
|
+
"whether",
|
|
987
|
+
"because",
|
|
988
|
+
"since",
|
|
989
|
+
"while",
|
|
990
|
+
"until",
|
|
991
|
+
"unless",
|
|
992
|
+
"except",
|
|
993
|
+
"besides",
|
|
994
|
+
"anyway",
|
|
995
|
+
"otherwise",
|
|
996
|
+
"instead",
|
|
997
|
+
"meanwhile",
|
|
998
|
+
"furthermore",
|
|
999
|
+
"moreover",
|
|
1000
|
+
"nevertheless"
|
|
626
1001
|
]);
|
|
627
1002
|
function isConsonant(word, i) {
|
|
628
1003
|
const c = word[i];
|
|
@@ -1152,36 +1527,88 @@ function isLikelyArticleTitle(name) {
|
|
|
1152
1527
|
}
|
|
1153
1528
|
return false;
|
|
1154
1529
|
}
|
|
1155
|
-
var
|
|
1156
|
-
|
|
1157
|
-
|
|
1530
|
+
var STRICTNESS_CONFIGS = {
|
|
1531
|
+
conservative: {
|
|
1532
|
+
minWordLength: 5,
|
|
1533
|
+
minSuggestionScore: 15,
|
|
1534
|
+
// Requires exact match (10) + at least one stem (5)
|
|
1535
|
+
minMatchRatio: 0.6,
|
|
1536
|
+
// 60% of multi-word entity must match
|
|
1537
|
+
requireMultipleMatches: true,
|
|
1538
|
+
// Single-word entities need multiple content matches
|
|
1539
|
+
stemMatchBonus: 3,
|
|
1540
|
+
// Lower bonus for stem-only matches
|
|
1541
|
+
exactMatchBonus: 10
|
|
1542
|
+
// Standard bonus for exact matches
|
|
1543
|
+
},
|
|
1544
|
+
balanced: {
|
|
1545
|
+
minWordLength: 4,
|
|
1546
|
+
minSuggestionScore: 8,
|
|
1547
|
+
// At least one exact match or two stem matches
|
|
1548
|
+
minMatchRatio: 0.4,
|
|
1549
|
+
// 40% of multi-word entity must match
|
|
1550
|
+
requireMultipleMatches: false,
|
|
1551
|
+
stemMatchBonus: 5,
|
|
1552
|
+
// Standard bonus for stem matches
|
|
1553
|
+
exactMatchBonus: 10
|
|
1554
|
+
// Standard bonus for exact matches
|
|
1555
|
+
},
|
|
1556
|
+
aggressive: {
|
|
1557
|
+
minWordLength: 4,
|
|
1558
|
+
minSuggestionScore: 5,
|
|
1559
|
+
// Single stem match is enough
|
|
1560
|
+
minMatchRatio: 0.3,
|
|
1561
|
+
// 30% of multi-word entity must match
|
|
1562
|
+
requireMultipleMatches: false,
|
|
1563
|
+
stemMatchBonus: 6,
|
|
1564
|
+
// Higher bonus for stem matches
|
|
1565
|
+
exactMatchBonus: 10
|
|
1566
|
+
// Standard bonus for exact matches
|
|
1567
|
+
}
|
|
1568
|
+
};
|
|
1569
|
+
var DEFAULT_STRICTNESS = "conservative";
|
|
1570
|
+
var MIN_SUGGESTION_SCORE = STRICTNESS_CONFIGS.balanced.minSuggestionScore;
|
|
1571
|
+
var MIN_MATCH_RATIO = STRICTNESS_CONFIGS.balanced.minMatchRatio;
|
|
1572
|
+
function scoreEntity(entityName, contentTokens, contentStems, config) {
|
|
1158
1573
|
const entityTokens = tokenize(entityName);
|
|
1159
1574
|
if (entityTokens.length === 0)
|
|
1160
1575
|
return 0;
|
|
1161
1576
|
const entityStems = entityTokens.map((t) => stem(t));
|
|
1162
1577
|
let score = 0;
|
|
1163
1578
|
let matchedWords = 0;
|
|
1579
|
+
let exactMatches = 0;
|
|
1164
1580
|
for (let i = 0; i < entityTokens.length; i++) {
|
|
1165
1581
|
const token = entityTokens[i];
|
|
1166
1582
|
const entityStem = entityStems[i];
|
|
1167
1583
|
if (contentTokens.has(token)) {
|
|
1168
|
-
score +=
|
|
1584
|
+
score += config.exactMatchBonus;
|
|
1169
1585
|
matchedWords++;
|
|
1586
|
+
exactMatches++;
|
|
1170
1587
|
} else if (contentStems.has(entityStem)) {
|
|
1171
|
-
score +=
|
|
1588
|
+
score += config.stemMatchBonus;
|
|
1172
1589
|
matchedWords++;
|
|
1173
1590
|
}
|
|
1174
1591
|
}
|
|
1175
1592
|
if (entityTokens.length > 1) {
|
|
1176
1593
|
const matchRatio = matchedWords / entityTokens.length;
|
|
1177
|
-
if (matchRatio <
|
|
1594
|
+
if (matchRatio < config.minMatchRatio) {
|
|
1595
|
+
return 0;
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
if (config.requireMultipleMatches && entityTokens.length === 1) {
|
|
1599
|
+
if (exactMatches === 0) {
|
|
1178
1600
|
return 0;
|
|
1179
1601
|
}
|
|
1180
1602
|
}
|
|
1181
1603
|
return score;
|
|
1182
1604
|
}
|
|
1183
1605
|
function suggestRelatedLinks(content, options = {}) {
|
|
1184
|
-
const {
|
|
1606
|
+
const {
|
|
1607
|
+
maxSuggestions = 3,
|
|
1608
|
+
excludeLinked = true,
|
|
1609
|
+
strictness = DEFAULT_STRICTNESS
|
|
1610
|
+
} = options;
|
|
1611
|
+
const config = STRICTNESS_CONFIGS[strictness];
|
|
1185
1612
|
const emptyResult = { suggestions: [], suffix: "" };
|
|
1186
1613
|
if (SUGGESTION_PATTERN.test(content)) {
|
|
1187
1614
|
return emptyResult;
|
|
@@ -1213,11 +1640,11 @@ function suggestRelatedLinks(content, options = {}) {
|
|
|
1213
1640
|
if (linkedEntities.has(entityName.toLowerCase())) {
|
|
1214
1641
|
continue;
|
|
1215
1642
|
}
|
|
1216
|
-
const score = scoreEntity(entityName, contentTokens, contentStems);
|
|
1643
|
+
const score = scoreEntity(entityName, contentTokens, contentStems, config);
|
|
1217
1644
|
if (score > 0) {
|
|
1218
1645
|
directlyMatchedEntities.add(entityName);
|
|
1219
1646
|
}
|
|
1220
|
-
if (score >=
|
|
1647
|
+
if (score >= config.minSuggestionScore) {
|
|
1221
1648
|
scoredEntities.push({ name: entityName, score });
|
|
1222
1649
|
}
|
|
1223
1650
|
}
|
|
@@ -1237,7 +1664,7 @@ function suggestRelatedLinks(content, options = {}) {
|
|
|
1237
1664
|
const existing = scoredEntities.find((e) => e.name === entityName);
|
|
1238
1665
|
if (existing) {
|
|
1239
1666
|
existing.score += boost;
|
|
1240
|
-
} else if (boost >=
|
|
1667
|
+
} else if (boost >= config.minSuggestionScore) {
|
|
1241
1668
|
scoredEntities.push({ name: entityName, score: boost });
|
|
1242
1669
|
}
|
|
1243
1670
|
}
|
|
@@ -1271,9 +1698,10 @@ function registerMutationTools(server2, vaultPath2) {
|
|
|
1271
1698
|
commit: z.boolean().default(false).describe("If true, commit this change to git (creates undo point)"),
|
|
1272
1699
|
skipWikilinks: z.boolean().default(false).describe("If true, skip auto-wikilink application (wikilinks are applied by default)"),
|
|
1273
1700
|
preserveListNesting: z.boolean().default(true).describe("Detect and preserve the indentation level of surrounding list items. Set false to disable."),
|
|
1274
|
-
suggestOutgoingLinks: z.boolean().default(true).describe('Append suggested outgoing wikilinks based on content (e.g., "\u2192 [[AI]] [[Philosophy]]"). Set false to disable.')
|
|
1701
|
+
suggestOutgoingLinks: z.boolean().default(true).describe('Append suggested outgoing wikilinks based on content (e.g., "\u2192 [[AI]] [[Philosophy]]"). Set false to disable.'),
|
|
1702
|
+
maxSuggestions: z.number().min(1).max(10).default(3).describe("Maximum number of suggested wikilinks to append (1-10, default: 3)")
|
|
1275
1703
|
},
|
|
1276
|
-
async ({ path: notePath, section, content, position, format, commit, skipWikilinks, preserveListNesting, suggestOutgoingLinks }) => {
|
|
1704
|
+
async ({ path: notePath, section, content, position, format, commit, skipWikilinks, preserveListNesting, suggestOutgoingLinks, maxSuggestions }) => {
|
|
1277
1705
|
try {
|
|
1278
1706
|
const fullPath = path5.join(vaultPath2, notePath);
|
|
1279
1707
|
try {
|
|
@@ -1299,7 +1727,7 @@ function registerMutationTools(server2, vaultPath2) {
|
|
|
1299
1727
|
let { content: processedContent, wikilinkInfo } = maybeApplyWikilinks(content, skipWikilinks);
|
|
1300
1728
|
let suggestInfo;
|
|
1301
1729
|
if (suggestOutgoingLinks && !skipWikilinks) {
|
|
1302
|
-
const result2 = suggestRelatedLinks(processedContent);
|
|
1730
|
+
const result2 = suggestRelatedLinks(processedContent, { maxSuggestions });
|
|
1303
1731
|
if (result2.suffix) {
|
|
1304
1732
|
processedContent = processedContent + " " + result2.suffix;
|
|
1305
1733
|
suggestInfo = `Suggested: ${result2.suggestions.join(", ")}`;
|
|
@@ -1437,9 +1865,10 @@ function registerMutationTools(server2, vaultPath2) {
|
|
|
1437
1865
|
useRegex: z.boolean().default(false).describe("Treat search as regex"),
|
|
1438
1866
|
commit: z.boolean().default(false).describe("If true, commit this change to git (creates undo point)"),
|
|
1439
1867
|
skipWikilinks: z.boolean().default(false).describe("If true, skip auto-wikilink application on replacement text"),
|
|
1440
|
-
suggestOutgoingLinks: z.boolean().default(true).describe('Append suggested outgoing wikilinks based on content (e.g., "\u2192 [[AI]] [[Philosophy]]"). Set false to disable.')
|
|
1868
|
+
suggestOutgoingLinks: z.boolean().default(true).describe('Append suggested outgoing wikilinks based on content (e.g., "\u2192 [[AI]] [[Philosophy]]"). Set false to disable.'),
|
|
1869
|
+
maxSuggestions: z.number().min(1).max(10).default(3).describe("Maximum number of suggested wikilinks to append (1-10, default: 3)")
|
|
1441
1870
|
},
|
|
1442
|
-
async ({ path: notePath, section, search, replacement, mode, useRegex, commit, skipWikilinks, suggestOutgoingLinks }) => {
|
|
1871
|
+
async ({ path: notePath, section, search, replacement, mode, useRegex, commit, skipWikilinks, suggestOutgoingLinks, maxSuggestions }) => {
|
|
1443
1872
|
try {
|
|
1444
1873
|
const fullPath = path5.join(vaultPath2, notePath);
|
|
1445
1874
|
try {
|
|
@@ -1465,7 +1894,7 @@ function registerMutationTools(server2, vaultPath2) {
|
|
|
1465
1894
|
let { content: processedReplacement, wikilinkInfo } = maybeApplyWikilinks(replacement, skipWikilinks);
|
|
1466
1895
|
let suggestInfo;
|
|
1467
1896
|
if (suggestOutgoingLinks && !skipWikilinks) {
|
|
1468
|
-
const result2 = suggestRelatedLinks(processedReplacement);
|
|
1897
|
+
const result2 = suggestRelatedLinks(processedReplacement, { maxSuggestions });
|
|
1469
1898
|
if (result2.suffix) {
|
|
1470
1899
|
processedReplacement = processedReplacement + " " + result2.suffix;
|
|
1471
1900
|
suggestInfo = `Suggested: ${result2.suggestions.join(", ")}`;
|
|
@@ -1674,9 +2103,10 @@ function registerTaskTools(server2, vaultPath2) {
|
|
|
1674
2103
|
commit: z2.boolean().default(false).describe("If true, commit this change to git (creates undo point)"),
|
|
1675
2104
|
skipWikilinks: z2.boolean().default(false).describe("If true, skip auto-wikilink application (wikilinks are applied by default)"),
|
|
1676
2105
|
suggestOutgoingLinks: z2.boolean().default(true).describe('Append suggested outgoing wikilinks based on content (e.g., "\u2192 [[AI]] [[Philosophy]]"). Set false to disable.'),
|
|
2106
|
+
maxSuggestions: z2.number().min(1).max(10).default(3).describe("Maximum number of suggested wikilinks to append (1-10, default: 3)"),
|
|
1677
2107
|
preserveListNesting: z2.boolean().default(true).describe("Preserve indentation when inserting into nested lists. Default: true")
|
|
1678
2108
|
},
|
|
1679
|
-
async ({ path: notePath, section, task, position, completed, commit, skipWikilinks, suggestOutgoingLinks, preserveListNesting }) => {
|
|
2109
|
+
async ({ path: notePath, section, task, position, completed, commit, skipWikilinks, suggestOutgoingLinks, maxSuggestions, preserveListNesting }) => {
|
|
1680
2110
|
try {
|
|
1681
2111
|
const fullPath = path6.join(vaultPath2, notePath);
|
|
1682
2112
|
try {
|
|
@@ -1702,7 +2132,7 @@ function registerTaskTools(server2, vaultPath2) {
|
|
|
1702
2132
|
let { content: processedTask, wikilinkInfo } = maybeApplyWikilinks(task.trim(), skipWikilinks);
|
|
1703
2133
|
let suggestInfo;
|
|
1704
2134
|
if (suggestOutgoingLinks && !skipWikilinks) {
|
|
1705
|
-
const result2 = suggestRelatedLinks(processedTask);
|
|
2135
|
+
const result2 = suggestRelatedLinks(processedTask, { maxSuggestions });
|
|
1706
2136
|
if (result2.suffix) {
|
|
1707
2137
|
processedTask = processedTask + " " + result2.suffix;
|
|
1708
2138
|
suggestInfo = `Suggested: ${result2.suggestions.join(", ")}`;
|