feat: per-conversation project binding + action-tool consent gate
- Conversations bind to a project on creation; RAG scopes to the conversation's project, not the global setting. - Action tools (web_search/fetch_url/remember) are withheld unless allow_action_tools is enabled (off by default). Settings toggle. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+21
-3
@@ -140,6 +140,11 @@ class PersistentMemoryStore:
|
||||
cur.execute("ALTER TABLE conversations ADD COLUMN title TEXT")
|
||||
except Exception:
|
||||
pass
|
||||
# Migrate: bind a conversation to a project ("" = unscoped).
|
||||
try:
|
||||
cur.execute("ALTER TABLE conversations ADD COLUMN project_id TEXT NOT NULL DEFAULT ''")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
cur.execute("""
|
||||
CREATE TABLE IF NOT EXISTS messages (
|
||||
@@ -364,20 +369,30 @@ class PersistentMemoryStore:
|
||||
# -----------------------------
|
||||
# Conversation API
|
||||
# -----------------------------
|
||||
def create_conversation(self, conversation_id: str) -> ConversationItem:
|
||||
def create_conversation(self, conversation_id: str, project_id: str = "") -> ConversationItem:
|
||||
now = time.time()
|
||||
conn = self._connect()
|
||||
try:
|
||||
cur = conn.cursor()
|
||||
cur.execute(
|
||||
"INSERT OR IGNORE INTO conversations (id, created_at, updated_at) VALUES (?, ?, ?)",
|
||||
(conversation_id, now, now)
|
||||
"INSERT OR IGNORE INTO conversations (id, created_at, updated_at, project_id) VALUES (?, ?, ?, ?)",
|
||||
(conversation_id, now, now, project_id or "")
|
||||
)
|
||||
conn.commit()
|
||||
finally:
|
||||
conn.close()
|
||||
return ConversationItem(id=conversation_id, created_at=now, updated_at=now)
|
||||
|
||||
def conversation_project(self, conversation_id: str) -> Optional[str]:
|
||||
"""The conversation's bound project ('' = unscoped), or None if it doesn't
|
||||
exist yet — lets a new chat inherit the current workspace."""
|
||||
conn = self._connect()
|
||||
row = conn.execute(
|
||||
"SELECT project_id FROM conversations WHERE id = ?", (conversation_id,)
|
||||
).fetchone()
|
||||
conn.close()
|
||||
return None if row is None else (row["project_id"] or "")
|
||||
|
||||
def set_conversation_title(self, conversation_id: str, title: str):
|
||||
conn = self._connect()
|
||||
try:
|
||||
@@ -983,6 +998,9 @@ class PersistentMemoryStore:
|
||||
"rag_min_score": 0.6,
|
||||
# Active project/workspace; "" = all documents (unscoped).
|
||||
"active_project": "",
|
||||
# Consent gate for tools that act (web_search/fetch_url/remember). Off by
|
||||
# default: a playbook can list them, but they only run when this is on.
|
||||
"allow_action_tools": False,
|
||||
"system_prompt": "",
|
||||
"timeout": 120,
|
||||
# How long Ollama keeps the model resident in VRAM between messages.
|
||||
|
||||
Reference in New Issue
Block a user