Data groups: a provider's models read only their own group's data
Every connection is in a data group. Its models are handed, and can find, only that group's memories, notes, skills, knowledge, reports and personality -- by search and by id. A chat stays in the group it was started in: switching its model, the endpoint fallback, the crowd, friends, bases and the @ menu all stay inside it, and a chat whose model has moved is refused rather than sent. A group may name its own embedder and image reviewer. data.manage lets a person make personal groups, remap connections for themselves and move their own records. Also: a search no longer mixes two embedders of the same width. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -261,6 +261,10 @@ def authored_sideways() -> tuple[str, ...]:
|
||||
return tuple(selectors)
|
||||
|
||||
|
||||
# The chat `build_client` seeds, so a run can name `/chat/<SHOOT_CHAT>`.
|
||||
SHOOT_CHAT = "5" * 32
|
||||
|
||||
|
||||
def build_client():
|
||||
import lembas.config as config_mod
|
||||
|
||||
@@ -293,6 +297,45 @@ def build_client():
|
||||
for name in ("gemma4-moe", "qwen3-coder"):
|
||||
db.add(Model(connection_id=connection.id, model_id=name, display_name=name))
|
||||
|
||||
# A second data group with a hosted model in it, a note in each group and a
|
||||
# chat with a fixed id (`SHOOT_CHAT`). Without them every grouped screen --
|
||||
# the chips, the Data tab, the models named under the picker as being in
|
||||
# another group -- is rendered with nothing in it, which is the "a screen the
|
||||
# test never renders is unchecked" lesson again.
|
||||
from lembas.db.models import Chat, DataGroup, Note, User
|
||||
|
||||
with session_scope() as db:
|
||||
db.add(DataGroup(id="hosted", name="Hosted providers"))
|
||||
hosted = Connection(
|
||||
name="hosted",
|
||||
base_url="http://127.0.0.1:2",
|
||||
api_key_encrypted="",
|
||||
data_group_id="hosted",
|
||||
)
|
||||
db.add(hosted)
|
||||
db.flush()
|
||||
db.add(
|
||||
Model(
|
||||
connection_id=hosted.id,
|
||||
model_id="deepseek-flash",
|
||||
display_name="DeepSeek Flash",
|
||||
)
|
||||
)
|
||||
owner = db.query(User).first()
|
||||
db.add(Note(owner_id=owner.id, title="A note at home", body="x", data_group_id="default"))
|
||||
db.add(Note(owner_id=owner.id, title="A hosted note", body="x", data_group_id="hosted"))
|
||||
local = db.query(Connection).filter_by(name="local").first()
|
||||
db.add(
|
||||
Chat(
|
||||
id=SHOOT_CHAT,
|
||||
user_id=owner.id,
|
||||
model_id="gemma4-moe",
|
||||
connection_id=local.id,
|
||||
data_group_id="default",
|
||||
title="A chat to measure",
|
||||
)
|
||||
)
|
||||
|
||||
# 🚨 The suggestion cards are seeded by the startup hook, and `TestClient(app)`
|
||||
# runs a lifespan only inside a `with` block -- so every shot of the new-chat
|
||||
# screen ever taken by this script was of a page with its cards missing. That
|
||||
|
||||
Reference in New Issue
Block a user