feat(chat): save by default + share anonymously — auto-saved chats, guest-facing Share, success toast, action row
This commit is contained in:
@@ -6,7 +6,10 @@ styles.css so a silent regression (key rename, dropped try/catch, missing
|
||||
restore, New chat control lost) is caught without a browser.
|
||||
|
||||
Pinned design (PLAN §7.4 note / phase 14):
|
||||
* versioned key ``bor.chat.v1`` → ``{v: 1, messages: [...]}``, raw text only;
|
||||
* versioned key ``bor.chat.v1`` → ``{v: 1, chatId: string | null,
|
||||
messages: [...]}`` (phase 55 A2: the shape extends IN PLACE with the
|
||||
saved_chats row link — a pre-55 record without it reads as null),
|
||||
raw text only;
|
||||
* save points: user message on send, brain message on ``done``;
|
||||
* every ``localStorage`` access wrapped in try/catch (failure-safe);
|
||||
* size budget ~700k chars, oldest dropped first;
|
||||
@@ -45,13 +48,28 @@ def _index() -> str:
|
||||
|
||||
def test_versioned_storage_key_and_v1_payload() -> None:
|
||||
"""`bor.chat.v1` (versioned — a format bump is a clean start) with the
|
||||
{v, messages} payload shape (A11: raw localStorage JSON, no library)."""
|
||||
{v, chatId, messages} payload shape (A11: raw localStorage JSON, no
|
||||
library). Phase 55 (A2): the shape extends IN PLACE with `chatId` —
|
||||
the saved_chats row link (null when unlinked), so a reload restores
|
||||
the conversation AND its link; the trimToBudget size probe measures
|
||||
the same shape."""
|
||||
js = _js()
|
||||
assert 'const STORAGE_KEY = "bor.chat.v1"' in js
|
||||
assert "export const STORAGE_VERSION = 1" in js
|
||||
# The payload written to the key is always {v: STORAGE_VERSION, messages}
|
||||
# (two write paths: saveConversation and the trimToBudget size probe).
|
||||
assert js.count("v: STORAGE_VERSION, messages") >= 2
|
||||
# The write carries the version, the row link, and the trimmed
|
||||
# messages (the single write path — saveConversation).
|
||||
save_start = js.find("function saveConversation")
|
||||
save_body = js[save_start : js.find("\n}\n", save_start)]
|
||||
assert "v: STORAGE_VERSION" in save_body
|
||||
assert "chatId: currentChatId" in save_body, (
|
||||
"phase 55: the link is written with the record (null when unlinked)"
|
||||
)
|
||||
assert "trimToBudget(conversation)" in save_body
|
||||
# The size probe measures the same shape (the link is a fixed-length
|
||||
# field — null stands in for the size estimate).
|
||||
probe_start = js.find("function trimToBudget")
|
||||
probe = js[probe_start : js.find("\n}\n", probe_start)]
|
||||
assert "v: STORAGE_VERSION" in probe and "chatId: null" in probe
|
||||
# Restore validates the version before trusting anything.
|
||||
assert "data.v !== STORAGE_VERSION" in js
|
||||
|
||||
|
||||
Reference in New Issue
Block a user