smartmemory 1.4.25__tar.gz → 1.4.26__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 (100) hide show
  1. {smartmemory-1.4.25 → smartmemory-1.4.26}/CHANGELOG.md +15 -0
  2. {smartmemory-1.4.25 → smartmemory-1.4.26}/PKG-INFO +2 -2
  3. {smartmemory-1.4.25 → smartmemory-1.4.26}/pyproject.toml +2 -2
  4. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/local_api.py +71 -2
  5. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/viewer_server.py +13 -0
  6. {smartmemory-1.4.25 → smartmemory-1.4.26}/.github/dependabot.yml +0 -0
  7. {smartmemory-1.4.25 → smartmemory-1.4.26}/.github/workflows/publish.yml +0 -0
  8. {smartmemory-1.4.25 → smartmemory-1.4.26}/.github/workflows/sync-core.yml +0 -0
  9. {smartmemory-1.4.25 → smartmemory-1.4.26}/.gitignore +0 -0
  10. {smartmemory-1.4.25 → smartmemory-1.4.26}/LICENSE +0 -0
  11. {smartmemory-1.4.25 → smartmemory-1.4.26}/LICENSE.agpl-v3 +0 -0
  12. {smartmemory-1.4.25 → smartmemory-1.4.26}/LICENSE.header +0 -0
  13. {smartmemory-1.4.25 → smartmemory-1.4.26}/README.md +0 -0
  14. {smartmemory-1.4.25 → smartmemory-1.4.26}/plugin.json +0 -0
  15. {smartmemory-1.4.25 → smartmemory-1.4.26}/scripts/generate_seed_patterns.py +0 -0
  16. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/__init__.py +0 -0
  17. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/__main__.py +0 -0
  18. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/async_enrichment.py +0 -0
  19. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/cli.py +0 -0
  20. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/cli_code.py +0 -0
  21. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/cli_mcp.py +0 -0
  22. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/config.py +0 -0
  23. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/daemon.py +0 -0
  24. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/data/ai.smartmemory.daemon.plist +0 -0
  25. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/data/ai.smartmemory.worker.plist +0 -0
  26. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/data/seed_patterns.jsonl +0 -0
  27. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/data/seeds/ai-model.jsonl +0 -0
  28. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/data/seeds/concept.jsonl +0 -0
  29. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/data/seeds/database.jsonl +0 -0
  30. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/data/seeds/framework.jsonl +0 -0
  31. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/data/seeds/language.jsonl +0 -0
  32. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/data/seeds/manifest.json +0 -0
  33. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/data/seeds/organization.jsonl +0 -0
  34. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/data/seeds/platform.jsonl +0 -0
  35. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/data/seeds/protocol.jsonl +0 -0
  36. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/data/seeds/service.jsonl +0 -0
  37. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/data/seeds/tool.jsonl +0 -0
  38. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/enrichment_queue.py +0 -0
  39. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/enrichment_worker.py +0 -0
  40. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/event_sink.py +0 -0
  41. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/events_server.py +0 -0
  42. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/hooks/distill.sh +0 -0
  43. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/hooks/learn.sh +0 -0
  44. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/hooks/observe.sh +0 -0
  45. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/hooks/orient.sh +0 -0
  46. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/hooks/persist.sh +0 -0
  47. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/hooks/recall.sh +0 -0
  48. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/launch_metrics.py +0 -0
  49. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/lifecycle.py +0 -0
  50. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/lifecycle_api.py +0 -0
  51. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/lifecycle_config.py +0 -0
  52. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/patterns.py +0 -0
  53. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/recall_format.py +0 -0
  54. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/remote_backend.py +0 -0
  55. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/setup.py +0 -0
  56. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/setup_tui.py +0 -0
  57. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/skills/ingest.md +0 -0
  58. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/skills/orient.md +0 -0
  59. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/skills/remember.md +0 -0
  60. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/skills/search.md +0 -0
  61. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/static/assets/local-Clt8rYLQ.js +0 -0
  62. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/static/assets/local-ZCcXPKXN.css +0 -0
  63. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/static/icons/icon-192x192.svg +0 -0
  64. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/static/icons/icon-512x512.svg +0 -0
  65. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/static/index.html +0 -0
  66. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/static/logo.svg +0 -0
  67. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/static/viewer-logo.svg +0 -0
  68. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/storage.py +0 -0
  69. {smartmemory-1.4.25 → smartmemory-1.4.26}/smartmemory_app/sync.py +0 -0
  70. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/__init__.py +0 -0
  71. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/conftest.py +0 -0
  72. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/integration/__init__.py +0 -0
  73. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/integration/test_async_enrichment_e2e.py +0 -0
  74. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/integration/test_async_enrichment_sqlite_regression.py +0 -0
  75. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/integration/test_cli_new_subcommands.py +0 -0
  76. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/integration/test_daemon.py +0 -0
  77. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/integration/test_entity_ruler_patterns.py +0 -0
  78. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/integration/test_hook_recall.py +0 -0
  79. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/integration/test_hook_scripts.py +0 -0
  80. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/integration/test_local_api_integration.py +0 -0
  81. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/integration/test_recall_confidence.py +0 -0
  82. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/integration/test_recall_flow.py +0 -0
  83. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/integration/test_viewer_server.py +0 -0
  84. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/unit/__init__.py +0 -0
  85. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/unit/test_async_enrichment.py +0 -0
  86. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/unit/test_cli.py +0 -0
  87. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/unit/test_config.py +0 -0
  88. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/unit/test_events_server.py +0 -0
  89. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/unit/test_launchd.py +0 -0
  90. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/unit/test_lifecycle.py +0 -0
  91. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/unit/test_lite_api_contract.py +0 -0
  92. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/unit/test_local_api.py +0 -0
  93. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/unit/test_patterns.py +0 -0
  94. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/unit/test_recall_format.py +0 -0
  95. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/unit/test_remote_backend.py +0 -0
  96. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/unit/test_server_tools.py +0 -0
  97. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/unit/test_setup.py +0 -0
  98. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/unit/test_setup_tui.py +0 -0
  99. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/unit/test_stale_markers.py +0 -0
  100. {smartmemory-1.4.25 → smartmemory-1.4.26}/tests/unit/test_storage.py +0 -0
