feat: v2.8.0 — Artifacts uploads and plugin links, console tab combos, account avatars

- Artifacts hub: upload a file from the computer; make a skill by uploading a
  Markdown file, files, a folder or a .zip/.skill, or by writing it in the
  dialog; add plugins by picking from the list a marketplace link answers
  (POST /api/artifacts/plugin/inspect); Settings → AI tools → Artifacts Hub.
- Console tabs are combos of up to four split panes (ConsoleTabs, PaneGrid).
- Accounts: an own avatar (PUT/DELETE /api/me/avatar, raster only, ≤ 1 MB,
  <data dir>/avatars/), shown with name and role at the sidebar's foot and on
  the workspace owner groups (GET /api/users/:id/avatar, owner_avatar_at).
- Users page: per-user storage (GET /api/users/storage, measured in a worker)
  and account-pool spend/tokens per account (server/lib/pool-usage.js).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-14 17:21:33 +07:00
parent 8ed5018a2f
commit 7a88b74016
63 changed files with 3833 additions and 354 deletions
+3
View File
@@ -142,6 +142,8 @@ const publicUser = (u) =>
disabled: Boolean(u.disabled),
displayName: u.display_name ?? null,
email: u.email ?? null,
// When the avatar was last set (null = none): the client's cache-buster.
avatarAt: u.avatar_at ?? null,
createdAt: u.created_at ?? null,
};
@@ -349,6 +351,7 @@ function deleteUser(username) {
const lanesLib = require("./lanes");
for (const lane of lanes) lanesLib.deleteLane(lane.id);
sql("DELETE FROM user_prefs WHERE user_key = ?").run(`u${u.id}`);
require("./avatars").removeAvatar(u.id);
try {
sql("DELETE FROM push_subscriptions WHERE user_id = ?").run(u.id);
} catch {