legion: rename My Booth -> My Legion, Mansion -> My Mansion (1.0.0)
Route 'legion' with a legacy '#/booth' alias; BoothDashboard -> LegionDashboard; nav, footer, hotspots, WebMCP enum, gate copy all renamed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
80d7140d1f
commit
c2a8616255
@ -1 +0,0 @@
|
||||
{"sessionId":"17e654e8-7dd5-4856-85c5-0cfeb7ab736b","pid":3488121,"procStart":"252909119","acquiredAt":1781038486936}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "amerc-site",
|
||||
"version": "0.99.0-boothform",
|
||||
"version": "1.0.0-legion",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@ -34,8 +34,8 @@ export default function Account({ auth, setRoute }) {
|
||||
<p className="acct-email">{u.email}</p>
|
||||
<span className={`acct-role acct-role-${u.role}`}>{u.role}</span>
|
||||
<div className="acct-links">
|
||||
<button className="px-action" onClick={() => setRoute('booth')}>My Booth</button>
|
||||
<button className="px-action" onClick={() => setRoute('mansion')}>Mansion</button>
|
||||
<button className="px-action" onClick={() => setRoute('legion')}>My Legion</button>
|
||||
<button className="px-action" onClick={() => setRoute('mansion')}>My Mansion</button>
|
||||
<button className="px-action" onClick={() => auth.logout()}>Log out</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -96,11 +96,11 @@ export function AgentBrowse({ auth, setRoute }) {
|
||||
</button>
|
||||
))}
|
||||
{loaded && classes.length > 0 && (
|
||||
<button className="ap-card ap-card-add" onClick={() => setRoute('booth')}>
|
||||
<button className="ap-card ap-card-add" onClick={() => setRoute('legion')}>
|
||||
<span className="ap-add-plus" aria-hidden="true">+</span>
|
||||
<strong>Publish your own</strong>
|
||||
<p>Register an agent class and run it from your booth — your mercenary joins the roster right here.</p>
|
||||
<span className="ap-add-cta">Open My Booth →</span>
|
||||
<p>Register an agent class and field it from your legion — your mercenary joins the roster right here.</p>
|
||||
<span className="ap-add-cta">Open My Legion →</span>
|
||||
</button>
|
||||
)}
|
||||
{loaded && !classes.length && (q || tag) && (
|
||||
@ -115,11 +115,11 @@ export function AgentBrowse({ auth, setRoute }) {
|
||||
<div className="ap-empty-start">
|
||||
<h3>No agents here yet — be the first.</h3>
|
||||
<ol>
|
||||
<li><b>Publish a class</b> in <button className="ap-link" onClick={() => setRoute('booth')}>My Booth</button> — name it, tag it (e.g. <code>backend</code>, <code>model</code>).</li>
|
||||
<li><b>Publish a class</b> in <button className="ap-link" onClick={() => setRoute('legion')}>My Legion</button> — name it, tag it (e.g. <code>backend</code>, <code>model</code>).</li>
|
||||
<li><b>Run an instance</b> — your broker connects and it goes <span style={{ color: STATUS_COLOR.online }}>online</span>.</li>
|
||||
<li><b>Use it</b> — embed it as a chatbox or drive it through a web terminal.</li>
|
||||
</ol>
|
||||
<button className="px-action" onClick={() => setRoute('booth')}>Open My Booth →</button>
|
||||
<button className="px-action" onClick={() => setRoute('legion')}>Open My Legion →</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@ -166,7 +166,7 @@ function ClassModal({ id, auth, onClose }) {
|
||||
<button className="px-action" disabled={i.status !== 'online'} onClick={() => setUse(i)}>Use ▸</button>
|
||||
</div>
|
||||
))}
|
||||
{!data.instances.length && <p className="ap-hint">No instances published. The owner can publish one in My Booth.</p>}
|
||||
{!data.instances.length && <p className="ap-hint">No instances published. The owner can field one in My Legion.</p>}
|
||||
</div>
|
||||
{use && <UsePanel instance={use} onClose={() => setUse(null)} />}
|
||||
</div>
|
||||
@ -224,7 +224,7 @@ export function UsePanel({ instance, onClose }) {
|
||||
);
|
||||
}
|
||||
|
||||
// ---- My Booth: publish classes + instances, manage ------------------------
|
||||
// ---- My Legion: publish classes + instances, manage ------------------------
|
||||
export function KeysCard() {
|
||||
const [keys, setKeys] = useState([]);
|
||||
const [name, setName] = useState('');
|
||||
@ -267,7 +267,7 @@ export function KeysCard() {
|
||||
);
|
||||
}
|
||||
|
||||
export function BoothDashboard({ auth, setRoute }) {
|
||||
export function LegionDashboard({ auth, setRoute }) {
|
||||
const [classes, setClasses] = useState([]);
|
||||
const [insts, setInsts] = useState([]);
|
||||
const [err, setErr] = useState('');
|
||||
@ -296,7 +296,7 @@ export function BoothDashboard({ auth, setRoute }) {
|
||||
if (!auth.user) return (
|
||||
<div className="ap ap-gate ap-gate-rich">
|
||||
<span className="ap-gate-ico" aria-hidden="true">🗡️</span>
|
||||
<h2>Your booth awaits</h2>
|
||||
<h2>Your legion awaits</h2>
|
||||
<p>Log in to publish agent classes, run instances, and put your mercenaries to work — as an embedded chatbox, a live web terminal, or behind a public URL.</p>
|
||||
<div className="ap-gate-cta">
|
||||
<button className="gm-cta-btn gm-cta-primary" onClick={() => setRoute('signin')}>Log in / Sign up</button>
|
||||
@ -318,7 +318,7 @@ export function BoothDashboard({ auth, setRoute }) {
|
||||
|
||||
return (
|
||||
<div className="ap">
|
||||
<div className="ap-head"><h2>My Booth</h2><span className="ap-by">{auth.user.handle}</span></div>
|
||||
<div className="ap-head"><h2>My Legion</h2><span className="ap-by">{auth.user.handle}</span></div>
|
||||
{err && <p className="px-auth-err">{err}</p>}
|
||||
<div className="ap-booth-grid">
|
||||
<form className="ap-publish" onSubmit={publishClass}>
|
||||
@ -358,12 +358,12 @@ export function BoothDashboard({ auth, setRoute }) {
|
||||
) : !classes.length ? (
|
||||
<div className="ap-booth-welcome">
|
||||
<span className="ap-booth-welcome-ico" aria-hidden="true">🗡️</span>
|
||||
<h3>Welcome to your booth, {auth.user.handle}.</h3>
|
||||
<h3>Welcome to your legion, {auth.user.handle}.</h3>
|
||||
<p>This is where you arm and dispatch your mercenaries. Three steps to go live:</p>
|
||||
<ol>
|
||||
<li><b>Publish a class</b> — name your agent and tag its skills, in the form on the left.</li>
|
||||
<li><b>Run an instance</b> — your broker connects and it turns <span className="ap-on-word">online</span>.</li>
|
||||
<li><b>Deliver it</b> — embed a chatbox, drive a web terminal, or expose a local port via the <b>Mansion</b>.</li>
|
||||
<li><b>Deliver it</b> — embed a chatbox, drive a web terminal, or expose a local port via <b>My Mansion</b>.</li>
|
||||
</ol>
|
||||
<p className="ap-hint">Your broker authenticates with an instance accesskey (shown when you publish one) or an agent key — mint one below.</p>
|
||||
</div>
|
||||
|
||||
@ -12,7 +12,7 @@ export default function Mansion({ auth, setRoute }) {
|
||||
<header className="mn-hero">
|
||||
<div className="mn-hero-emblem" aria-hidden="true">🏰</div>
|
||||
<div className="mn-hero-body">
|
||||
<h2>The Mansion</h2>
|
||||
<h2>My Mansion</h2>
|
||||
<p>A hall of amerc services that put your work on the open internet — each lives behind amerc's edge and is brought to life by your own broker. No servers to rent, no ports to forward.</p>
|
||||
{loggedIn
|
||||
? <span className="mn-hero-you"><i className="mn-live-dot" /> {auth.user.handle}'s rooms are open</span>
|
||||
@ -30,7 +30,7 @@ export default function Mansion({ auth, setRoute }) {
|
||||
<SoonRoom
|
||||
ico="🤖" name="Hosted webagent" tag="runtime"
|
||||
desc="Let amerc host the broker for you — keep an agent class always-on without leaving your own machine running."
|
||||
feats={['always-on instances', 'managed runtime', 'one-click from My Booth']}
|
||||
feats={['always-on instances', 'managed runtime', 'one-click from My Legion']}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useAuth, AuthPanel, AdminConsole } from './Auth.jsx';
|
||||
import { AgentBrowse, BoothDashboard } from './AgentPlatform.jsx';
|
||||
import { AgentBrowse, LegionDashboard } from './AgentPlatform.jsx';
|
||||
import Mansion from './Mansion.jsx';
|
||||
import Account from './Account.jsx';
|
||||
import TavernGame from './TavernGame.jsx';
|
||||
@ -10,25 +10,26 @@ import { api } from './api.js';
|
||||
const Menu = ({ size = 20 }) => (<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" aria-hidden="true"><line x1="3" y1="6" x2="21" y2="6" /><line x1="3" y1="12" x2="21" y2="12" /><line x1="3" y1="18" x2="21" y2="18" /></svg>);
|
||||
const X = ({ size = 20 }) => (<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" aria-hidden="true"><line x1="18" y1="6" x2="6" y2="18" /><line x1="6" y1="6" x2="18" y2="18" /></svg>);
|
||||
|
||||
const RELEASE = '0.99.0-boothform';
|
||||
const RELEASE = '1.0.0-legion';
|
||||
|
||||
const NAV = [
|
||||
{ id: 'home', label: 'Tavern' },
|
||||
{ id: 'agents', label: 'Browse Agents' },
|
||||
{ id: 'mansion', label: 'Mansion' },
|
||||
{ id: 'booth', label: 'My Booth' },
|
||||
{ id: 'mansion', label: 'My Mansion' },
|
||||
{ id: 'legion', label: 'My Legion' },
|
||||
];
|
||||
const VALID_ROUTES = ['home', 'agents', 'mansion', 'booth', 'account', 'admin', 'signin', 'status', 'changelog'];
|
||||
const VALID_ROUTES = ['home', 'agents', 'mansion', 'legion', 'account', 'admin', 'signin', 'status', 'changelog'];
|
||||
const ROUTE_TITLES = {
|
||||
home: 'amerc — hire agents like mercenaries', agents: 'Browse Agents · amerc', mansion: 'The Mansion · amerc',
|
||||
booth: 'My Booth · amerc', account: 'Account · amerc', signin: 'Sign in · amerc', status: 'System status · amerc',
|
||||
home: 'amerc — hire agents like mercenaries', agents: 'Browse Agents · amerc', mansion: 'My Mansion · amerc',
|
||||
legion: 'My Legion · amerc', account: 'Account · amerc', signin: 'Sign in · amerc', status: 'System status · amerc',
|
||||
changelog: 'Changelog · amerc', admin: 'Quartermaster · amerc',
|
||||
};
|
||||
|
||||
function useHashRoute() {
|
||||
const normalize = () => {
|
||||
// first path segment is the route; the rest (e.g. #/agents/<slug>) is a sub-path
|
||||
const base = window.location.hash.replace(/^#\/?/, '').split('/')[0];
|
||||
let base = window.location.hash.replace(/^#\/?/, '').split('/')[0];
|
||||
if (base === 'booth') base = 'legion'; // legacy alias for the renamed route
|
||||
return VALID_ROUTES.includes(base) ? base : 'home';
|
||||
};
|
||||
const [route, setRouteState] = useState(normalize);
|
||||
@ -127,7 +128,7 @@ function Home({ setRoute }) {
|
||||
<p>Hire, run, and deliver AI agents across any software boundary — as an embedded chatbox, a live web terminal, or a public URL. <b>No infrastructure, just skills.</b></p>
|
||||
<div className="gm-cta">
|
||||
<button className="gm-cta-btn gm-cta-primary" onClick={() => setRoute('agents')}>Browse Agents →</button>
|
||||
<button className="gm-cta-btn gm-cta-secondary" onClick={() => setRoute('booth')}>Publish yours</button>
|
||||
<button className="gm-cta-btn gm-cta-secondary" onClick={() => setRoute('legion')}>Publish yours</button>
|
||||
</div>
|
||||
{stats && (
|
||||
<div className="hero-live">
|
||||
@ -148,8 +149,8 @@ function Home({ setRoute }) {
|
||||
|
||||
const HF_STEPS = [
|
||||
{ icon: '🍺', title: 'Browse & hire', body: 'Walk the tavern floor and pick a mercenary by skill and tag. See runtime, online status, and what each agent can do.', cta: ['Browse Agents', 'agents'] },
|
||||
{ icon: '🗡️', title: 'Publish & run', body: 'Register your own agent class in My Booth and run instances — your broker brings the runtime. No infrastructure to manage.', cta: ['Open My Booth', 'booth'] },
|
||||
{ icon: '🔌', title: 'Deliver anywhere', body: 'Serve users as an embedded chatbox, drive a live web terminal, or expose a local port to the internet via Showcase.', cta: ['The Mansion', 'mansion'] },
|
||||
{ icon: '🗡️', title: 'Publish & run', body: 'Register your own agent class in My Legion and run instances — your broker brings the runtime. No infrastructure to manage.', cta: ['Open My Legion', 'legion'] },
|
||||
{ icon: '🔌', title: 'Deliver anywhere', body: 'Serve users as an embedded chatbox, drive a live web terminal, or expose a local port to the internet via Showcase.', cta: ['My Mansion', 'mansion'] },
|
||||
];
|
||||
const HF_USES = [
|
||||
{ icon: '💬', title: 'Chatbox', body: 'Drop one <script> tag on any site; the agent appears as a chat widget with your page skills injected.' },
|
||||
@ -334,7 +335,7 @@ function HomeFeatures({ setRoute }) {
|
||||
<ActivityFeed />
|
||||
<div className="hf-cta">
|
||||
<button className="px-action" onClick={() => setRoute('agents')}>Browse Agents</button>
|
||||
<button className="px-action" onClick={() => setRoute('booth')}>Publish an Agent</button>
|
||||
<button className="px-action" onClick={() => setRoute('legion')}>Publish an Agent</button>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
@ -359,8 +360,8 @@ function Footer({ setRoute }) {
|
||||
</div>
|
||||
<div className="ft-col"><h4>Product</h4>
|
||||
<button onClick={() => setRoute('agents')}>Browse Agents</button>
|
||||
<button onClick={() => setRoute('mansion')}>Mansion</button>
|
||||
<button onClick={() => setRoute('booth')}>My Booth</button>
|
||||
<button onClick={() => setRoute('mansion')}>My Mansion</button>
|
||||
<button onClick={() => setRoute('legion')}>My Legion</button>
|
||||
</div>
|
||||
<div className="ft-col"><h4>Resources</h4>
|
||||
<a href="https://docs.amerc.ai/">Docs</a>
|
||||
@ -409,7 +410,7 @@ function Gatehouse({ auth, setRoute }) {
|
||||
<div className="gate-form">
|
||||
<div className="px-board gate-board">
|
||||
<header className="px-board-head"><span className="px-board-tag">ONE ACCOUNT</span><h2>Welcome, mercenary</h2><p>Log in, or create your account in seconds.</p></header>
|
||||
<AuthPanel auth={auth} onDone={() => setRoute('booth')} />
|
||||
<AuthPanel auth={auth} onDone={() => setRoute('legion')} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -476,6 +477,7 @@ function StatusPage() {
|
||||
}
|
||||
|
||||
const CHANGELOG = [
|
||||
{ v: '1.0', date: 'Jun 2026', title: 'Legion & My Mansion', notes: ['My Booth is now your Legion — your war-band of agent classes and the instances you field', 'The Mansion became My Mansion, your estate of live services'] },
|
||||
{ v: '0.99', date: 'Jun 2026', title: 'Clearer publish form', notes: ['The Booth publish form now labels every field, so the pre-filled Kind and Launch command are no longer ambiguous'] },
|
||||
{ v: '0.98', date: 'Jun 2026', title: 'Live API console', notes: ['The home-page API peek now shows the response status and timing, with a run button to re-fetch'] },
|
||||
{ v: '0.97', date: 'Jun 2026', title: 'Clearer sign-in', notes: ['The join form now uses plain labels (Email, Password) and a clear Log in button'] },
|
||||
@ -544,7 +546,7 @@ function Scene({ route, setRoute, auth }) {
|
||||
if (route === 'home') return <Home setRoute={setRoute} auth={auth} />;
|
||||
if (route === 'agents') return <Page setRoute={setRoute}><AgentBrowse auth={auth} setRoute={setRoute} /></Page>;
|
||||
if (route === 'mansion') return <Page setRoute={setRoute}><Mansion auth={auth} setRoute={setRoute} /></Page>;
|
||||
if (route === 'booth') return <Page setRoute={setRoute}><BoothDashboard auth={auth} setRoute={setRoute} /></Page>;
|
||||
if (route === 'legion') return <Page setRoute={setRoute}><LegionDashboard auth={auth} setRoute={setRoute} /></Page>;
|
||||
if (route === 'account') return <Page setRoute={setRoute}><Account auth={auth} setRoute={setRoute} /></Page>;
|
||||
if (route === 'status') return <Page setRoute={setRoute}><StatusPage /></Page>;
|
||||
if (route === 'changelog') return <Page setRoute={setRoute}><ChangelogPage /></Page>;
|
||||
|
||||
@ -126,10 +126,10 @@ export default function TavernGame({ onHotspot, stats }) {
|
||||
<div className="gm-overlay">
|
||||
<button className="gm-hot" style={{ left: '38%', top: '1%', width: '24%', height: '16%' }} onClick={() => onHotspot?.('agents')} title="Browse Agents (screen)" />
|
||||
<button className="gm-label gm-label-screen" style={{ left: '50%', top: '18%' }} onClick={() => onHotspot?.('agents')}>▸ Browse Agents</button>
|
||||
<button className="gm-hot" style={{ left: '44%', top: '50%', width: '14%', height: '24%' }} onClick={() => onHotspot?.('booth')} title="My Booth" />
|
||||
<button className="gm-label gm-label-booth" style={{ left: '50%', top: '90%' }} onClick={() => onHotspot?.('booth')}>⌂ Enter My Booth</button>
|
||||
<button className="gm-hot" style={{ left: '44%', top: '50%', width: '14%', height: '24%' }} onClick={() => onHotspot?.('legion')} title="My Legion" />
|
||||
<button className="gm-label gm-label-booth" style={{ left: '50%', top: '90%' }} onClick={() => onHotspot?.('legion')}>⌂ Enter My Legion</button>
|
||||
<Npc x="11%" y="4%" w="13%" h="20%" who="Barkeep" say="What'll it be? The staff roster is up on the board." onClick={() => onHotspot?.('agents')} />
|
||||
<Npc x="11%" y="52%" w="13%" h="22%" who="Patron" say="I run three mercenaries straight from my booth." onClick={() => onHotspot?.('booth')} />
|
||||
<Npc x="11%" y="52%" w="13%" h="22%" who="Patron" say="I field three mercenaries straight from my legion." onClick={() => onHotspot?.('legion')} />
|
||||
<Npc x="72%" y="52%" w="13%" h="22%" who="Patron" say="Showcase put my little app on the open internet!" onClick={() => onHotspot?.('mansion')} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -47,7 +47,7 @@ export function registerAmercTools() {
|
||||
mc.registerTool({
|
||||
name: 'amerc_open',
|
||||
description: 'Open a section of the amerc tavern in the browser so the user can see it.',
|
||||
inputSchema: { type: 'object', properties: { section: { type: 'string', enum: ['home', 'agents', 'mansion', 'booth', 'account', 'status', 'changelog', 'signin'], description: 'which section to open' } }, required: ['section'] },
|
||||
inputSchema: { type: 'object', properties: { section: { type: 'string', enum: ['home', 'agents', 'mansion', 'legion', 'account', 'status', 'changelog', 'signin'], description: 'which section to open' } }, required: ['section'] },
|
||||
execute: async (input) => { window.location.hash = `#/${input.section}`; return { ok: true, opened: input.section }; },
|
||||
});
|
||||
} catch { /* WebMCP API shape differs — ignore, the site is unaffected */ }
|
||||
|
||||
Loading…
Reference in New Issue
Block a user