zigsm 1.4.1 → 1.4.2

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/std.js CHANGED
@@ -743,6 +743,36 @@ function setInputString(s) {
743
743
  let inMemoryEmbeddingCache = null;
744
744
  let cachedSourceTextIndex = null;
745
745
  let cachedSourceTextRef = null;
746
+ function countWordHits(text, words) {
747
+ let hits = 0;
748
+ for (const word of words) {
749
+ if (text.includes(word))
750
+ hits++;
751
+ }
752
+ return hits;
753
+ }
754
+ function scoreDeclMatch(decl, queryLower, queryWords) {
755
+ const nameLower = decl.name.toLowerCase();
756
+ const pathLower = decl.path.toLowerCase();
757
+ let score = 0;
758
+ if (nameLower === queryLower)
759
+ score += 1000;
760
+ else if (nameLower.startsWith(queryLower))
761
+ score += 700;
762
+ else if (nameLower.includes(queryLower))
763
+ score += 450;
764
+ if (pathLower.includes(queryLower))
765
+ score += 150;
766
+ if (score === 0 && queryWords.length > 0) {
767
+ const searchable = `${nameLower} ${decl.preview.toLowerCase()} ${pathLower}`;
768
+ const wordHits = countWordHits(searchable, queryWords);
769
+ if (wordHits === queryWords.length)
770
+ score += 300;
771
+ else if (wordHits > 0)
772
+ score += wordHits * 80;
773
+ }
774
+ return score;
775
+ }
746
776
  async function initWasmRuntime(wasmPath, stdSources) {
747
777
  const fs = await import("node:fs");
748
778
  const wasmBytes = typeof wasmPath === "string" ? fs.readFileSync(wasmPath) : wasmPath;
@@ -888,34 +918,55 @@ function buildSourceTextIndex(stdSources) {
888
918
  function fallbackSearchStdLib(stdSources, query, limit) {
889
919
  const index = buildSourceTextIndex(stdSources);
890
920
  const queryLower = query.toLowerCase().trim();
891
- const scored = index.decls
892
- .map((decl) => {
893
- const nameLower = decl.name.toLowerCase();
894
- const pathLower = decl.path.toLowerCase();
895
- let score = 0;
896
- if (nameLower === queryLower)
897
- score += 1000;
898
- else if (nameLower.startsWith(queryLower))
899
- score += 700;
900
- else if (nameLower.includes(queryLower))
901
- score += 450;
902
- if (pathLower.includes(queryLower))
903
- score += 150;
904
- return { decl, score };
905
- })
921
+ const queryWords = queryLower.split(/\s+/).filter(Boolean);
922
+ const declScored = index.decls
923
+ .map((decl) => ({ decl, score: scoreDeclMatch(decl, queryLower, queryWords) }))
906
924
  .filter((item) => item.score > 0)
907
925
  .sort((a, b) => b.score - a.score);
926
+ const contentMatches = [];
927
+ if (declScored.length < limit) {
928
+ for (const file of index.files) {
929
+ const lines = file.text.split("\n");
930
+ for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
931
+ const wordHits = countWordHits(lines[lineIndex].toLowerCase(), queryWords);
932
+ if (wordHits === queryWords.length) {
933
+ contentMatches.push({
934
+ path: file.path,
935
+ line: lineIndex + 1,
936
+ preview: lines[lineIndex].trim().slice(0, 120),
937
+ score: 200 + wordHits * 30,
938
+ });
939
+ }
940
+ if (contentMatches.length >= limit * 3)
941
+ break;
942
+ }
943
+ if (contentMatches.length >= limit * 3)
944
+ break;
945
+ }
946
+ contentMatches.sort((a, b) => b.score - a.score);
947
+ }
908
948
  let markdown = `# Search Results\n\nQuery: "${query}"\n\n`;
909
949
  markdown += `_Fallback mode: text index (parser-incompatible Zig version)_\n\n`;
910
- if (scored.length === 0) {
950
+ if (declScored.length === 0 && contentMatches.length === 0) {
911
951
  markdown += "No results found.";
912
952
  return markdown;
913
953
  }
914
- const limited = scored.slice(0, limit);
915
- markdown += `Found ${scored.length} results (showing ${limited.length}):\n\n`;
916
- for (let i = 0; i < limited.length; i++) {
917
- const entry = limited[i].decl;
918
- markdown += `- std.${entry.name} (${entry.path}:${entry.line})\n`;
954
+ if (declScored.length > 0) {
955
+ const limited = declScored.slice(0, limit);
956
+ markdown += `Found ${declScored.length} declaration matches (showing ${limited.length}):\n\n`;
957
+ for (let i = 0; i < limited.length; i++) {
958
+ const entry = limited[i].decl;
959
+ markdown += `- std.${entry.name} (${entry.path}:${entry.line})\n`;
960
+ }
961
+ }
962
+ if (contentMatches.length > 0 && declScored.length < limit) {
963
+ const remaining = limit - declScored.length;
964
+ const limited = contentMatches.slice(0, remaining);
965
+ markdown += `\nContent matches:\n\n`;
966
+ for (let i = 0; i < limited.length; i++) {
967
+ const entry = limited[i];
968
+ markdown += `- ${entry.path}:${entry.line} — \`${entry.preview}\`\n`;
969
+ }
919
970
  }
920
971
  return markdown;
921
972
  }
@@ -934,17 +985,7 @@ function fallbackGetStdLibItem(stdSources, name, getSourceFile) {
934
985
  const target = name.split(".").pop()?.trim() || name.trim();
935
986
  const targetLower = target.toLowerCase();
936
987
  const ranked = index.decls
937
- .map((decl) => {
938
- const declLower = decl.name.toLowerCase();
939
- let score = 0;
940
- if (declLower === targetLower)
941
- score += 1000;
942
- else if (declLower.startsWith(targetLower))
943
- score += 700;
944
- else if (declLower.includes(targetLower))
945
- score += 450;
946
- return { decl, score };
947
- })
988
+ .map((decl) => ({ decl, score: scoreDeclMatch(decl, targetLower, [targetLower]) }))
948
989
  .filter((item) => item.score > 0)
949
990
  .sort((a, b) => b.score - a.score);
950
991
  if (ranked.length === 0) {
package/dist/tools.js CHANGED
@@ -67,15 +67,26 @@ function getBuiltinFunctionTool(builtinFunctions) {
67
67
  ],
68
68
  };
69
69
  }
70
+ const queryBare = queryLower.replace(/@/g, "");
71
+ const queryWords = queryBare.split(/\s+/).filter(Boolean);
70
72
  const scoredFunctions = builtinFunctions.map((fn) => {
71
73
  const funcLower = fn.func.toLowerCase();
74
+ const funcBare = funcLower.replace(/^@/, "");
72
75
  let score = 0;
73
- if (funcLower === queryLower)
76
+ if (funcLower === queryLower || funcBare === queryBare)
74
77
  score += 1000;
75
78
  else if (funcLower.startsWith(queryLower))
76
79
  score += 500;
77
80
  else if (funcLower.includes(queryLower))
78
81
  score += 300;
82
+ if (score === 0 && queryWords.length > 0) {
83
+ const searchable = `${funcBare} ${fn.docs.toLowerCase()} ${fn.signature.toLowerCase()}`;
84
+ const wordHits = queryWords.filter((w) => searchable.includes(w)).length;
85
+ if (wordHits === queryWords.length)
86
+ score += 200;
87
+ else if (wordHits > 0)
88
+ score += wordHits * 60;
89
+ }
79
90
  if (score > 0)
80
91
  score += Math.max(0, 50 - fn.func.length);
81
92
  return { ...fn, score };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigsm",
3
- "version": "1.4.1",
3
+ "version": "1.4.2",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "zsm": "dist/mcp.js"