chore: v2.8.15 — Oh My Pi login sharing, omp --allow-home, Markdown Preview default, first-login password

- omp-share.js: an admin's switch (S3) runs omp's own auth broker + gateway as
  the host on loopback; a member's omp pane reaches it as a scoped client keyed
  by its pane token (clients file = live omp panes only), runs on
  --model agenthub/<model>, never holds a credential.
- omp catalog: --allow-home, so a workspace at the account's home keeps its
  sessions there (they were recorded under a temp dir and dropped).
- Settings → Appearance → Open Markdown as: Preview (default) or Raw, for
  Files/Changes, the config viewer and a chat's file panel.
- First-login password change and password rules, avatar URLs, Artifacts
  "Mine" includes installed shared skills/plugins, a member's own hook pages.
This commit is contained in:
2026-10-22 10:04:30 +07:00
parent 8a6dc6a29e
commit 750d74a2af
66 changed files with 3021 additions and 696 deletions
+23
View File
@@ -733,6 +733,8 @@ export type AuthUser = {
/** When the account's avatar was last set (null = none) — versions its URL. */
avatarAt?: string | null;
createdAt?: string;
/** An admin gave this password: the user must choose their own before anything else. */
mustChangePassword?: boolean;
};
export type AuthState = { mode: "local" } | { mode: "server"; user: AuthUser | null };
/** GET /api/me/prefs — the signed-in account's own UI preferences (localStorage keys). */
@@ -1007,6 +1009,9 @@ export const api = {
body: file,
headers: { "Content-Type": "application/octet-stream" },
}),
/** POST /api/me/avatar/url — the server downloads the picture from an https link. */
setAvatarFromUrl: (url: string) =>
request<MyAccount>("/me/avatar/url", { method: "POST", body: JSON.stringify({ url }) }),
/** DELETE /api/me/avatar — back to the initials. */
removeAvatar: () => request<MyAccount>("/me/avatar", { method: "DELETE" }),
},
@@ -3051,6 +3056,14 @@ export const api = {
aiTools: {
/** GET /api/ai-tools - the catalog, what is installed, enabled, and the default. */
list: () => request<AiToolsView>("/ai-tools"),
/** GET /api/ai-tools/omp-sharing - the host's Oh My Pi login shared with members (S3). */
ompSharing: () => request<OmpSharingState>("/ai-tools/omp-sharing"),
/** PUT /api/ai-tools/omp-sharing - an admin's switch. */
setOmpSharing: (enabled: boolean) =>
request<OmpSharingState>("/ai-tools/omp-sharing", {
method: "PUT",
body: JSON.stringify({ enabled }),
}),
/** POST /api/ai-tools/refresh - re-read the login shell's PATH and re-detect. */
refresh: () => request<AiToolsView>("/ai-tools/refresh", { method: "POST" }),
/** PUT /api/ai-tools/:id - enable/disable a tool, make it the default, or set its default model ("" clears). */
@@ -4307,6 +4320,16 @@ export interface ArtifactCandidate {
pinned: boolean;
}
/** `GET /api/ai-tools/omp-sharing` — never a token. */
export interface OmpSharingState {
/** Server mode with per-user Linux accounts (S3): the only place it applies. */
available: boolean;
enabled: boolean;
installed: boolean;
broker: { running: boolean; error?: string | null };
gateway: { running: boolean; port?: number; error?: string | null };
}
export interface ArtifactSettings {
serverMode: boolean;
canShare: boolean;