Files
nesquena-hermes e061e8534c Rebase #5337 (public read-only conversation sharing) onto master
Rebased 363 commits forward (branch-point 2026-07-05). Applied the PR's code
diff cleanly across 16 files; resolved api/models.py additively (both master's
process_wakeup_pause/anchor_scene_index fields AND the PR's share_token/
share_created_at fields kept in the Session constructor, metadata list, and
to_dict). CI workflow (.github/workflows/tests.yml) intentionally NOT taken from
the stale branch — master owns it (the branch's apparent removal of Playwright/
Office steps was a PAT-workflow-scope revert; rebase restores master's CI).

Co-authored-by: MicoRobot. Concept approved by maintainer (opt-in public share,
2026-07-11). Note: 4 dynamic share tests fail identically on the original
unrebased head (pre-existing test-env Session.load fragility, not rebase-caused);
to be resolved during the security re-gate in a proper sandbox.
2026-07-11 01:39:42 +00:00

83 lines
6.9 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Shared Conversation - Hermes</title>
<meta name="robots" content="noindex,nofollow,noarchive">
<meta name="referrer" content="same-origin">
<script>(function(){try{var themes={light:1,dark:1,system:1},skins={codex:1,terracotta:1,default:1,ares:1,mono:1,graphite:1,github:1,slate:1,poseidon:1,sisyphus:1,charizard:1,sienna:1,catppuccin:1,hepburn:1,nous:1,'geist-contrast':1,neon:1,zeus:1,'verdigris':1},legacy={slate:['dark','slate'],solarized:['dark','poseidon'],monokai:['dark','sisyphus'],nord:['dark','slate'],oled:['dark','default']},t=(localStorage.getItem('hermes-theme')||'dark').toLowerCase(),s=(localStorage.getItem('hermes-skin')||'').toLowerCase(),m=legacy[t],theme=m?m[0]:(themes[t]?t:'dark');var pendingExt=s&&s!=='default'&&!skins[s]&&!legacy[s];var skin=skins[s]?s:(pendingExt?s:(m?m[1]:'default'));localStorage.setItem('hermes-theme',theme);localStorage.setItem('hermes-skin',skin);if(theme==='system')theme=window.matchMedia('(prefers-color-scheme:dark)').matches?'dark':'light';if(theme==='dark')document.documentElement.classList.add('dark');if(skin!=='default')document.documentElement.dataset.skin=skin;}catch(e){document.documentElement.classList.add('dark');}})()</script>
<link rel="stylesheet" href="/static/style.css">
<style>
html,body{height:auto;min-height:100%}
body{overflow-y:auto;overflow-x:hidden;display:block}
.share-shell{min-height:100vh;background:var(--bg);color:var(--text);}
.share-topbar{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:18px 22px;border-bottom:1px solid var(--border);background:var(--sidebar);position:sticky;top:0;z-index:10}
.share-brand{display:flex;align-items:center;gap:10px;min-width:0}
.share-brand-title{font-size:13px;font-weight:700;color:var(--text);letter-spacing:.01em}
.share-brand-sub{font-size:11px;color:var(--muted)}
.share-actions{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.share-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;padding:10px 14px;border-radius:10px;border:1px solid var(--border);background:var(--surface);color:var(--text);font-size:13px;font-weight:500;cursor:pointer;transition:background .15s,border-color .15s,color .15s;text-decoration:none}
.share-btn:hover{background:var(--accent-bg);border-color:var(--accent-bg-strong);color:var(--accent-text)}
.share-btn:disabled{opacity:.45;cursor:not-allowed}
.share-wrap{width:min(920px,calc(100vw - 32px));margin:0 auto;padding:28px 0 72px}
.share-hero{padding:6px 0 18px}
.share-kicker{display:inline-flex;align-items:center;gap:8px;padding:6px 10px;border-radius:999px;background:var(--surface);border:1px solid var(--border2);font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.08em}
.share-title{margin:16px 0 10px;font-size:32px;line-height:1.1;letter-spacing:-.02em;color:var(--strong,var(--text))}
.share-meta{font-size:13px;color:var(--muted);line-height:1.6}
.share-transcript{margin-top:22px;padding:18px 18px 8px;border:1px solid var(--border);border-radius:18px;background:linear-gradient(180deg,color-mix(in srgb,var(--surface) 88%,transparent),color-mix(in srgb,var(--sidebar) 94%,transparent))}
.share-empty,.share-error{padding:40px 16px;text-align:center;color:var(--muted)}
.share-error strong{color:var(--text)}
.share-message{padding:14px 0 18px;border-top:1px solid color-mix(in srgb,var(--border) 78%,transparent)}
.share-message:first-child{border-top:none;padding-top:4px}
.share-role{display:flex;align-items:center;gap:10px;font-size:11px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin-bottom:10px}
.share-role-badge{display:inline-flex;align-items:center;justify-content:center;min-width:26px;height:26px;padding:0 8px;border-radius:999px;border:1px solid var(--border2);background:var(--surface-subtle);color:var(--text)}
.share-message[data-role="user"] .share-role-badge{background:var(--accent-bg);border-color:var(--accent-bg-strong);color:var(--accent-text)}
.share-message-body{padding-left:0;max-width:none}
.share-foot{margin-top:18px;padding-top:18px;border-top:1px solid var(--border);font-size:12px;color:var(--muted);line-height:1.7}
@media (max-width: 720px){
.share-topbar{padding:14px 14px 12px;align-items:flex-start;flex-direction:column}
.share-wrap{width:min(100vw - 20px,920px)}
.share-title{font-size:26px}
.share-transcript{padding:14px 14px 6px;border-radius:16px}
.share-actions{width:100%}
.share-btn{flex:1 1 180px}
}
</style>
</head>
<body>
<div class="share-shell">
<header class="share-topbar">
<div class="share-brand">
<span class="app-titlebar-icon" aria-hidden="true">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="18" height="18" aria-hidden="true"><defs><linearGradient id="share-mark" x1="0" y1="0" x2="1" y2="0"><stop offset="0" stop-color="#08EBF1"/><stop offset="1" stop-color="#3889FD"/></linearGradient><radialGradient id="share-tile" cx="50%" cy="42%" r="75%"><stop offset="0%" stop-color="#0D3460"/><stop offset="100%" stop-color="#021128"/></radialGradient></defs><rect width="64" height="64" rx="14.3" fill="url(#share-tile)"/><g transform="translate(-8.632 -11.731) scale(0.06483)"><path fill="url(#share-mark)" fill-rule="evenodd" d="M630.5 961.9 C634.9 960.7 638.5 957.9 640.5 953.9 C642.5 950.1 643.3 865.1 641.4 864.3 C640 863.8 623.9 872.5 618.2 876.8 C616.4 878.2 613.8 881.2 612.5 883.5 L610 887.7 610 918.4 C610 951.8 610.2 953.1 615.7 958.3 C618.3 960.8 622.4 962.7 625.5 962.9 C626 963 628.3 962.5 630.5 961.9 Z"/></g></svg>
</span>
<div>
<div class="share-brand-title">Hermes Shared Conversation</div>
<div class="share-brand-sub">Read-only snapshot</div>
</div>
</div>
<div class="share-actions">
<button class="share-btn" id="shareCopyBtn" type="button">Copy link</button>
<a class="share-btn" href="/" id="shareHomeLink">Open Hermes</a>
</div>
</header>
<main class="share-wrap">
<section class="share-hero">
<div class="share-kicker">Public share</div>
<h1 class="share-title" id="shareTitle">Loading...</h1>
<div class="share-meta" id="shareMeta">Fetching shared conversation...</div>
</section>
<section class="share-transcript" id="shareTranscript">
<div class="share-empty">Loading shared conversation...</div>
</section>
<div class="share-foot">
This link shows a read-only snapshot prepared by Hermes WebUI. It does not expose the original workspace browser, profile settings, or live session controls.
</div>
</main>
</div>
<script src="/static/ui.js"></script>
<script src="/static/share.js"></script>
</body>
</html>