confluence-knowledge 0.4.0__tar.gz → 0.4.1__tar.gz

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.
Files changed (35) hide show
  1. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/PKG-INFO +1 -1
  2. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/pyproject.toml +1 -1
  3. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/cli.py +29 -0
  4. confluence_knowledge-0.4.1/src/confluence_knowledge/update.py +55 -0
  5. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge.egg-info/PKG-INFO +1 -1
  6. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge.egg-info/SOURCES.txt +3 -1
  7. confluence_knowledge-0.4.1/tests/test_update.py +40 -0
  8. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/README.md +0 -0
  9. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/setup.cfg +0 -0
  10. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/__init__.py +0 -0
  11. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/auth.py +0 -0
  12. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/client.py +0 -0
  13. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/crawl.py +0 -0
  14. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/extract.py +0 -0
  15. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/extract_files.py +0 -0
  16. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/index.py +0 -0
  17. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/models.lock.json +0 -0
  18. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/registration.py +0 -0
  19. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/retrieval.py +0 -0
  20. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/server.py +0 -0
  21. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/settings.py +0 -0
  22. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge.egg-info/dependency_links.txt +0 -0
  23. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge.egg-info/entry_points.txt +0 -0
  24. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge.egg-info/requires.txt +0 -0
  25. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge.egg-info/top_level.txt +0 -0
  26. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/tests/test_agent_doc_consistency.py +0 -0
  27. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/tests/test_client_get_only.py +0 -0
  28. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/tests/test_crawl.py +0 -0
  29. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/tests/test_extract.py +0 -0
  30. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/tests/test_index.py +0 -0
  31. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/tests/test_prepare_models.py +0 -0
  32. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/tests/test_registration.py +0 -0
  33. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/tests/test_retrieval.py +0 -0
  34. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/tests/test_secrets.py +0 -0
  35. {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/tests/test_server_flow.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: confluence-knowledge
3
- Version: 0.4.0
3
+ Version: 0.4.1
4
4
  Summary: Local, GET-only Confluence subtree indexer + grounded-Q&A MCP service
5
5
  License: MIT
6
6
  Project-URL: Repository, https://github.com/nkunal1992/agents
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "confluence-knowledge"
7
- version = "0.4.0"
7
+ version = "0.4.1"
8
8
  description = "Local, GET-only Confluence subtree indexer + grounded-Q&A MCP service"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -94,9 +94,21 @@ def _wizard() -> int:
94
94
 
95
95
  def _doctor() -> int:
96
96
  from .server import status
97
+ from .update import check
97
98
  try:
98
99
  s = status()
99
100
  print(json.dumps(s, indent=2))
101
+ upd = check("confluence-knowledge")
102
+ if upd["installed"]:
103
+ line = f"version: {upd['installed']}"
104
+ if upd["latest"]:
105
+ line += f" (latest: {upd['latest']})"
106
+ elif upd["latest"] is None:
107
+ line += " (latest: unchecked — offline or internal mirror)"
108
+ print(line)
109
+ if upd["update_available"]:
110
+ print("update available: run `confluence-knowledge update` "
111
+ "(or pip install -U confluence-knowledge[models])")
100
112
  if s.get("configured"):
101
113
  from .server import _client_for # internal but fine in CLI
102
114
  profile = SiteProfile.load(default_home())
@@ -122,6 +134,7 @@ def main() -> None:
122
134
  sub.add_parser("setup", help="guided credential + config setup")
123
135
  sub.add_parser("doctor", help="verify config, credentials, models")
124
136
  sub.add_parser("prepare-models", help="download the pinned local models")
137
+ sub.add_parser("update", help="upgrade this package via pip -U")
125
138
  reg = sub.add_parser(
126
139
  "register",
127
140
  help="write this server into the IDE's MCP config (no manual paste)")
@@ -145,6 +158,22 @@ def main() -> None:
145
158
  for line in prepare_models(default_home()):
146
159
  print(line)
147
160
  return
161
+ if args.cmd == "update":
162
+ import subprocess
163
+ cmd = [sys.executable, "-m", "pip", "install", "-U",
164
+ "confluence-knowledge[models]"]
165
+ if os.name == "nt":
166
+ # this exe is the running process on Windows — pip can't replace
167
+ # a file that's in use; hand the user the equivalent python -m
168
+ # pip command instead (same mechanism `pip install -U pip` uses)
169
+ print("on Windows, upgrade via the venv python directly:\n "
170
+ + " ".join(f'"{c}"' if " " in c else c for c in cmd))
171
+ return
172
+ r = subprocess.run(cmd, check=False)
173
+ if r.returncode == 0:
174
+ print("\nupdated — models are pinned and unchanged; "
175
+ "run `confluence-knowledge doctor` to confirm")
176
+ sys.exit(r.returncode)
148
177
  if args.cmd == "register":
149
178
  from .registration import register
150
179
  try:
@@ -0,0 +1,55 @@
1
+ """Self-update check — installed vs latest published version.
2
+
3
+ One GET to the package index (PyPI or an internal mirror set via
4
+ KNOWLEDGE_UPDATE_INDEX) — fails silent to ``latest: None`` when offline or
5
+ proxied, and never blocks doctor.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ import os
12
+ import urllib.request
13
+ from importlib.metadata import PackageNotFoundError, version
14
+
15
+ INDEX = "https://pypi.org/pypi/{dist}/json"
16
+ ENV_INDEX = "KNOWLEDGE_UPDATE_INDEX"
17
+ TIMEOUT = 5
18
+
19
+
20
+ def installed_version(dist: str) -> str | None:
21
+ try:
22
+ return version(dist)
23
+ except PackageNotFoundError:
24
+ return None
25
+
26
+
27
+ def latest_version(dist: str, timeout: float = TIMEOUT) -> str | None:
28
+ """Latest version on the index — None when it can't be checked (offline,
29
+ internal mirror without the package, network policy). Never raises."""
30
+ url = os.environ.get(ENV_INDEX, INDEX).format(dist=dist)
31
+ try:
32
+ with urllib.request.urlopen(url, timeout=timeout) as r:
33
+ return json.loads(r.read())["info"]["version"]
34
+ except Exception: # noqa: BLE001 — every failure mode means "couldn't check"
35
+ return None
36
+
37
+
38
+ def check(dist: str) -> dict:
39
+ """{installed, latest, update_available} — the dict doctor reports."""
40
+ inst = installed_version(dist)
41
+ latest = latest_version(dist)
42
+ return {
43
+ "installed": inst,
44
+ "latest": latest,
45
+ "update_available": bool(
46
+ inst and latest and _version_tuple(latest) > _version_tuple(inst)),
47
+ }
48
+
49
+
50
+ def _version_tuple(v: str) -> tuple:
51
+ out = []
52
+ for part in v.split("."):
53
+ num = "".join(c for c in part if c.isdigit())
54
+ out.append(int(num) if num else 0)
55
+ return tuple(out)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: confluence-knowledge
3
- Version: 0.4.0
3
+ Version: 0.4.1
4
4
  Summary: Local, GET-only Confluence subtree indexer + grounded-Q&A MCP service
5
5
  License: MIT
6
6
  Project-URL: Repository, https://github.com/nkunal1992/agents
@@ -13,6 +13,7 @@ src/confluence_knowledge/registration.py
13
13
  src/confluence_knowledge/retrieval.py
14
14
  src/confluence_knowledge/server.py
15
15
  src/confluence_knowledge/settings.py
16
+ src/confluence_knowledge/update.py
16
17
  src/confluence_knowledge.egg-info/PKG-INFO
17
18
  src/confluence_knowledge.egg-info/SOURCES.txt
18
19
  src/confluence_knowledge.egg-info/dependency_links.txt
@@ -28,4 +29,5 @@ tests/test_prepare_models.py
28
29
  tests/test_registration.py
29
30
  tests/test_retrieval.py
30
31
  tests/test_secrets.py
31
- tests/test_server_flow.py
32
+ tests/test_server_flow.py
33
+ tests/test_update.py
@@ -0,0 +1,40 @@
1
+ """Self-update check — mocked index, offline path, version compare."""
2
+ from __future__ import annotations
3
+
4
+ from confluence_knowledge import update
5
+
6
+
7
+ def test_installed_version():
8
+ v = update.installed_version("confluence-knowledge")
9
+ assert v and v[0].isdigit()
10
+
11
+
12
+ def test_latest_offline_returns_none(monkeypatch):
13
+ monkeypatch.setattr(update, "INDEX", "https://invalid.invalid/{dist}")
14
+ monkeypatch.delenv("KNOWLEDGE_UPDATE_INDEX", raising=False)
15
+ # urllib will fail to resolve — must return None, not raise
16
+ assert update.latest_version("confluence-knowledge", timeout=1) is None
17
+
18
+
19
+ def test_check_update_available(monkeypatch):
20
+ monkeypatch.setattr(update, "latest_version", lambda d, **k: "99.0.0")
21
+ r = update.check("confluence-knowledge")
22
+ assert r["update_available"] is True and r["latest"] == "99.0.0"
23
+
24
+
25
+ def test_check_up_to_date(monkeypatch):
26
+ inst = update.installed_version("confluence-knowledge")
27
+ monkeypatch.setattr(update, "latest_version", lambda d, **k: inst)
28
+ r = update.check("confluence-knowledge")
29
+ assert r["update_available"] is False
30
+
31
+
32
+ def test_check_cannot_check(monkeypatch):
33
+ monkeypatch.setattr(update, "latest_version", lambda d, **k: None)
34
+ r = update.check("confluence-knowledge")
35
+ assert r["update_available"] is False and r["latest"] is None
36
+
37
+
38
+ def test_version_tuple():
39
+ assert update._version_tuple("1.2.10") > update._version_tuple("1.2.9")
40
+ assert update._version_tuple("0.4.1") == update._version_tuple("0.4.1")