A bot's or workspace's picture was only shared when its media row carried
the bot-image or workspace-image paradigm. A picture set before pictures
were copied into their own row points at the chat upload itself, so only
its uploader could load it and everyone else saw the default icon. A
picture is now shared because a bot or workspace points at it, whatever
its paradigm; profile photos still have to be the user's primary one.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A profile photo, a bot's picture and a workspace's picture all come from
one condition now (sharedPictureMediaSql), so a face is never blank just
because its owner isn't in the viewer's rail. Anything that isn't a
picture stays behind its own check.
A bot's identity was one of seven hues, and the hue picked both its colour
and its stone shape. Now its colour is free and its stone is its own:
- `bots.color` holds any `#rrggbb`, `bots.stone` the flat-cut shape it's
drawn on. `bots.hue` stays as the palette column they replaced, read only
as a fallback; `src/scripts/move-bot-colour-to-owners.ts` backfills an
install from it (safe to rerun).
- `src/utils/bot-color.ts` is the only place a colour is validated or
resolved (`resolveBotColor`/`resolveBotStone` carry the old hue forward,
`botColorNeedsPaperFace` flips the eyes to paper on a very dark body), and
`src/utils/bot-stone-props.ts` gives every row its props, so a row saved
before this still renders as it did.
- `BotStone` takes the colour as the body's SVG `fill`, the one documented
exception to the token rule: an arbitrary hex has no token to point at.
`UnreadDot` follows it.
- The picker keeps the palette tiles (still shape and colour together) and
adds a native swatch and a hex field, so a custom colour keeps its stone.
Same place as before: the header avatar's modal and Settings > Bots, for
crew managers. The coordinator stays hue-less.
- A recolour reaches other open tabs through `pushBotUpdated`.
Take the Bots and Workspaces pickers out of the user form. A user's
settings page lists what they reach in two groups, like a workspace's
Bots group: each row links to its settings and can be taken away, and
a select adds one, saved straight away through users/add-access and
users/remove-access (setUserGrant).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
create_workspace gives the coordinator a way to start a workspace with its shared context, and the tool list is shared, so a new id can be used by create_bot or add_bot_to_workspace in the same reply.
A coordinator's tasks now get create_workspace and update_workspace too: the research task that had the material could only report it, never write it into the workspace, so the coordinator promised an update it had no turn to make.
A workspace created from chat is pushed as server:workspace-created, from the tool and from the live relay, so the rail shows it without a reload.
Bots, workspaces and computers now belong to the install. Users reach
workers only through bot_users (assigned by a super admin or admin) and
workspace_users; the coordinator and main computer are one per install,
and only the super admin sees the coordinator. Conversations are per
user (bot_sessions.user_id), jobs run for the session's user, and live
updates go only to who should see them.
A bot's core memory is now general knowledge shared by every user it
works for; what it learns about a user lives in bot_user_memories.
One-off scripts move existing installs over: move-bot-memory-to-owners
(run first), then share-crew.
Co-Authored-By: Claude Opus 5.5 <[email protected]>