@@ -3,6 +3,21 @@
3
3
  Notable, **user-facing** changes to the `smartmemory` distribution package. The wrapper is thin — it pins an exact `smartmemory-core` version and the two move in lockstep — so entries here highlight what a release *delivers* (features, fixes, security), not routine version-pin bumps. For full internal detail, see [`smartmemory-core`'s CHANGELOG](https://github.com/smart-memory/smart-memory-core/blob/main/CHANGELOG.md). Loosely follows [Keep a Changelog](https://keepachangelog.com); not every patch release gets an entry.
4
4
 
5
5
  ## [Unreleased]
6
+ ### Changed (auto, lockstep) — track smartmemory-core==1.4.26 (1.4.26)
7
+ - Version copied from smartmemory-core 1.4.26 release (single-source lockstep).
8
+
9
+ ### Added — lite daemon graph parity (DIST-OBSIDIAN-LITE-PARITY-1)
10
+ - Local daemon (`viewer_server` + `local_api`) now serves `GET /memory/{id}/lineage`
11
+ (walks the `derived_from` chain, mirroring the hosted service) and
12
+ `GET /memory/{id}/links` (incident edges in `{source_id, target_id, link_type}`
13
+ shape). Previously missing, so the Obsidian lineage panel and graph link
14
+ fallback 404'd against the daemon. `/health` capabilities now advertise
15
+ `lineage`/`links` (true) and `decisions` (false, hosted-only).
16
+
17
+ ### Fixed
18
+ - `reextract` logged via an undefined `logger` (NameError on failure) → use `log`;
19
+ dropped an unused import.
20
+
6
21
  ### Changed (auto, lockstep) — track smartmemory-core==1.4.25 (1.4.25)
7
22
  - Version copied from smartmemory-core 1.4.25 release (single-source lockstep).
8
23
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: smartmemory
3
- Version: 1.4.25
3
+ Version: 1.4.26
4
4
  License-File: LICENSE
5
5
  License-File: LICENSE.agpl-v3
6
6
  License-File: LICENSE.header
@@ -10,7 +10,7 @@ Requires-Dist: fastapi>=0.110
10
10
  Requires-Dist: filelock>=3.12
11
11
  Requires-Dist: httpx>=0.27
12
12
  Requires-Dist: keyring>=24.0
13
- Requires-Dist: smartmemory-core[lite]==1.4.25
13
+ Requires-Dist: smartmemory-core[lite]==1.4.26
14
14
  Requires-Dist: smartmemory-mcp>=0.2.0
15
15
  Requires-Dist: textual>=8.0
16
16
  Requires-Dist: tomli-w>=1.0
@@ -4,10 +4,10 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "smartmemory"
7
- version = "1.4.25"
7
+ version = "1.4.26"
8
8
  requires-python = ">=3.11"
9
9
  dependencies = [
10
- "smartmemory-core[lite]==1.4.25", # EXACT pin — wrapper and core versions move in lockstep
10
+ "smartmemory-core[lite]==1.4.26", # EXACT pin — wrapper and core versions move in lockstep
11
11
  "filelock>=3.12", # cross-process SQLite write locking
12
12
  "smartmemory-mcp>=0.2.0", # unified MCP server (PLAT-MCP-UNIFY-1)
13
13
  "httpx>=0.27", # remote API calls (DIST-LITE-5)
@@ -328,6 +328,76 @@ def get_neighbors(memory_id: str) -> dict:
328
328
  return {"neighbors": formatted, "edges": edges}
329
329
 
330
330
 
331
+ @api.get("/{memory_id}/links")
332
+ def get_links(memory_id: str) -> dict:
333
+ """All edges incident to a node in the {source_id, target_id, link_type}
334
+ shape the graph adapter's getLinks consumer expects (useGraphData.js
335
+ fallback path) and the hosted service route returns.
336
+
337
+ DIST-OBSIDIAN-LITE-PARITY-1: was missing on the daemon, so the Obsidian
338
+ graph's per-node link fallback and any links() call 404'd in lite mode.
339
+ """
340
+ mem = _get_mem()
341
+ from smartmemory_app.remote_backend import RemoteMemory
342
+ if isinstance(mem, RemoteMemory):
343
+ # RemoteMemory carries raw edges on its neighbors payload; reshape.
344
+ edges = mem.get_neighbors(memory_id).get("edges", []) or []
345
+ else:
346
+ with _rw_lock:
347
+ edges = _get_backend().get_edges_for_node(memory_id)
348
+ links = []
349
+ for e in edges:
350
+ link_type = e.get("edge_type") or e.get("link_type")
351
+ if not link_type:
352
+ continue # malformed edge — skip rather than emit link_type=None
353
+ links.append({
354
+ "source_id": e.get("source_id"),
355
+ "target_id": e.get("target_id"),
356
+ "link_type": link_type,
357
+ })
358
+ return {"links": links}
359
+
360
+
361
+ @api.get("/{memory_id}/lineage")
362
+ def get_lineage(memory_id: str) -> dict:
363
+ """Walk the derived_from chain from an item back to its root (the item
364
+ with no derived_from). Mirrors the hosted service route verbatim
365
+ (smart-memory-service crud.py:634) so the Obsidian LineagePanel renders
366
+ identically in lite mode. Depth-capped at 20 to bound cycles.
367
+
368
+ DIST-OBSIDIAN-LITE-PARITY-1: was missing on the daemon — the panel showed
369
+ "No derivation history" for every note in lite mode.
370
+ """
371
+ mem = _get_mem()
372
+ from smartmemory_app.remote_backend import RemoteMemory
373
+ is_remote = isinstance(mem, RemoteMemory)
374
+
375
+ def _get_node(node_id: str) -> Optional[dict]:
376
+ if is_remote:
377
+ return mem.get_node(node_id)
378
+ with _rw_lock:
379
+ return _get_backend().get_node(node_id)
380
+
381
+ chain: list[dict] = []
382
+ current_id: Optional[str] = memory_id
383
+ seen: set = set()
384
+ while current_id and len(chain) < 20 and current_id not in seen:
385
+ seen.add(current_id)
386
+ node = _get_node(current_id)
387
+ if node is None:
388
+ break
389
+ derived_from = node.get("derived_from")
390
+ chain.append({
391
+ "item_id": node.get("item_id") or node.get("id") or current_id,
392
+ "content": (node.get("content") or "")[:200],
393
+ "memory_type": node.get("memory_type"),
394
+ "derived_from": derived_from,
395
+ "confidence": node.get("confidence"),
396
+ })
397
+ current_id = derived_from
398
+ return {"lineage": chain, "depth": len(chain)}
399
+
400
+
331
401
  @api.get("/{memory_id}")
332
402
  def get_memory_item(memory_id: str) -> dict[str, Any]:
333
403
  """get_node() uses _row_to_node() — output is already flat, no transformation needed."""
@@ -588,7 +658,7 @@ def reextract_entities() -> dict:
588
658
 
589
659
  extracted += 1
590
660
  except Exception as e:
591
- logger.warning("Re-extraction failed for %s: %s", item_id, e)
661
+ log.warning("Re-extraction failed for %s: %s", item_id, e)
592
662
  skipped += 1
593
663
 
594
664
  elapsed = time.time() - t0
@@ -629,7 +699,6 @@ def ingest_endpoint(body: IngestRequest) -> dict:
629
699
  SMARTMEMORY_WORKSPACE_ID env var > None (legacy untagged).
630
700
  """
631
701
  import os
632
- import time
633
702
  from smartmemory_app.recall_format import derive_workspace_id
634
703
 
635
704
  memory_type = body.memory_type
@@ -112,6 +112,15 @@ def _build_app() -> FastAPI:
112
112
  "neighbors_direction": True,
113
113
  "quota": False,
114
114
  "auth": False,
115
+ # DIST-OBSIDIAN-LITE-PARITY-1: lineage + per-node links are
116
+ # served by the daemon (built from get_node / neighbors edges).
117
+ "lineage": True,
118
+ "links": True,
119
+ # Decisions are a hosted-service subsystem (transitive
120
+ # provenance walk + decision store) the daemon does not
121
+ # replicate. False → clients degrade the panel explicitly
122
+ # instead of 404'ing.
123
+ "decisions": False,
115
124
  }
116
125
  else:
117
126
  mode = "lite"
@@ -121,6 +130,10 @@ def _build_app() -> FastAPI:
121
130
  "neighbors_direction": True,
122
131
  "quota": False,
123
132
  "auth": False,
133
+ # DIST-OBSIDIAN-LITE-PARITY-1: see remote block above.
134
+ "lineage": True,
135
+ "links": True,
136
+ "decisions": False,
124
137
  }
125
138
 
126
139
  return {
File without changes
File without changes
File without changes
File without changes