dsh-biocore 0.1.0 → 0.1.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.
Files changed (250) hide show
  1. package/README.md +2 -2
  2. package/lib/py/bridge.py +15 -7
  3. package/lib/py-bridge.js +4 -3
  4. package/package.json +3 -2
  5. package/python/biocore_memory/__init__.py +21 -0
  6. package/python/biocore_memory/adapters/__init__.py +2 -0
  7. package/python/biocore_memory/adapters/astrbot.py +24 -0
  8. package/python/biocore_memory/adapters/dsh_cli.py +335 -0
  9. package/python/biocore_memory/co_recall.py +324 -0
  10. package/python/biocore_memory/consolidate/__init__.py +11 -0
  11. package/python/biocore_memory/consolidate/gated.py +104 -0
  12. package/python/biocore_memory/consolidate/neighbors.py +68 -0
  13. package/python/biocore_memory/consolidate/reflection.py +45 -0
  14. package/python/biocore_memory/consolidate/tree.py +95 -0
  15. package/python/biocore_memory/consolidate/writeback.py +181 -0
  16. package/python/biocore_memory/core/__init__.py +4 -0
  17. package/python/biocore_memory/core/config.py +127 -0
  18. package/python/biocore_memory/core/permissions.py +69 -0
  19. package/python/biocore_memory/core/types.py +116 -0
  20. package/python/biocore_memory/core/util.py +26 -0
  21. package/python/biocore_memory/embedding_local.py +447 -0
  22. package/python/biocore_memory/embedding_mode.py +156 -0
  23. package/python/biocore_memory/engine.py +2476 -0
  24. package/python/biocore_memory/engine_helpers.py +266 -0
  25. package/python/biocore_memory/event/__init__.py +3 -0
  26. package/python/biocore_memory/event/_types.py +16 -0
  27. package/python/biocore_memory/event/consistency.py +117 -0
  28. package/python/biocore_memory/event/extract.py +48 -0
  29. package/python/biocore_memory/event/media.py +111 -0
  30. package/python/biocore_memory/event/notes.py +85 -0
  31. package/python/biocore_memory/event/notes_link.py +87 -0
  32. package/python/biocore_memory/event/vector.py +69 -0
  33. package/python/biocore_memory/evict/__init__.py +3 -0
  34. package/python/biocore_memory/evict/adaptive.py +73 -0
  35. package/python/biocore_memory/evict/consequence.py +58 -0
  36. package/python/biocore_memory/evict/heat.py +54 -0
  37. package/python/biocore_memory/evict/inhibition.py +105 -0
  38. package/python/biocore_memory/evict/policy.py +188 -0
  39. package/python/biocore_memory/evict/score.py +23 -0
  40. package/python/biocore_memory/identity/__init__.py +6 -0
  41. package/python/biocore_memory/identity/api.py +99 -0
  42. package/python/biocore_memory/identity/history.py +9 -0
  43. package/python/biocore_memory/identity/ledger.py +191 -0
  44. package/python/biocore_memory/identity/narrative.py +358 -0
  45. package/python/biocore_memory/identity/snapshot.py +13 -0
  46. package/python/biocore_memory/identity/writeback.py +61 -0
  47. package/python/biocore_memory/index/__init__.py +3 -0
  48. package/python/biocore_memory/index/cue_index.py +80 -0
  49. package/python/biocore_memory/index/entities.py +85 -0
  50. package/python/biocore_memory/index/entity_boost.py +104 -0
  51. package/python/biocore_memory/index/graph.py +172 -0
  52. package/python/biocore_memory/recall/__init__.py +5 -0
  53. package/python/biocore_memory/recall/api.py +65 -0
  54. package/python/biocore_memory/recall/bm25.py +118 -0
  55. package/python/biocore_memory/recall/channels.py +98 -0
  56. package/python/biocore_memory/recall/complexity.py +62 -0
  57. package/python/biocore_memory/recall/constraints.py +75 -0
  58. package/python/biocore_memory/recall/embedding.py +745 -0
  59. package/python/biocore_memory/recall/expand.py +26 -0
  60. package/python/biocore_memory/recall/filters.py +40 -0
  61. package/python/biocore_memory/recall/fusion.py +18 -0
  62. package/python/biocore_memory/recall/mmr.py +70 -0
  63. package/python/biocore_memory/recall/ppr.py +85 -0
  64. package/python/biocore_memory/recall/retrieval_practice.py +102 -0
  65. package/python/biocore_memory/relay/__init__.py +2 -0
  66. package/python/biocore_memory/relay/card.py +51 -0
  67. package/python/biocore_memory/slots/__init__.py +18 -0
  68. package/python/biocore_memory/slots/admission.py +64 -0
  69. package/python/biocore_memory/slots/boundary.py +128 -0
  70. package/python/biocore_memory/slots/evict_bridge.py +106 -0
  71. package/python/biocore_memory/slots/registry.py +135 -0
  72. package/python/biocore_memory/slots/switch.py +42 -0
  73. package/python/biocore_memory/store/__init__.py +4 -0
  74. package/python/biocore_memory/store/audit.py +74 -0
  75. package/python/biocore_memory/store/compress.py +81 -0
  76. package/python/biocore_memory/store/dedupe.py +178 -0
  77. package/python/biocore_memory/store/json_store.py +154 -0
  78. package/python/biocore_memory/store/media.py +145 -0
  79. package/python/biocore_memory/store/provenance.py +73 -0
  80. package/python/biocore_memory/store/rate_limit.py +93 -0
  81. package/python/biocore_memory/store/security.py +107 -0
  82. package/python/biocore_memory/store/source_consistency.py +123 -0
  83. package/python/biocore_memory/store/tiering.py +61 -0
  84. package/python/biocore_memory/store/tiering_exec.py +50 -0
  85. package/python/biocore_memory/store/tombstone.py +23 -0
  86. package/python/biocore_memory/store/versions.py +69 -0
  87. package/python/biocore_memory/thread/__init__.py +2 -0
  88. package/python/biocore_memory/thread/card.py +58 -0
  89. package/python/biocore_model/__init__.py +37 -0
  90. package/python/biocore_model/affective_labor.py +162 -0
  91. package/python/biocore_model/appraisal.py +257 -0
  92. package/python/biocore_model/appraisal_action.py +78 -0
  93. package/python/biocore_model/archive_queue.py +60 -0
  94. package/python/biocore_model/attachment_behavior.py +130 -0
  95. package/python/biocore_model/attachment_regulation.py +75 -0
  96. package/python/biocore_model/attachment_state.py +41 -0
  97. package/python/biocore_model/attribution.py +73 -0
  98. package/python/biocore_model/attributor.py +162 -0
  99. package/python/biocore_model/autonomic.py +91 -0
  100. package/python/biocore_model/autonomy_affect.py +51 -0
  101. package/python/biocore_model/autonomy_check.py +67 -0
  102. package/python/biocore_model/autonomy_loop.py +122 -0
  103. package/python/biocore_model/autonomy_mode.py +114 -0
  104. package/python/biocore_model/autonomy_model.py +733 -0
  105. package/python/biocore_model/autonomy_params.py +131 -0
  106. package/python/biocore_model/autonomy_reason.py +73 -0
  107. package/python/biocore_model/autonomy_tick.py +227 -0
  108. package/python/biocore_model/bio_appraisal.py +49 -0
  109. package/python/biocore_model/bio_autonomy_state.py +171 -0
  110. package/python/biocore_model/bio_config.py +221 -0
  111. package/python/biocore_model/bio_const.py +128 -0
  112. package/python/biocore_model/bio_daily.py +267 -0
  113. package/python/biocore_model/bio_emotion.py +538 -0
  114. package/python/biocore_model/bio_emotion2.py +214 -0
  115. package/python/biocore_model/bio_goal.py +220 -0
  116. package/python/biocore_model/bio_identity.py +82 -0
  117. package/python/biocore_model/bio_noise.py +119 -0
  118. package/python/biocore_model/bio_physiology2.py +114 -0
  119. package/python/biocore_model/bio_snapshot.py +324 -0
  120. package/python/biocore_model/bio_state.py +272 -0
  121. package/python/biocore_model/bio_tick.py +310 -0
  122. package/python/biocore_model/bio_util.py +82 -0
  123. package/python/biocore_model/blocks.py +264 -0
  124. package/python/biocore_model/boundary.py +251 -0
  125. package/python/biocore_model/boundary_gate.py +188 -0
  126. package/python/biocore_model/commitment_extractor.py +517 -0
  127. package/python/biocore_model/compassion_fatigue.py +84 -0
  128. package/python/biocore_model/connection_bids.py +120 -0
  129. package/python/biocore_model/core_bridge.py +177 -0
  130. package/python/biocore_model/core_client.py +127 -0
  131. package/python/biocore_model/core_commands.py +112 -0
  132. package/python/biocore_model/core_mode.py +104 -0
  133. package/python/biocore_model/core_mode_ui.mjs +104 -0
  134. package/python/biocore_model/criticality.py +81 -0
  135. package/python/biocore_model/defense_mechanisms.py +272 -0
  136. package/python/biocore_model/delta_budget.py +99 -0
  137. package/python/biocore_model/diag_trace.py +274 -0
  138. package/python/biocore_model/dissonance.py +134 -0
  139. package/python/biocore_model/emotion_geometry.py +108 -0
  140. package/python/biocore_model/emotion_probe.py +209 -0
  141. package/python/biocore_model/entity_graph.py +931 -0
  142. package/python/biocore_model/entity_resolve.py +260 -0
  143. package/python/biocore_model/envy.py +193 -0
  144. package/python/biocore_model/exit_or_silence.py +230 -0
  145. package/python/biocore_model/expr_guard.py +24 -0
  146. package/python/biocore_model/expr_intent.py +77 -0
  147. package/python/biocore_model/expr_state.py +204 -0
  148. package/python/biocore_model/expr_template.py +105 -0
  149. package/python/biocore_model/expr_tone.py +81 -0
  150. package/python/biocore_model/extreme_scenarios.py +205 -0
  151. package/python/biocore_model/feedback_flow.py +227 -0
  152. package/python/biocore_model/feedback_guard.py +129 -0
  153. package/python/biocore_model/feedback_llm.py +163 -0
  154. package/python/biocore_model/feedback_memory.py +96 -0
  155. package/python/biocore_model/feedback_user.py +93 -0
  156. package/python/biocore_model/frustration_curve.py +110 -0
  157. package/python/biocore_model/granularity.py +283 -0
  158. package/python/biocore_model/graph_extract.py +248 -0
  159. package/python/biocore_model/graph_recall.py +221 -0
  160. package/python/biocore_model/intent_render.py +91 -0
  161. package/python/biocore_model/intero_core.py +235 -0
  162. package/python/biocore_model/intero_style.py +116 -0
  163. package/python/biocore_model/layered_memory.py +297 -0
  164. package/python/biocore_model/learning_probe.py +120 -0
  165. package/python/biocore_model/memory_dual.py +224 -0
  166. package/python/biocore_model/memory_forgetting.py +125 -0
  167. package/python/biocore_model/memory_store.py +1399 -0
  168. package/python/biocore_model/metacog.py +153 -0
  169. package/python/biocore_model/migrate.py +733 -0
  170. package/python/biocore_model/migrate_store.py +337 -0
  171. package/python/biocore_model/mind_wander.py +111 -0
  172. package/python/biocore_model/mood.py +48 -0
  173. package/python/biocore_model/narrative.py +172 -0
  174. package/python/biocore_model/needs_esteem.py +116 -0
  175. package/python/biocore_model/needs_events.py +137 -0
  176. package/python/biocore_model/needs_sleep.py +72 -0
  177. package/python/biocore_model/noise_bank.py +95 -0
  178. package/python/biocore_model/persona_flow.mjs +25 -0
  179. package/python/biocore_model/pipeline.py +240 -0
  180. package/python/biocore_model/pipeline_api.py +200 -0
  181. package/python/biocore_model/plugin_config.py +83 -0
  182. package/python/biocore_model/plugin_routes.py +1435 -0
  183. package/python/biocore_model/policy_learning.py +132 -0
  184. package/python/biocore_model/possible_selves.py +110 -0
  185. package/python/biocore_model/predictor.py +178 -0
  186. package/python/biocore_model/preset.py +205 -0
  187. package/python/biocore_model/proactive_context.py +153 -0
  188. package/python/biocore_model/prompt_rules.py +90 -0
  189. package/python/biocore_model/prospective.py +183 -0
  190. package/python/biocore_model/provider_fallback.py +97 -0
  191. package/python/biocore_model/reconstruction.py +132 -0
  192. package/python/biocore_model/regulation_loop.py +179 -0
  193. package/python/biocore_model/regulation_strategies.py +294 -0
  194. package/python/biocore_model/relation_stage.py +130 -0
  195. package/python/biocore_model/relationship_stage.py +95 -0
  196. package/python/biocore_model/render.py +901 -0
  197. package/python/biocore_model/render_guard.mjs +34 -0
  198. package/python/biocore_model/repair_after_boundary.py +350 -0
  199. package/python/biocore_model/reply_limit.py +183 -0
  200. package/python/biocore_model/reply_split.py +203 -0
  201. package/python/biocore_model/rollback.py +143 -0
  202. package/python/biocore_model/runtime.py +479 -0
  203. package/python/biocore_model/sanitize.py +200 -0
  204. package/python/biocore_model/scheduler.py +123 -0
  205. package/python/biocore_model/schema.py +120 -0
  206. package/python/biocore_model/secrecy.py +145 -0
  207. package/python/biocore_model/self_esteem.py +50 -0
  208. package/python/biocore_model/self_intent.py +437 -0
  209. package/python/biocore_model/self_interest.py +263 -0
  210. package/python/biocore_model/self_verification.py +178 -0
  211. package/python/biocore_model/services.py +78 -0
  212. package/python/biocore_model/situation.py +254 -0
  213. package/python/biocore_model/sleep_circadian.py +116 -0
  214. package/python/biocore_model/social_pain.py +69 -0
  215. package/python/biocore_model/social_repair.py +111 -0
  216. package/python/biocore_model/social_theory.py +131 -0
  217. package/python/biocore_model/source_monitoring.py +292 -0
  218. package/python/biocore_model/stages.py +487 -0
  219. package/python/biocore_model/state_tag.py +231 -0
  220. package/python/biocore_model/switch_groups.mjs +201 -0
  221. package/python/biocore_model/tabs_state.mjs +37 -0
  222. package/python/biocore_model/template_expr.py +252 -0
  223. package/python/biocore_model/tools/caps_check.mjs +23 -0
  224. package/python/biocore_model/tools/init_symbols_check.mjs +11 -0
  225. package/python/biocore_model/tools/missing_ids.mjs +16 -0
  226. package/python/biocore_model/tools/scope_check.mjs +19 -0
  227. package/python/biocore_model/topic_control.py +268 -0
  228. package/python/biocore_model/turn_memory.py +152 -0
  229. package/python/biocore_model/ui_compat.mjs +48 -0
  230. package/python/biocore_model/ui_settings.py +266 -0
  231. package/python/biocore_model/ui_settings.py.bak_authority +108 -0
  232. package/python/biocore_model/value_order.py +186 -0
  233. package/python/biocore_model/view_mode.mjs +8 -0
  234. package/python/biocore_model/voice_bank.py +177 -0
  235. package/python/biocore_model/waiting_sense.py +229 -0
  236. package/python/biocore_model/x_directives.py +142 -0
  237. package/python/biocore_runtime/__init__.py +7 -0
  238. package/python/biocore_runtime/pipeline.py +1915 -0
  239. package/python/dsh_adapter/README.md +96 -0
  240. package/python/dsh_adapter/adapter.py +1077 -0
  241. package/python/dsh_adapter/cli.py +107 -0
  242. package/python/dsh_adapter/data/demo_state.json +164 -0
  243. package/python/dsh_adapter/data/verify_state.json +164 -0
  244. package/python/dsh_adapter/tests/__init__.py +1 -0
  245. package/python/dsh_adapter/tests/test_adapter.py +494 -0
  246. package/ui/panel-layout.js +3 -3
  247. package/ui/panel.css +53 -6
  248. package/ui/panel.html +33 -32
  249. package/ui/panel.js +9 -1
  250. package/lib/py/__pycache__/bridge.cpython-310.pyc +0 -0
