Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
# Changelog

## [0.4.1] - 2026-06-09

### Added
- FTS5 token filter: fixed `detail=column` issue where pure-digit/alpha tokens were parsed as column names (port from Opprime)
- Knowledge auto-retrieval: record_hit() on every auto-search hit for cache warmth
- _recorded_tc: track total tool calls per loop execution for SkillOpt gate integration
- _build_gmem_summary: standalone helper for archive_store compression summary construction
- tools/remember_info.py: unified memory route — auto-classifies user content into Knowledge/Notes/Experience
- tools/archive_search.py: Archive Store search tool for cross-session memory recall

### Changed
- kernel.py: merged Opprime improvements (FTS5 safety filter + Knowledge hit recording + loop tc tracking)
- session.py: synchronized with Opprime (fixes for L1 compaction type mismatch, image_url filtering)
- experience.py: synchronized with Opprime (improved JSON error tolerance)
- storage.py: synchronized with Opprime (aging mechanism for Knowledge entries)
- archive_store.py: generalized agent-specific DB fallback paths to `~/gbase-home/` (public-ready)

### Fixed
- knowledge.py: FTS5 MATCH returning 0 matches due to unpurged detail=column token pollution
- session.py: content null leading to DeepSeek serde enum variant mismatch (400 error)
- session.py: L1 compression type mismatch (passing str instead of list[dict])

## [0.4.0] - 2026-06-02

### Added
Expand All @@ -14,6 +36,18 @@
- L4 permanent notes: auto-serialize when tool calls >= 5 or reply >= 500 chars
- 20+ new tools: self_edit, feishu_send, note_tool, knowledge, mirror_tool, chain, mail, security_watch, etc.

### Added
- ArchiveStore: full-text conversation archive with LIKE-based semantic retrieval (replaces LLM compression)
- Session: removed 3-layer LLM compression, replaced with ArchiveStore append/search
- Territory safety: cross-agent read/write access control (write blocking, read warning)
- RSI Dual-Knob: task intent classification → dynamic temperature control
- Time-decay weighted retrieval: M3 sparse attention inspired (7d full / 7-30d linear / 30d+ exponential)
- Entity conflict detection: Cosmos 3 inspired, auto-detect contradictions on write
- Hot query cache (LRU, max 64) for high-frequency entity lookups
- Archive trash recovery: deleted entries saved to `data/archive_trash/` as grep-able JSONL
- L4 permanent notes: auto-serialize when tool calls >= 5 or reply >= 500 chars
- 20+ new tools: self_edit, feishu_send, note_tool, knowledge, mirror_tool, chain, mail, security_watch, etc.

### Changed
- kernel.py: archive_store init + semantic bridge search/save (disabled old online LLM compression)
- session.py: replaced compress_l1/l2/async_compress with archive-driven context building
Expand Down
1 change: 1 addition & 0 deletions editions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- default identity
- resource requirements
"""

from dataclasses import dataclass, field


Expand Down
1 change: 1 addition & 0 deletions examples/02_quick_chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ async def chat():
response = await kernel.run("Prove you remember: what was my first question?")
print("🤖 GBase:", response)


asyncio.run(chat())
4 changes: 3 additions & 1 deletion examples/03_agent_as_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,7 @@
if __name__ == "__main__":
port = sys.argv[1] if len(sys.argv) > 1 else "8420"
print(f"Starting GBase server on port {port}...")
print(f"Try: curl http://localhost:{port}/ask -X POST -H 'Content-Type: application/json' -d '{{\"message\": \"hi\"}}'")
print(
f"Try: curl http://localhost:{port}/ask -X POST -H 'Content-Type: application/json' -d '{{\"message\": \"hi\"}}'"
)
run(mode="http", port=int(port))
4 changes: 3 additions & 1 deletion examples/03_memory_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
Run it twice. The second time, it will remember our first conversation.
"""


# First conversation — the agent learns something
print("=== Session 1: Teaching ===")
import asyncio
Expand All @@ -17,13 +16,16 @@ async def teach():
print("GBase:", resp)
print("Memory saved! Now run this script again to see if it remembers.")


async def recall():
kernel = GBaseKernel()
resp = await kernel.run("What's my favorite color?")
print("GBase:", resp)


if __name__ == "__main__":
import sys

if "--recall" in sys.argv:
asyncio.run(recall())
else:
Expand Down
6 changes: 5 additions & 1 deletion examples/04_memory_persistence.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,20 @@

async def teach():
kernel = GBaseKernel()
resp = await kernel.run("Remember this fact: the creator of GBase is Gary Lin, and the project was born in Shanghai, 2026.")
resp = await kernel.run(
"Remember this fact: the creator of GBase is Gary Lin, and the project was born in Shanghai, 2026."
)
print("🤖 GBase:", resp)
print("\n✅ Taught! Now run: python3 examples/04_memory_persistence.py recall")


async def recall():
kernel = GBaseKernel()
resp = await kernel.run("Who created you, and where were you born?")
print("🤖 GBase:", resp)
print("\n💡 If it remembers, Mirror Memory is working. If not, check data/mirror.db exists.")


if __name__ == "__main__":
if len(sys.argv) < 2:
print(__doc__)
Expand Down
3 changes: 2 additions & 1 deletion examples/05_rsi_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@ async def rsi_cycle():
print(f"📊 Before: {result.get('score_before', 'N/A')}")
print(f"📊 After: {result.get('score_after', 'N/A')}")

if result.get('rollback'):
if result.get("rollback"):
print("↩️ Agent decided to rollback — changes weren't beneficial")
else:
print("🎉 Agent found genuine improvements!")

print(f"\n🔬 Details: {result.get('details', '')}")


asyncio.run(rsi_cycle())
Loading
Loading