kyp-mem 0.2.1 → 0.3.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/kyp_mem/ui.py CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  import webbrowser
4
4
  from pathlib import Path
5
- from fastapi import FastAPI
5
+ from fastapi import FastAPI, Request
6
6
  from fastapi.responses import HTMLResponse, JSONResponse
7
7
  import uvicorn
8
8
  from .config import get_vault_path
@@ -34,6 +34,38 @@ def create_app(vault_path: str = None) -> FastAPI:
34
34
  return JSONResponse({"error": "Not found"}, 404)
35
35
  backlinks = vault.get_backlinks(path)
36
36
  related = vault.get_related(path)
37
+
38
+ backlink_details = []
39
+ for bl_path in backlinks:
40
+ bl_note = vault.index.notes.get(bl_path)
41
+ context = ""
42
+ if bl_note:
43
+ for line in bl_note.content.split("\n"):
44
+ if note.title.lower() in line.lower() or Path(path).stem.lower() in line.lower():
45
+ context = line.strip()[:150]
46
+ break
47
+ backlink_details.append({
48
+ "path": bl_path,
49
+ "title": bl_note.title if bl_note else bl_path,
50
+ "context": context,
51
+ })
52
+
53
+ unlinked = []
54
+ stem = Path(path).stem.lower()
55
+ title_lower = note.title.lower()
56
+ for other_path, other_note in vault.index.notes.items():
57
+ if other_path == path or other_path in backlinks:
58
+ continue
59
+ text = other_note.content.lower()
60
+ if stem in text or title_lower in text:
61
+ for line in other_note.content.split("\n"):
62
+ if stem in line.lower() or title_lower in line.lower():
63
+ ctx = line.strip()[:150]
64
+ break
65
+ else:
66
+ ctx = ""
67
+ unlinked.append({"path": other_path, "title": other_note.title, "context": ctx})
68
+
37
69
  return JSONResponse({
38
70
  "path": note.path,
39
71
  "title": note.title,
@@ -43,7 +75,8 @@ def create_app(vault_path: str = None) -> FastAPI:
43
75
  "created": note.created,
44
76
  "updated": note.updated,
45
77
  "links": note.links,
46
- "backlinks": backlinks,
78
+ "backlinks": backlink_details,
79
+ "unlinked": unlinked[:10],
47
80
  "related": [{"path": p, "score": s, "title": vault.index.notes[p].title if p in vault.index.notes else p} for p, s in related],
48
81
  })
49
82
 
@@ -75,6 +108,17 @@ def create_app(vault_path: str = None) -> FastAPI:
75
108
  for n in notes
76
109
  ])
77
110
 
111
+ @app.post("/api/note/{path:path}")
112
+ async def save_note(path: str, request: Request):
113
+ body = await request.json()
114
+ content = body.get("content", "")
115
+ tags = body.get("tags", [])
116
+ props = body.get("properties", {})
117
+ if not path.endswith(".md"):
118
+ path += ".md"
119
+ vault.write_note(path, content, tags, props)
120
+ return JSONResponse({"ok": True, "path": path})
121
+
78
122
  @app.post("/api/reload")
79
123
  def reload():
80
124
  vault._load_all()
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kyp-mem",
3
- "version": "0.2.1",
4
- "description": "Know Your Project — Headless knowledge base for AI agents. MCP-powered with wikilinks, backlinks, and neon web UI.",
3
+ "version": "0.3.0",
4
+ "description": "Know Your Project — Persistent knowledge base for AI agents. MCP-powered with wikilinks, backlinks, auto-learning, and neon web UI.",
5
5
  "bin": {
6
6
  "kyp-mem": "bin/cli.mjs"
7
7
  },
package/pyproject.toml CHANGED
@@ -4,8 +4,8 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "kyp-mem"
7
- version = "0.2.1"
8
- description = "Know Your Project — Headless knowledge base for AI agents. MCP-powered with wikilinks, backlinks, and neon web UI."
7
+ version = "0.3.0"
8
+ description = "Know Your Project — Persistent knowledge base for AI agents. MCP-powered with wikilinks, backlinks, auto-learning, and neon web UI."
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
11
11
  requires-python = ">=3.10"