@allansantos-dev/smart-tool 0.9.38 → 0.9.39

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/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.9.39 - beta
4
+
5
+ - Two-letter technical terms (`ui`, `db`, `id`) count again in the shared `focus_terms`, used by `smart_search
6
+ mode=dossier` and `smart_scout`. Two-letter English and Portuguese function words (`is`, `of`, `de`, `em`, ...) are
7
+ dropped like the question words. Tests in `tests/test_dossier.py`.
8
+ - The npm registry and OSV checks of `freshness` no longer raise. `npm_registry_evidence` read a local `version` before
9
+ assigning it (UnboundLocalError on every call) and `npm_advisories` shadowed the `version` module with its parameter;
10
+ both return evidence or `None` as documented. Tests in `tests/test_npm_evidence.py`.
11
+
3
12
  ## 0.9.38 - beta
4
13
 
5
14
  - One definition of a search term. `smart_search mode=dossier` now takes its terms from `dossier.focus_terms`, the
package/README.md CHANGED
@@ -16,7 +16,7 @@ registered as the `playwright` server where this machine lets a browser be drive
16
16
  An optional hook routes the agent's native Grep/Glob/Read/Bash/WebSearch/WebFetch calls to these tools when they
17
17
  are cheaper, or just tells the agent what Smart Tool would do.
18
18
 
19
- **Status:** 0.9.38 beta. Windows only. What changed in each version: [CHANGELOG.md](CHANGELOG.md).
19
+ **Status:** 0.9.39 beta. Windows only. What changed in each version: [CHANGELOG.md](CHANGELOG.md).
20
20
 
21
21
  ## How it works
22
22
 
package/dossier.py CHANGED
@@ -16,7 +16,7 @@ TITLE_CHARS = 80
16
16
  MAX_FILE_BYTES = 512 * 1024
17
17
  BACKLOG_FILES = ("docs/BACKLOG.md", "BACKLOG.md")
18
18
  INSTRUCTION_FILES = (("CLAUDE.md", "claude_md"), (".claude/CLAUDE.md", "claude_md"), ("AGENTS.md", "agents_md"))
19
- _WORD = re.compile(r"[\w]{3,}", re.UNICODE)
19
+ _WORD = re.compile(r"[\w]{2,}", re.UNICODE)
20
20
  _STOPWORDS = {
21
21
  "the", "and", "for", "how", "what", "where", "which", "does", "with", "from", "that", "this", "are", "when", "who",
22
22
  "why", "into", "used", "use", "uses", "its", "has", "have", "code", "project", "file", "files",
@@ -24,13 +24,15 @@ _STOPWORDS = {
24
24
  "pela", "ele", "ela", "isso", "esse", "essa", "este", "esta", "fica", "ficam", "usa", "usado", "usada", "sobre",
25
25
  "entre", "depois", "antes", "quando", "cada", "seu", "sua", "seus", "suas", "não", "sem", "mais", "código",
26
26
  "projeto", "arquivo", "arquivos", "decide", "funciona",
27
+ "is", "in", "to", "of", "on", "at", "by", "an", "as", "it", "or", "be", "do", "if", "so", "we", "no", "up", "me", "my",
28
+ "he", "us", "am", "de", "da", "em", "na", "os", "um", "se", "ao", "ou", "eu", "te", "é", "já", "só",
27
29
  }
28
30
  _UNIT_START = re.compile(r"#{1,6}\s|[-*]\s")
29
31
 
30
32
 
31
33
  def focus_terms(*texts):
32
- """Casefolded content words of the texts (3+ characters, common question words dropped), camelCase split, in
33
- order: what a window is scored by."""
34
+ """Casefolded content words of the texts (2+ characters, common question and function words dropped), camelCase
35
+ split, in order: what a window is scored by."""
34
36
  found = []
35
37
  for text in texts:
36
38
  spaced = re.sub(r"([a-z])([A-Z])", r"\1 \2", text or "")
package/freshness.py CHANGED
@@ -62,23 +62,23 @@ def npm_registry_evidence(package):
62
62
  try:
63
63
  with urllib.request.urlopen(request, timeout=7) as response:
64
64
  data = json.load(response)
65
- version = data.get("version") if isinstance(data, dict) else None
66
- if not isinstance(version, str) or not version or len(version) > 80:
65
+ latest = data.get("version") if isinstance(data, dict) else None
66
+ if not isinstance(latest, str) or not latest or len(latest) > 80:
67
67
  return None
68
68
  return {"title": f"npm registry: {package}", "url": url,
69
- "snippet": f"Latest version published on the npm registry: {version}",
70
- "tier": "npm_registry", "npm_package": package, "npm_version": version}
69
+ "snippet": f"Latest version published on the npm registry: {latest}",
70
+ "tier": "npm_registry", "npm_package": package, "npm_version": latest}
71
71
  except Exception:
72
72
  return None
73
73
 
74
74
 
75
- def npm_advisories(package, version):
75
+ def npm_advisories(package, package_version):
76
76
  """IDs conhecidos pela OSV para a versão; None significa checagem indisponível."""
77
- if (not package or not version
77
+ if (not package or not package_version
78
78
  or not re.fullmatch(r"(?:@[a-z0-9._-]+/)?[a-z0-9._-]+", package)):
79
79
  return None
80
80
  body = json.dumps({"package": {"name": package, "ecosystem": "npm"},
81
- "version": version}).encode("utf-8")
81
+ "version": package_version}).encode("utf-8")
82
82
  request = urllib.request.Request(
83
83
  "https://api.osv.dev/v1/query", data=body, method="POST",
84
84
  headers={"Content-Type": "application/json", "Accept": "application/json",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allansantos-dev/smart-tool",
3
- "version": "0.9.38",
3
+ "version": "0.9.39",
4
4
  "description": "Local MCP server that gives coding agents (Claude Code, Codex) cheaper, sharper tools than their built-in search. Windows.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Allan Santos",
package/version.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """Single source of the Smart Tool version and of the User-Agent sent to public APIs."""
2
2
  import re
3
3
 
4
- VERSION = "0.9.38"
4
+ VERSION = "0.9.39"
5
5
  _CONTACT_RE = re.compile(r"^(?:[^\s@()<>;]+@[^\s@()<>;]+\.[^\s@()<>;]+|https?://[^\s()<>;]+)$")
6
6
 
7
7