web: refresh roster on unknown-thread messages; agent: default to Sonnet (#56)
- chat.js: a WS message for a thread we don't know reloads threads but not the roster, so a first-contact sender (new joiner's DM, a bot's welcome) rendered as "Someone" until a full reload. Refresh the roster there too. - Bots default to claude-sonnet-5 (was Opus) — cheaper, and the default personas don't need deep reasoning; per-bot console config still picks any model. Admin dropdown + README follow.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
5 files changed,
+8
−3
agent/README.md+1 −1agent/config.mjs+1 −1changelog/2026-07-02-someone-label.md+1 −0web/pages/admin.html+1 −1web/static/chat.js+4 −0
diff --git a/agent/README.md b/agent/README.md| index e630335..868ceca 100644 |
| --- a/agent/README.md |
| +++ b/agent/README.md |
| @@ -25,7 +25,7 @@ console, its `#fragment` passed once as the matching `*_INVITE` env var. |
| | `LCHAT_INVITE` | **One-time.** The `#fragment` of a `/join/…` link minted in the admin console (tick "This is an agent"). Spent after provisioning. | |
| Optional: `LCHAT_AGENT_NAME` (default `Claude`), `LCHAT_MODEL` (default |
| -`claude-opus-4-8`; try `claude-sonnet-5` for lower cost), `LCHAT_SYSTEM` (system |
| +`claude-sonnet-5`; try `claude-opus-4-8` when a bot needs deeper reasoning), `LCHAT_SYSTEM` (system |
| prompt), `LCHAT_SESSION` (session-file path). |
| ## Run |
diff --git a/agent/config.mjs b/agent/config.mjs| index 49c501e..db65464 100644 |
| --- a/agent/config.mjs |
| +++ b/agent/config.mjs |
| @@ -12,7 +12,7 @@ export const BASE = (process.env.LCHAT_BASE || "").replace(/\/$/, ""); |
| export const WS_BASE = BASE.replace(/^http/, "ws"); |
| export const AGENT_NAME = process.env.LCHAT_AGENT_NAME || "Claude"; |
| -export const MODEL = process.env.LCHAT_MODEL || "claude-opus-4-8"; |
| +export const MODEL = process.env.LCHAT_MODEL || "claude-sonnet-5"; |
| // Session lives next to this module by default so `node agent.mjs` works from |
| // any cwd; override with LCHAT_SESSION. |
diff --git a/changelog/2026-07-02-someone-label.md b/changelog/2026-07-02-someone-label.md| new file mode 100644 |
| index 0000000..2463b6d |
| --- /dev/null |
| +++ b/changelog/2026-07-02-someone-label.md |
| @@ -0,0 +1 @@ |
| +Fixed: a first-time chat from someone new (like a helper saying hi) no longer shows as "Someone" until you refresh. |
diff --git a/web/pages/admin.html b/web/pages/admin.html| index fdb7bfd..7b433f2 100644 |
| --- a/web/pages/admin.html |
| +++ b/web/pages/admin.html |
| @@ -69,7 +69,7 @@ |
| <input id="agentLabel" placeholder="Bot name (e.g. Claude)" maxlength="60" style="display:block;width:100%;margin:0 0 8px" /> |
| <input id="agentDescription" placeholder="What this helper does, in one line — members see this in the Helpers list" maxlength="200" style="display:block;width:100%;margin:0 0 8px" /> |
| <select id="agentModel" style="display:block;width:100%;margin:0 0 8px"> |
| - <option value="">Default model (Opus)</option> |
| + <option value="">Default model (Sonnet)</option> |
| <option value="claude-opus-4-8">Opus — most capable</option> |
| <option value="claude-sonnet-5">Sonnet — balanced</option> |
| <option value="claude-haiku-4-5">Haiku — fast & cheap</option> |
diff --git a/web/static/chat.js b/web/static/chat.js| index 6b05157..6062ff9 100644 |
| --- a/web/static/chat.js |
| +++ b/web/static/chat.js |
| @@ -2884,6 +2884,10 @@ function connectWS() { |
| // mode the native sidebar owns the other threads and we have no private key to |
| // unwrap them, so ignore anything but the active thread. |
| if (embed) return; |
| + // The sender may be someone we haven't seen either (a new joiner's first DM, |
| + // a bot like Eleven welcoming us) — without a roster refresh they render as |
| + // "Someone" until the next full reload. |
| + await loadRoster(); |
| await loadThreads(); |
| renderThreadList(); |
| return; |