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
+10 -2
View File
@@ -37,6 +37,7 @@ import { api, gitTarget } from "../../lib/api";
import { copyText } from "../../lib/clipboard";
import { useDialog } from "../../hooks/useDialog";
import { dragSkill } from "../../lib/promptAttach";
import { readMarkdownPreview } from "../../lib/markdownView";
import { MarkdownPreview } from "../MarkdownPreview";
import { CodeBlock } from "../conversation/CodeBlock";
import { useTheme } from "../../hooks/useTheme";
@@ -227,6 +228,13 @@ function ArtifactFrame({ kind, text, title }: { kind: ArtifactKind; text: string
type View = "preview" | "code";
/** A file's first tab: Preview where it renders — Markdown as Settings → Appearance says. */
function defaultView(path: string): View {
const kind = artifactKind(path);
if (!RENDERED.has(kind)) return "code";
return kind === "markdown" && !readMarkdownPreview() ? "code" : "preview";
}
function Body({ path, content, view }: { path: string; content: Content; view: View }) {
const { t } = useTranslation("run");
const kind = artifactKind(path);
@@ -320,7 +328,7 @@ export function FilePreview({
const { t } = useTranslation("run");
const kind = artifactKind(path);
const loaded = useContent(path, scope);
const [view, setView] = useState<View>(RENDERED.has(kind) ? "preview" : "code");
const [view, setView] = useState<View>(() => defaultView(path));
const [full, setFull] = useState(false);
const [sharing, setSharing] = useState(false);
const versions = useMemo(
@@ -332,7 +340,7 @@ export function FilePreview({
// Another file opens on its own default tab, at its newest version.
useEffect(() => {
setPicked(null);
setView(RENDERED.has(artifactKind(path)) ? "preview" : "code");
setView(defaultView(path));
}, [path]);
const last = Math.max(versions.length - 1, 0);
const at = picked ?? last;