Server side implementation for interactive entry edits

This commit is contained in:
2024-11-23 15:34:33 +01:00
parent bb74fd3621
commit dbc0068a82
28 changed files with 749 additions and 553 deletions

View File

@@ -1,4 +1,4 @@
from typing import List, Optional
from typing import List, Optional, Callable, Set
import xml.etree.ElementTree as ET
from .entry import Entry
@@ -10,11 +10,34 @@ class WorkingMemory:
The working memory stores different types of entries (scripts, reasoning, errors, etc.)
and provides methods to add, remove, and update them. It also generates XML context
representing the current state.
Notifies observers of entry additions, deletions and changes. During update(),
changes are batched and a single notification is sent after completion.
"""
def __init__(self):
"""Initialize an empty working memory."""
self._entries: List[Entry] = []
self._change_handlers: List[Callable[[], None]] = []
self._updating = False
self._changed_during_update: Set[Entry] = set()
def add_change_handler(self, handler: Callable[[], None]) -> None:
"""Add a callback for working memory changes."""
if handler not in self._change_handlers:
self._change_handlers.append(handler)
def _notify_change(self) -> None:
"""Notify all handlers of working memory changes."""
for handler in self._change_handlers:
handler()
def _handle_entry_change(self, entry: Entry) -> None:
"""Handle changes from individual entries."""
if self._updating:
self._changed_during_update.add(entry)
else:
self._notify_change()
def add_entry(self, entry: Entry) -> None:
"""
@@ -25,7 +48,9 @@ class WorkingMemory:
"""
if not isinstance(entry, Entry):
raise TypeError("Entry must be an instance of Entry class")
entry.add_change_handler(self._handle_entry_change)
self._entries.append(entry)
self._notify_change()
def remove_entry(self, id: str) -> None:
"""
@@ -39,6 +64,7 @@ class WorkingMemory:
if entry is not None:
entry.cleanup()
self._entries = [e for e in self._entries if e.id != id]
self._notify_change()
def clear(self) -> None:
"""
@@ -48,12 +74,11 @@ class WorkingMemory:
for entry in self._entries:
entry.cleanup()
self._entries.clear()
self._notify_change()
def __del__(self):
"""
Clean up all entries when memory is deleted.
"""
if hasattr(self, '_entries'): # Check in case of partial initialization
"""Clean up all entries when memory is deleted."""
if hasattr(self, '_entries'):
self.clear()
def get_entry(self, id: str) -> Optional[Entry]:
@@ -78,7 +103,7 @@ class WorkingMemory:
Returns:
List[Entry]: List of all entries
"""
return self._entries.copy() # Return a copy to prevent external modification
return self._entries.copy()
def get_entries_count(self) -> int:
"""
@@ -88,24 +113,22 @@ class WorkingMemory:
int: Number of entries in working memory
"""
return len(self._entries)
def get_entries_by_type(self, entry_type: type) -> List[Entry]:
"""
Get all entries of a specific type.
Args:
entry_type: Type of entries to retrieve
Returns:
List[Entry]: List of entries matching the specified type
"""
return [e for e in self._entries if isinstance(e, entry_type)]
def update(self) -> None:
"""Update all entries in working memory."""
"""
Update all entries in working memory.
Batches change notifications and sends single update after completion.
"""
self._updating = True
self._changed_during_update.clear()
for entry in self._entries:
entry.update()
self._updating = False
if self._changed_during_update:
self._notify_change()
def generate_context(self) -> List[ET.Element]:
"""
Generate XML Elements representing all entries.
@@ -113,4 +136,4 @@ class WorkingMemory:
Returns:
List[ET.Element]: List of XML elements for each entry
"""
return [entry.generate_context() for entry in self._entries]
return [entry.generate_context() for entry in self._entries]