@@ -0,0 +1,181 @@
1
+ """Write-back bridge for consolidation suggestions (default OFF, idempotent).
2
+ Pure/local: operates on an in-memory MemoryStore-like object (entries/add/update).
3
+ It never saves to disk by itself; the caller decides when to call store.save().
4
+ All failures degrade to skipped entries instead of raising.
5
+ """
6
+ from __future__ import annotations
7
+ import hashlib
8
+ import json
9
+ WRITEBACK_ENABLED = False
10
+ MAX_RELATED = 8
11
+ REFLECTION_SOURCE = "consolidate"
12
+ TREE_SOURCE = "ti_mem"
13
+ def _digest(text):
14
+ return hashlib.sha256(str(text or "").encode("utf-8")).hexdigest()[:12]
15
+ def _entries(store):
16
+ try:
17
+ rows = getattr(store, "entries", None)
18
+ if isinstance(rows, list):
19
+ return rows
20
+ if isinstance(store, dict):
21
+ rows = store.get("entries")
22
+ return rows if isinstance(rows, list) else []
23
+ return list(store or [])
24
+ except Exception:
25
+ return []
26
+ def _find(store, entry_id):
27
+ try:
28
+ fn = getattr(store, "find", None)
29
+ if callable(fn):
30
+ row = fn(entry_id)
31
+ if isinstance(row, dict):
32
+ return row
33
+ except Exception:
34
+ pass
35
+ for entry in _entries(store):
36
+ if isinstance(entry, dict) and str(entry.get("id") or "") == str(entry_id):
37
+ return entry
38
+ return None
39
+ def _add(store, entry):
40
+ try:
41
+ fn = getattr(store, "add", None)
42
+ if callable(fn):
43
+ return fn(entry)
44
+ if isinstance(store, dict):
45
+ store.setdefault("entries", []).append(entry)
46
+ return entry
47
+ store.append(entry)
48
+ return entry
49
+ except Exception:
50
+ return None
51
+ def _update(store, entry_id, **fields):
52
+ try:
53
+ fn = getattr(store, "update", None)
54
+ if callable(fn):
55
+ result = fn(entry_id, **fields)
56
+ if result is not None:
57
+ return result
58
+ except Exception:
59
+ pass
60
+ entry = _find(store, entry_id)
61
+ if isinstance(entry, dict):
62
+ entry.update(fields)
63
+ return entry
64
+ return None
65
+ def _source_ids(proposal):
66
+ raw = proposal.get("source_ids") if isinstance(proposal, dict) else []
67
+ return sorted({str(x) for x in (raw or []) if str(x)})
68
+ def _scope(entry):
69
+ fields = ("session", "scope", "user_id", "agent_id", "app_id", "run_id", "thread")
70
+ return {k: entry.get(k) for k in fields if entry.get(k) is not None}
71
+ def _importance(store, ids, default=0.5):
72
+ values = []
73
+ for sid in ids:
74
+ row = _find(store, sid)
75
+ if isinstance(row, dict):
76
+ try:
77
+ values.append(float(row.get("importance", 0.5) or 0.5))
78
+ except Exception:
79
+ continue
80
+ return round(sum(values) / len(values), 4) if values else default
81
+ def apply_reflections(store, proposals):
82
+ """Write reflection proposals as system entries; idempotent by source_ids."""
83
+ result = {"written": [], "skipped": []}
84
+ if not WRITEBACK_ENABLED:
85
+ result["skipped"].append({"reason": "disabled"})
86
+ return result
87
+ for idx, proposal in enumerate(proposals or []):
88
+ try:
89
+ text = str((proposal or {}).get("text") or "").strip() if isinstance(proposal, dict) else ""
90
+ ids = _source_ids(proposal)
91
+ if len(text) < 2 or not ids:
92
+ result["skipped"].append({"index": idx, "reason": "invalid"})
93
+ continue
94
+ duplicate = any(
95
+ str(e.get("source") or "") == REFLECTION_SOURCE
96
+ and sorted(str(x) for x in ((e.get("metadata") or {}).get("source_ids") or []))
97
+ == ids
98
+ for e in _entries(store) if isinstance(e, dict))
99
+ if duplicate:
100
+ result["skipped"].append({"index": idx, "reason": "duplicate"})
101
+ continue
102
+ base = {"id": "consolidate_" + _digest(json.dumps([text, ids]))}
103
+ base.update(_scope(_find(store, ids[0]) or {}))
104
+ base.update({"text": text, "role": "system", "source": REFLECTION_SOURCE,
105
+ "importance": _importance(store, ids),
106
+ "metadata": {"source_ids": ids, "origin": "reflection"}})
107
+ added = _add(store, base)
108
+ if isinstance(added, dict) and added.get("id"):
109
+ result["written"].append(str(added.get("id")))
110
+ else:
111
+ result["skipped"].append({"index": idx, "reason": "add_failed"})
112
+ except Exception:
113
+ result["skipped"].append({"index": idx, "reason": "error"})
114
+ return result
115
+ def _suggestions(suggestions):
116
+ if isinstance(suggestions, dict):
117
+ return [suggestions]
118
+ return [s for s in (suggestions or []) if isinstance(s, dict)]
119
+ def apply_neighbors(store, suggestions):
120
+ """Append strengthen() link_ids to related_ids (dedupe, total <=8)."""
121
+ result = {"linked": 0}
122
+ if not WRITEBACK_ENABLED:
123
+ return result
124
+ for suggestion in _suggestions(suggestions):
125
+ try:
126
+ eid = str(suggestion.get("entry_id") or "")
127
+ entry = _find(store, eid)
128
+ if not isinstance(entry, dict):
129
+ continue
130
+ current = entry.get("related_ids")
131
+ current = [str(x) for x in current if str(x)] if isinstance(current, list) else []
132
+ links = [str(x) for x in (suggestion.get("link_ids") or []) if str(x) and str(x) != eid]
133
+ merged = []
134
+ for value in current + links:
135
+ if value not in merged:
136
+ merged.append(value)
137
+ merged = merged[:MAX_RELATED]
138
+ if merged == current:
139
+ continue
140
+ if _update(store, eid, related_ids=merged):
141
+ result["linked"] += 1
142
+ except Exception:
143
+ continue
144
+ return result
145
+ def _day_of(items):
146
+ days = [str((x or {}).get("day") or (x or {}).get("key") or "") for x in (items or [])]
147
+ for value in days:
148
+ if len(value) >= 10 and value[:4].isdigit():
149
+ return value[:10]
150
+ return days[0][:10] if days and days[0] else ""
151
+ def write_tree(store, summary):
152
+ """Write one tree summary entry (level/day); idempotent by source+level+day."""
153
+ level = int((summary or {}).get("level") or 1) if isinstance(summary, dict) else 1
154
+ result = {"written": 0, "level": level}
155
+ if not WRITEBACK_ENABLED or not isinstance(summary, dict):
156
+ return result
157
+ try:
158
+ items = list(summary.get("items") or [])
159
+ if not summary.get("generated") or not items:
160
+ return result
161
+ day = _day_of(items)
162
+ duplicate = any(
163
+ str(e.get("source") or "") == TREE_SOURCE
164
+ and int((e.get("metadata") or {}).get("level") or 0) == level
165
+ and str((e.get("metadata") or {}).get("day") or "") == day
166
+ for e in _entries(store) if isinstance(e, dict))
167
+ if duplicate:
168
+ return result
169
+ text = "时间树 L%d %s:%s" % (
170
+ level, day, json.dumps(items[:10], ensure_ascii=False, sort_keys=True)[:1000])
171
+ entry = {"id": TREE_SOURCE + "_" + _digest("%s|%s|%s" % (level, day, text)),
172
+ "text": text[:1200], "role": "system", "source": TREE_SOURCE,
173
+ "importance": 0.5,
174
+ "metadata": {"level": level, "day": day,
175
+ "source_ids": [str(x.get("key") or "") for x in items[:8]]}}
176
+ added = _add(store, entry)
177
+ if isinstance(added, dict):
178
+ result["written"] = 1
179
+ return result
180
+ except Exception:
181
+ return result
@@ -0,0 +1,4 @@
1
+ # OWNER: engine-core
2
+ from .config import * # noqa
3
+ from .types import MemoryEntry, Cue, EventVector, ThreadCard, RelayCard # noqa
4
+ from .util import sha12, clamp01, normalize_text, now_ts # noqa
@@ -0,0 +1,127 @@
1
+ # -*- coding: utf-8 -*-
2
+ """All memory-layer thresholds/defaults in one place."""
3
+ from __future__ import annotations
4
+
5
+ SCHEMA_VERSION = 1
6
+ MAX_VERSIONS = 8
7
+ TOMBSTONE_LIMIT = 100
8
+ DEFAULT_BUDGET = 3
9
+ MAX_BUDGET = 5
10
+
11
+ # recall fusion / tiers (M2)
12
+ CUE_WEIGHT = 0.50
13
+ SEM_WEIGHT = 0.30
14
+ IMPORTANCE_WEIGHT = 0.10
15
+ TIME_BONUS = 0.10
16
+ HIGH_TIER = 0.55
17
+ MID_TIER = 0.35
18
+
19
+ # source credibility gate (separate from importance)
20
+ SOURCE_MIN_CONFIDENCE = 0.55
21
+ SOURCE_CONFIDENCE_DEFAULT = 0.70
22
+
23
+ # memory value formula (deterministic; trust is NOT part of value)
24
+ VALUE_BASE = 0.20
25
+ VALUE_W_INTENSITY = 0.30
26
+ VALUE_W_VALENCE = 0.20
27
+ VALUE_W_SELF = 0.15
28
+ VALUE_W_MAINLINE = 0.15
29
+ VALUE_W_ROUTINE = 0.20
30
+
31
+ # eviction weights (read-only score)
32
+ EVICT_W_SALIENCE = 0.30
33
+ EVICT_W_POSITION = 0.20
34
+ EVICT_W_REDUNDANCY = 0.20
35
+ EVICT_W_CONFIDENCE = 0.15
36
+ EVICT_W_STALENESS = 0.15
37
+
38
+ # identity write-back gate
39
+ SAME_DIRECTION_MIN = 3
40
+ MAX_STEP = 0.02
41
+ MAJOR_EVENT_STEP = 0.02
42
+
43
+ # thread card
44
+ THREAD_TTL = 21600.0
45
+ THREAD_LIMIT = 3
46
+
47
+ # memory-point gate (OR): value >= MIN_VALUE or importance >= MIN_IMPORTANCE or self >= MIN_SELF
48
+ # (event centrality / emotional intensity; self-reference effect; engineering thresholds)
49
+ MEMORY_POINT_MIN_VALUE = 0.60
50
+ MEMORY_POINT_MIN_SELF = 0.45
51
+ MEMORY_POINT_MIN_IMPORTANCE = 0.75
52
+
53
+ # engine wiring knobs (all read by MemoryEngine only)
54
+ RATE_LIMIT_PER_MIN = 30
55
+ COMPRESS_MAX_CHARS = 200
56
+ AUDIT_TAIL = 50
57
+ COOC_MAX_ENTRIES = 400
58
+ # after-turn auto consolidation: every N successful remember() calls
59
+ CONSOLIDATE_AUTO_TURNS = 10
60
+
61
+
62
+ # Per-mechanism flags: safety/read-path filters default ON; every optional
63
+ # mechanism defaults OFF and must keep the old code path when disabled.
64
+ # A flags.json in the data directory overrides these booleans at engine start
65
+ # (and MemoryEngine.set_flags(..., persist=True) rewrites it).
66
+ FLAGS = {
67
+ # safety / read-path (default ON)
68
+ # GA-03: keep engine default ON. DSH private mode disables it per-store via
69
+ # <dsh store>/flags.json; the shared engine must not be relaxed globally.
70
+ "security": True, # store/security.should_reject before write
71
+ "provenance": True, # provenance hash tag + chained tombstones
72
+ "source_filter": True, # low-confidence candidates are counted/dropped
73
+ "temporal_filter": True, # honour valid_at/invalid_at on recall
74
+ "dedupe": True, # remember-side L0-L3 dedupe
75
+ "relay": True, # relay card
76
+ "thread": True, # thread card / TTL expiry
77
+ "embedding": True, # optional embedding provider
78
+ # attention / model features (default OFF)
79
+ "slots": False,
80
+ "boundary": False, # slots/boundary.py event-boundary switching
81
+ "three_channel": False,
82
+ "eviction_readonly": False,
83
+ "identity": False,
84
+ "identity_writeback": False,
85
+ "due_hints": False,
86
+ # recall extensions (default OFF)
87
+ "bm25": False,
88
+ "bm25_multi": False,
89
+ "ppr": False,
90
+ "mmr": False,
91
+ "complexity": False,
92
+ "constraints": False,
93
+ "tiering": False,
94
+ "entity_boost": False,
95
+ "inhibition": False,
96
+ "retrieval_practice": False,
97
+ "compress": False, # output-only summary, never mutates the store
98
+ "source_consistency": False, # source-rank marking/downweight on recall
99
+ # eviction extension modules (default OFF)
100
+ "heat": False,
101
+ "consequence": False,
102
+ "tiering_exec": False,
103
+ "apply_evictions": False, # tick() may really soft-delete archived entries
104
+ "deletion_audit": False, # derived-data coverage audit after forget()
105
+ "adaptive_evict": False, # adaptive_score replaces the tick eviction score
106
+
107
+ # write-path extensions (default OFF)
108
+ "consistency": False, # old/new fact conflict annotation on remember
109
+ "rate_limit": False,
110
+ "audit": False,
111
+ "permissions": False,
112
+ "notes": False,
113
+ "media": False,
114
+ "notes_link": False,
115
+ "ledger": False,
116
+ # index / graph
117
+ "graph": False,
118
+ "cue_writeback": True, # store cue_index fields on each new entry (index-only, no recall change)
119
+ # consolidation modules (default OFF)
120
+ "consolidate_auto": False, # after-turn auto consolidate every CONSOLIDATE_AUTO_TURNS remembers
121
+ "consolidate_gated": False,
122
+ "consolidate_tree": False,
123
+ "consolidate_reflection": False,
124
+ "consolidate_neighbors": False,
125
+ "consolidate_writeback": False,
126
+ "narrative": False, # identity narrative update at consolidate end
127
+ }
@@ -0,0 +1,69 @@
1
+ # -*- coding: utf-8 -*-
2
+ """Scope-based read/write permissions (default OFF; pure, no astrbot)."""
3
+ from __future__ import annotations
4
+
5
+ enabled = False
6
+ ENABLED = False
7
+ ADMIN_ROLES = ("admin", "owner", "system", "superuser", "root")
8
+ READONLY_ROLES = ("guest", "readonly", "viewer")
9
+ PUBLIC_SCOPES = ("*", "public", "all", "shared")
10
+
11
+
12
+ def _principal(principal):
13
+ value = principal if isinstance(principal, dict) else {}
14
+ role = str(value.get("role") or "user").strip().lower()
15
+ identifier = str(value.get("id") or value.get("user_id") or "").strip()
16
+ scopes = value.get("scopes")
17
+ if not isinstance(scopes, list):
18
+ scopes = [value.get("scope")] if value.get("scope") is not None else []
19
+ return role, identifier, {str(s).strip() for s in scopes if str(s).strip()}
20
+
21
+
22
+ def _scopes(entry):
23
+ if not isinstance(entry, dict):
24
+ return set()
25
+ raw = entry.get("scope")
26
+ if raw is None:
27
+ raw = entry.get("scopes")
28
+ if isinstance(raw, str):
29
+ raw = [raw]
30
+ if not isinstance(raw, (list, tuple, set)):
31
+ return set()
32
+ return {str(value).strip() for value in raw if str(value).strip()}
33
+
34
+
35
+ def _can_access(entry, principal):
36
+ if not enabled:
37
+ return True
38
+ role, identifier, principal_scopes = _principal(principal)
39
+ if role in ADMIN_ROLES:
40
+ return True
41
+ scopes = _scopes(entry)
42
+ if not scopes:
43
+ return True
44
+ if scopes & set(PUBLIC_SCOPES):
45
+ return True
46
+ if identifier and (identifier in scopes or ("user:" + identifier) in scopes):
47
+ return True
48
+ return bool(principal_scopes & scopes)
49
+
50
+
51
+ def can_read(entry, principal=None):
52
+ """True when principal may read entry (disabled -> always True)."""
53
+ try:
54
+ return _can_access(entry, principal)
55
+ except Exception:
56
+ return not enabled
57
+
58
+
59
+ def can_write(entry, principal=None):
60
+ """True when principal may write entry; readonly roles are denied when on."""
61
+ try:
62
+ if not enabled:
63
+ return True
64
+ role, _identifier, _scopes_set = _principal(principal)
65
+ if role in READONLY_ROLES:
66
+ return False
67
+ return _can_access(entry, principal)
68
+ except Exception:
69
+ return not enabled
@@ -0,0 +1,116 @@
1
+ # -*- coding: utf-8 -*-
2
+ """Host-neutral data structures for the memory layer.
3
+
4
+ Interface summary:
5
+ MemoryEntry(id, text, role, session, ts, vector, importance, pin, metadata, scope)
6
+ Cue(entities, place, time, event_name, id)
7
+ EventVector(intensity, self_relevance, schema_conflict, relation_weight,
8
+ novelty, unresolved, repetition)
9
+ ThreadCard(id, text, ts); RelayCard(identity, relationship, open_loops,
10
+ recent, pins)
11
+ Each type exposes from_dict/to_dict (signatures below); no host imports.
12
+ """
13
+ from __future__ import annotations
14
+ from dataclasses import asdict, dataclass, field
15
+
16
+
17
+ @dataclass
18
+ class MemoryEntry:
19
+ id: str = ""
20
+ text: str = ""
21
+ role: str = "user"
22
+ session: str = ""
23
+ ts: float = 0.0
24
+ vector: list = field(default_factory=list)
25
+ importance: float = 0.5
26
+ pin: bool = False
27
+ metadata: dict = field(default_factory=dict)
28
+ scope: str = "default"
29
+
30
+ @classmethod
31
+ def from_dict(cls, value):
32
+ if not isinstance(value, dict):
33
+ return cls(text=str(value or ""))
34
+ return cls(**{k: value[k] for k in cls.__dataclass_fields__ if k in value})
35
+
36
+ def to_dict(self):
37
+ out = asdict(self)
38
+ metadata = out.pop("metadata", {}) or {}
39
+ out.update(metadata)
40
+ return out
41
+
42
+
43
+ @dataclass
44
+ class Cue:
45
+ entities: list = field(default_factory=list)
46
+ place: list = field(default_factory=list)
47
+ time: list = field(default_factory=list)
48
+ event_name: str = ""
49
+ id: str = ""
50
+
51
+ @classmethod
52
+ def from_dict(cls, value):
53
+ if not isinstance(value, dict):
54
+ return cls()
55
+ return cls(**{k: value[k] for k in cls.__dataclass_fields__ if k in value})
56
+
57
+ def to_dict(self):
58
+ return asdict(self)
59
+
60
+
61
+ @dataclass
62
+ class EventVector:
63
+ intensity: float = 0.0
64
+ self_relevance: float = 0.0
65
+ schema_conflict: float = 0.0
66
+ relation_weight: float = 0.0
67
+ novelty: float = 0.0
68
+ unresolved: float = 0.0
69
+ repetition: float = 0.0
70
+
71
+ @classmethod
72
+ def from_dict(cls, value):
73
+ if not isinstance(value, dict):
74
+ return cls()
75
+ return cls(**{k: value[k] for k in cls.__dataclass_fields__ if k in value})
76
+
77
+ def to_dict(self):
78
+ return asdict(self)
79
+
80
+ def as_dict(self):
81
+ """Compatibility alias for to_dict (older call sites)."""
82
+ return self.to_dict()
83
+
84
+
85
+ @dataclass
86
+ class ThreadCard:
87
+ id: str = ""
88
+ text: str = ""
89
+ ts: float = 0.0
90
+
91
+ @classmethod
92
+ def from_dict(cls, value):
93
+ if not isinstance(value, dict):
94
+ return cls()
95
+ return cls(**{k: value[k] for k in cls.__dataclass_fields__ if k in value})
96
+
97
+ def to_dict(self):
98
+ return asdict(self)
99
+
100
+
101
+ @dataclass
102
+ class RelayCard:
103
+ identity: list = field(default_factory=list)
104
+ relationship: list = field(default_factory=list)
105
+ open_loops: list = field(default_factory=list)
106
+ recent: list = field(default_factory=list)
107
+ pins: list = field(default_factory=list)
108
+
109
+ @classmethod
110
+ def from_dict(cls, value):
111
+ if not isinstance(value, dict):
112
+ return cls()
113
+ return cls(**{k: value[k] for k in cls.__dataclass_fields__ if k in value})
114
+
115
+ def to_dict(self):
116
+ return asdict(self)
@@ -0,0 +1,26 @@
1
+ # -*- coding: utf-8 -*-
2
+ """Normalization / hash / time helpers (stdlib only)."""
3
+ from __future__ import annotations
4
+ import hashlib, re, time
5
+
6
+
7
+ def sha12(text):
8
+ return hashlib.sha256(str(text).encode("utf-8")).hexdigest()[:12]
9
+
10
+
11
+ def clamp01(value, default=0.0):
12
+ try:
13
+ return max(0.0, min(1.0, float(value)))
14
+ except Exception:
15
+ return default
16
+
17
+
18
+ def normalize_text(text):
19
+ return re.sub(r"\s+", " ", str(text or "")).strip()
20
+
21
+
22
+ def now_ts(now=None):
23
+ try:
24
+ return float(now if now is not None else time.time())
25
+ except Exception:
26
+ return time.time()