Feat v0.5.2 chat surface

Chat surface package (packages/chat/) with conversation list, message
thread, compose bar, participant sidebar, create conversation dialog,
typing indicators, read receipts, message editing, and message deletion.
Built on chat-core library with realtime event subscriptions.

Fix stale token login deadlock: REST client auth endpoints excluded
from 401 retry loop, 8s defensive boot timeout on auth.boot().

Fix bundled package permissions: auto-grant with NULL granted_by and
set status active on install.

Switch docker-compose to named volume for remote Docker host compat.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-30 14:48:18 +00:00
parent 7155aaf663
commit a0cd724d35
12 changed files with 1476 additions and 20 deletions

39
packages/chat/script.star Normal file
View File

@@ -0,0 +1,39 @@
# Chat Surface — Starlark Backend (v0.1.0)
#
# Thin surface layer on top of chat-core library.
# Only handles typing indicator broadcast — all CRUD is
# delegated to chat-core's own API routes.
#
# Modules: json, realtime
def _resp(status, data):
return {"status": status, "body": json.encode(data), "headers": {"Content-Type": "application/json"}}
def on_request(req):
path = req["path"]
method = req["method"]
user_id = req.get("user_id", "")
# POST /typing/:conversation_id — broadcast typing indicator
if method == "POST" and path.startswith("/typing/"):
cid = path[len("/typing/"):]
if not cid:
return _resp(400, {"error": "conversation_id required"})
body = json.decode(req.get("body", "{}"))
display_name = str(body.get("display_name", ""))
realtime.publish(
"conversation:" + cid,
"typing",
{
"participant_id": user_id,
"display_name": display_name,
"conversation_id": cid,
},
)
return _resp(200, {"ok": True})
return _resp(404, {"error": "not found"})