@oddessentials/agent-guild 0.7.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -2
- package/package.json +1 -1
- package/web/app.js +69 -17
- package/web/index.html +13 -3
- package/web/skins/guild/skin.css +502 -0
- package/web/skins/orbital/characters/anthropic/idle.avif +0 -0
- package/web/skins/orbital/characters/anthropic/idle.webp +0 -0
- package/web/skins/orbital/characters/anthropic/locked.avif +0 -0
- package/web/skins/orbital/characters/anthropic/locked.webp +0 -0
- package/web/skins/orbital/characters/anthropic/working.avif +0 -0
- package/web/skins/orbital/characters/anthropic/working.webp +0 -0
- package/web/skins/orbital/characters/google/idle.avif +0 -0
- package/web/skins/orbital/characters/google/idle.webp +0 -0
- package/web/skins/orbital/characters/google/locked.avif +0 -0
- package/web/skins/orbital/characters/google/locked.webp +0 -0
- package/web/skins/orbital/characters/google/working.avif +0 -0
- package/web/skins/orbital/characters/google/working.webp +0 -0
- package/web/skins/orbital/characters/openai/idle.avif +0 -0
- package/web/skins/orbital/characters/openai/idle.webp +0 -0
- package/web/skins/orbital/characters/openai/locked.avif +0 -0
- package/web/skins/orbital/characters/openai/locked.webp +0 -0
- package/web/skins/orbital/characters/openai/working.avif +0 -0
- package/web/skins/orbital/characters/openai/working.webp +0 -0
- package/web/skins/orbital/characters/shell/idle.avif +0 -0
- package/web/skins/orbital/characters/shell/idle.webp +0 -0
- package/web/skins/orbital/characters/shell/locked.avif +0 -0
- package/web/skins/orbital/characters/shell/locked.webp +0 -0
- package/web/skins/orbital/characters/shell/working.avif +0 -0
- package/web/skins/orbital/characters/shell/working.webp +0 -0
- package/web/skins/orbital/characters/xai/idle.avif +0 -0
- package/web/skins/orbital/characters/xai/idle.webp +0 -0
- package/web/skins/orbital/characters/xai/locked.avif +0 -0
- package/web/skins/orbital/characters/xai/locked.webp +0 -0
- package/web/skins/orbital/characters/xai/working.avif +0 -0
- package/web/skins/orbital/characters/xai/working.webp +0 -0
- package/web/skins/orbital/familiars/aether.png +0 -0
- package/web/skins/orbital/familiars/flame.png +0 -0
- package/web/skins/orbital/familiars/leaf.png +0 -0
- package/web/skins/orbital/familiars/night.png +0 -0
- package/web/skins/orbital/fonts/OFL.txt +93 -0
- package/web/skins/orbital/fonts/exo2.woff2 +0 -0
- package/web/skins/orbital/icons/anthropic.avif +0 -0
- package/web/skins/orbital/icons/anthropic.webp +0 -0
- package/web/skins/orbital/icons/google.avif +0 -0
- package/web/skins/orbital/icons/google.webp +0 -0
- package/web/skins/orbital/icons/openai.avif +0 -0
- package/web/skins/orbital/icons/openai.webp +0 -0
- package/web/skins/orbital/icons/shell.avif +0 -0
- package/web/skins/orbital/icons/shell.webp +0 -0
- package/web/skins/orbital/icons/xai.avif +0 -0
- package/web/skins/orbital/icons/xai.webp +0 -0
- package/web/skins/orbital/page-light.avif +0 -0
- package/web/skins/orbital/page-light.webp +0 -0
- package/web/skins/orbital/page.avif +0 -0
- package/web/skins/orbital/page.webp +0 -0
- package/web/skins/orbital/skin.css +393 -0
- package/web/skins/orbital/ui/empty-state.avif +0 -0
- package/web/skins/orbital/ui/empty-state.webp +0 -0
- package/web/skins/orbital/ui/level.svg +1 -0
- package/web/skins/orbital/ui/lock.svg +1 -0
- package/web/skins/orbital/ui/plasma.svg +1 -0
- package/web/skins/orbital/ui/power.svg +1 -0
- package/web/skins/professional/banners/anthropic/idle.svg +1 -0
- package/web/skins/professional/banners/anthropic/locked.svg +1 -0
- package/web/skins/professional/banners/anthropic/working.svg +1 -0
- package/web/skins/professional/banners/google/idle.svg +1 -0
- package/web/skins/professional/banners/google/locked.svg +1 -0
- package/web/skins/professional/banners/google/working.svg +1 -0
- package/web/skins/professional/banners/openai/idle.svg +1 -0
- package/web/skins/professional/banners/openai/locked.svg +1 -0
- package/web/skins/professional/banners/openai/working.svg +1 -0
- package/web/skins/professional/banners/shell/idle.svg +1 -0
- package/web/skins/professional/banners/shell/locked.svg +1 -0
- package/web/skins/professional/banners/shell/working.svg +1 -0
- package/web/skins/professional/banners/xai/idle.svg +1 -0
- package/web/skins/professional/banners/xai/locked.svg +1 -0
- package/web/skins/professional/banners/xai/working.svg +1 -0
- package/web/skins/professional/icons/anthropic.svg +1 -0
- package/web/skins/professional/icons/google.svg +1 -0
- package/web/skins/professional/icons/openai.svg +1 -0
- package/web/skins/professional/icons/shell.svg +1 -0
- package/web/skins/professional/icons/xai.svg +1 -0
- package/web/skins/professional/page-light.svg +1 -0
- package/web/skins/professional/page.svg +1 -0
- package/web/skins/professional/skin.css +253 -0
- package/web/skins/professional/ui/empty-state-light.svg +1 -0
- package/web/skins/professional/ui/empty-state.svg +1 -0
- package/web/skins/professional/ui/lock.svg +1 -0
- package/web/styles.css +43 -44
- package/web/theme.js +19 -3
- package/web/art/art.css +0 -467
- /package/web/{art/ui/guild-crest.png → brand/crest.png} +0 -0
- /package/web/{art/ui → brand}/favicon.png +0 -0
- /package/web/{art → skins/guild}/characters/anthropic/idle.avif +0 -0
- /package/web/{art → skins/guild}/characters/anthropic/idle.webp +0 -0
- /package/web/{art → skins/guild}/characters/anthropic/locked.avif +0 -0
- /package/web/{art → skins/guild}/characters/anthropic/locked.webp +0 -0
- /package/web/{art → skins/guild}/characters/anthropic/working.avif +0 -0
- /package/web/{art → skins/guild}/characters/anthropic/working.webp +0 -0
- /package/web/{art → skins/guild}/characters/google/idle.avif +0 -0
- /package/web/{art → skins/guild}/characters/google/idle.webp +0 -0
- /package/web/{art → skins/guild}/characters/google/locked.avif +0 -0
- /package/web/{art → skins/guild}/characters/google/locked.webp +0 -0
- /package/web/{art → skins/guild}/characters/google/working.avif +0 -0
- /package/web/{art → skins/guild}/characters/google/working.webp +0 -0
- /package/web/{art → skins/guild}/characters/openai/idle.avif +0 -0
- /package/web/{art → skins/guild}/characters/openai/idle.webp +0 -0
- /package/web/{art → skins/guild}/characters/openai/locked.avif +0 -0
- /package/web/{art → skins/guild}/characters/openai/locked.webp +0 -0
- /package/web/{art → skins/guild}/characters/openai/working.avif +0 -0
- /package/web/{art → skins/guild}/characters/openai/working.webp +0 -0
- /package/web/{art → skins/guild}/characters/shell/idle.avif +0 -0
- /package/web/{art → skins/guild}/characters/shell/idle.webp +0 -0
- /package/web/{art → skins/guild}/characters/shell/locked.avif +0 -0
- /package/web/{art → skins/guild}/characters/shell/locked.webp +0 -0
- /package/web/{art → skins/guild}/characters/shell/working.avif +0 -0
- /package/web/{art → skins/guild}/characters/shell/working.webp +0 -0
- /package/web/{art → skins/guild}/characters/xai/idle.avif +0 -0
- /package/web/{art → skins/guild}/characters/xai/idle.webp +0 -0
- /package/web/{art → skins/guild}/characters/xai/locked.avif +0 -0
- /package/web/{art → skins/guild}/characters/xai/locked.webp +0 -0
- /package/web/{art → skins/guild}/characters/xai/working.avif +0 -0
- /package/web/{art → skins/guild}/characters/xai/working.webp +0 -0
- /package/web/{art → skins/guild}/familiars/aether.png +0 -0
- /package/web/{art → skins/guild}/familiars/flame.png +0 -0
- /package/web/{art → skins/guild}/familiars/leaf.png +0 -0
- /package/web/{art → skins/guild}/familiars/night.png +0 -0
- /package/web/{art → skins/guild}/icons/anthropic.avif +0 -0
- /package/web/{art → skins/guild}/icons/anthropic.webp +0 -0
- /package/web/{art → skins/guild}/icons/google.avif +0 -0
- /package/web/{art → skins/guild}/icons/google.webp +0 -0
- /package/web/{art → skins/guild}/icons/openai.avif +0 -0
- /package/web/{art → skins/guild}/icons/openai.webp +0 -0
- /package/web/{art → skins/guild}/icons/shell.avif +0 -0
- /package/web/{art → skins/guild}/icons/shell.webp +0 -0
- /package/web/{art → skins/guild}/icons/xai.avif +0 -0
- /package/web/{art → skins/guild}/icons/xai.webp +0 -0
- /package/web/{art → skins/guild}/page-light.avif +0 -0
- /package/web/{art → skins/guild}/page-light.webp +0 -0
- /package/web/{art → skins/guild}/page.avif +0 -0
- /package/web/{art → skins/guild}/page.webp +0 -0
- /package/web/{art → skins/guild}/ui/empty-state.avif +0 -0
- /package/web/{art → skins/guild}/ui/empty-state.webp +0 -0
- /package/web/{art → skins/guild}/ui/frame-ornate.png +0 -0
- /package/web/{art → skins/guild}/ui/frame.png +0 -0
- /package/web/{art → skins/guild}/ui/gem-mana.png +0 -0
- /package/web/{art → skins/guild}/ui/gem-vitality.png +0 -0
- /package/web/{art → skins/guild}/ui/level-medallion.png +0 -0
- /package/web/{art → skins/guild}/ui/padlock.png +0 -0
package/README.md
CHANGED
|
@@ -99,8 +99,12 @@ vX.Y.Z** switches over when you are ready. The version badge opens
|
|
|
99
99
|
|
|
100
100
|
<img src="docs/images/whats-new.webp" alt="The What's new panel listing the release notes of each version">
|
|
101
101
|
|
|
102
|
-
**
|
|
103
|
-
|
|
102
|
+
**Appearance.** The Appearance menu in the top bar picks a skin and light or
|
|
103
|
+
dark mode, without a reload. **Guild** is the default fantasy look;
|
|
104
|
+
**Professional** is a plain business look with no characters; **Orbital**
|
|
105
|
+
puts a crew of little robots in deep space. The page
|
|
106
|
+
follows your system's light or dark setting until you pick one. See
|
|
107
|
+
[docs/SKINS.md](docs/SKINS.md) to make another.
|
|
104
108
|
|
|
105
109
|
## Commands
|
|
106
110
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oddessentials/agent-guild",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Launch and watch AI coding-assistant terminal sessions from one local web page. A bundled session manager owns the terminals so the page can close and reconnect.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
package/web/app.js
CHANGED
|
@@ -5,6 +5,7 @@ const TOKEN_KEY = 'agentGuild.token';
|
|
|
5
5
|
const CWD_KEY = 'agentGuild.cwd';
|
|
6
6
|
const ACCOUNTS_KEY = 'agentGuild.accounts';
|
|
7
7
|
const THEME_KEY = 'agentGuild.theme';
|
|
8
|
+
const SKIN_KEY = 'agentGuild.skin';
|
|
8
9
|
const NEWS_SEEN_KEY = 'agentGuild.newsSeen';
|
|
9
10
|
const NEWS_FILTER_KEY = 'agentGuild.newsFilter';
|
|
10
11
|
const CHANGELOG_SEEN_KEY = 'agentGuild.changelogSeen';
|
|
@@ -142,33 +143,72 @@ function unreadRelease() {
|
|
|
142
143
|
|
|
143
144
|
// ---- theme ----------------------------------------------------------------
|
|
144
145
|
|
|
145
|
-
/** theme.js applied the saved or system theme before the first paint; this keeps the
|
|
146
|
+
/** theme.js applied the saved or system theme before the first paint; this keeps the menu in step. */
|
|
146
147
|
function applyTheme(theme) {
|
|
147
148
|
document.documentElement.dataset.theme = theme;
|
|
148
|
-
|
|
149
|
-
const other = theme === 'dark' ? 'light' : 'dark';
|
|
150
|
-
button.textContent = theme === 'dark' ? 'Light' : 'Dark';
|
|
151
|
-
button.dataset.next = other;
|
|
152
|
-
button.title = `Switch to the ${other} theme`;
|
|
153
|
-
button.setAttribute('aria-label', `Switch to the ${other} theme`);
|
|
149
|
+
document.querySelector(`#appearance-menu input[name="theme"][value="${theme}"]`).checked = true;
|
|
154
150
|
}
|
|
155
151
|
|
|
156
152
|
function currentTheme() {
|
|
157
153
|
return document.documentElement.dataset.theme === 'dark' ? 'dark' : 'light';
|
|
158
154
|
}
|
|
159
155
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
const box = event.currentTarget.getBoundingClientRect();
|
|
156
|
+
/** Repaints the page with `change`, revealed in a circle growing from the control that asked for it. */
|
|
157
|
+
function revealChange(control, change) {
|
|
158
|
+
if (!document.startViewTransition || reducedMotion.matches) return change();
|
|
159
|
+
const box = control.getBoundingClientRect();
|
|
165
160
|
const x = box.left + box.width / 2;
|
|
166
161
|
const y = box.top + box.height / 2;
|
|
167
162
|
const root = document.documentElement.style;
|
|
168
163
|
root.setProperty('--reveal-x', `${Math.round(x)}px`);
|
|
169
164
|
root.setProperty('--reveal-y', `${Math.round(y)}px`);
|
|
170
165
|
root.setProperty('--reveal-r', `${Math.ceil(Math.hypot(Math.max(x, innerWidth - x), Math.max(y, innerHeight - y)))}px`);
|
|
171
|
-
|
|
166
|
+
// The browser skips the animation (still applying the change) when the page is hidden or another transition starts.
|
|
167
|
+
document.startViewTransition(change).ready.catch(() => {});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function changeTheme(input) {
|
|
171
|
+
const theme = input.value === 'dark' ? 'dark' : 'light';
|
|
172
|
+
save(THEME_KEY, theme);
|
|
173
|
+
revealChange(input.closest('label'), () => applyTheme(theme));
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// ---- skin -----------------------------------------------------------------
|
|
177
|
+
|
|
178
|
+
/** The skins theme.js offers; it applied the saved one before the first paint. */
|
|
179
|
+
const SKINS = window.agentGuildSkins ?? [{ id: 'guild', name: 'Guild' }];
|
|
180
|
+
|
|
181
|
+
function renderSkinChoices() {
|
|
182
|
+
const choices = SKINS.map((skin) => {
|
|
183
|
+
const label = document.createElement('label');
|
|
184
|
+
label.className = 'choice';
|
|
185
|
+
const input = Object.assign(document.createElement('input'), { type: 'radio', name: 'skin', value: skin.id });
|
|
186
|
+
input.checked = skin.id === document.documentElement.dataset.skin;
|
|
187
|
+
label.append(input, Object.assign(document.createElement('span'), { textContent: skin.name }));
|
|
188
|
+
return label;
|
|
189
|
+
});
|
|
190
|
+
$('skin-choices').append(...choices);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Switches skin in place. Entrance and level-up animations are cleared first
|
|
195
|
+
* so the new skin does not replay them on every card.
|
|
196
|
+
*/
|
|
197
|
+
function changeSkin(input) {
|
|
198
|
+
const skin = input.value;
|
|
199
|
+
if (!SKINS.some((s) => s.id === skin) || skin === document.documentElement.dataset.skin) return;
|
|
200
|
+
save(SKIN_KEY, skin);
|
|
201
|
+
for (const el of document.querySelectorAll('.deal, .enter, .level-up, .summon')) el.classList.remove('deal', 'enter', 'level-up', 'summon');
|
|
202
|
+
revealChange(input.closest('label'), () => { document.documentElement.dataset.skin = skin; });
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** Places the open menu under its button, right-aligned with it and kept on screen. */
|
|
206
|
+
function placeAppearanceMenu() {
|
|
207
|
+
const menu = $('appearance-menu');
|
|
208
|
+
if (!menu.matches(':popover-open')) return;
|
|
209
|
+
const box = $('appearance').getBoundingClientRect();
|
|
210
|
+
menu.style.top = `${Math.round(box.bottom + 6)}px`;
|
|
211
|
+
menu.style.right = `${Math.max(8, Math.round(innerWidth - box.right))}px`;
|
|
172
212
|
}
|
|
173
213
|
|
|
174
214
|
// ---- upgrading the manager ------------------------------------------------
|
|
@@ -2443,9 +2483,11 @@ function buildCard(session) {
|
|
|
2443
2483
|
if (id) copyId(id);
|
|
2444
2484
|
});
|
|
2445
2485
|
node.querySelector('.model-pill').addEventListener('click', () => openSessionModel(session.id));
|
|
2486
|
+
// Skins name their own keyframes, so the one-shot classes clear on any animation they run.
|
|
2446
2487
|
node.addEventListener('animationend', (e) => {
|
|
2447
|
-
if (e.
|
|
2448
|
-
else if (e.
|
|
2488
|
+
if (e.target.classList.contains('level-up')) e.target.classList.remove('level-up');
|
|
2489
|
+
else if (e.target.classList.contains('summon')) e.target.classList.remove('summon');
|
|
2490
|
+
else if (e.target === node) node.classList.remove('enter');
|
|
2449
2491
|
});
|
|
2450
2492
|
return node;
|
|
2451
2493
|
}
|
|
@@ -3170,9 +3212,18 @@ $('stop-manager').addEventListener('click', () => stopManager());
|
|
|
3170
3212
|
$('restart-manager').addEventListener('click', () => stopManager({ restart: true }));
|
|
3171
3213
|
$('copy-command').addEventListener('click', copyCommand);
|
|
3172
3214
|
$('upgrade').addEventListener('click', upgradeManager);
|
|
3173
|
-
$('
|
|
3215
|
+
$('appearance-menu').addEventListener('change', (e) => {
|
|
3216
|
+
if (e.target.name === 'skin') changeSkin(e.target);
|
|
3217
|
+
else if (e.target.name === 'theme') changeTheme(e.target);
|
|
3218
|
+
});
|
|
3219
|
+
$('appearance-menu').addEventListener('toggle', (e) => {
|
|
3220
|
+
if (e.newState !== 'open') return;
|
|
3221
|
+
placeAppearanceMenu();
|
|
3222
|
+
e.currentTarget.querySelector('input:checked')?.focus();
|
|
3223
|
+
});
|
|
3224
|
+
window.addEventListener('resize', placeAppearanceMenu);
|
|
3174
3225
|
$('providers').addEventListener('animationend', (e) => {
|
|
3175
|
-
if (e.
|
|
3226
|
+
if (e.target === e.currentTarget.lastElementChild) e.currentTarget.classList.remove('deal');
|
|
3176
3227
|
});
|
|
3177
3228
|
let tiltFrame = 0;
|
|
3178
3229
|
$('providers').addEventListener('pointermove', (e) => {
|
|
@@ -3196,6 +3247,7 @@ $('providers').addEventListener('pointerout', (e) => {
|
|
|
3196
3247
|
}
|
|
3197
3248
|
});
|
|
3198
3249
|
applyTheme(currentTheme());
|
|
3250
|
+
renderSkinChoices();
|
|
3199
3251
|
// Follow the system setting until the user picks a theme.
|
|
3200
3252
|
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
|
|
3201
3253
|
if (!load(THEME_KEY)) applyTheme(e.matches ? 'dark' : 'light');
|
package/web/index.html
CHANGED
|
@@ -6,11 +6,13 @@
|
|
|
6
6
|
<title>Agent Guild</title>
|
|
7
7
|
<meta name="color-scheme" content="light dark">
|
|
8
8
|
<script src="/theme.js"></script>
|
|
9
|
-
<link rel="icon" href="/
|
|
9
|
+
<link rel="icon" href="/brand/favicon.png" type="image/png">
|
|
10
10
|
<link rel="preload" href="/fonts/cinzel.woff2" as="font" type="font/woff2" crossorigin>
|
|
11
11
|
<link rel="stylesheet" href="/vendor/xterm/xterm.css">
|
|
12
12
|
<link rel="stylesheet" href="/styles.css">
|
|
13
|
-
<link rel="stylesheet" href="/
|
|
13
|
+
<link rel="stylesheet" href="/skins/guild/skin.css">
|
|
14
|
+
<link rel="stylesheet" href="/skins/professional/skin.css">
|
|
15
|
+
<link rel="stylesheet" href="/skins/orbital/skin.css">
|
|
14
16
|
</head>
|
|
15
17
|
<body>
|
|
16
18
|
<header class="topbar">
|
|
@@ -24,7 +26,15 @@
|
|
|
24
26
|
</div>
|
|
25
27
|
<span id="upgrade-note" class="upgrade-note" hidden></span>
|
|
26
28
|
<button id="upgrade" class="btn upgrade" type="button" hidden></button>
|
|
27
|
-
<button id="
|
|
29
|
+
<button id="appearance" class="btn appearance" type="button" popovertarget="appearance-menu" aria-haspopup="dialog">Appearance</button>
|
|
30
|
+
<div id="appearance-menu" class="appearance-menu" popover role="dialog" aria-label="Appearance">
|
|
31
|
+
<fieldset id="skin-choices"><legend>Skin</legend></fieldset>
|
|
32
|
+
<fieldset>
|
|
33
|
+
<legend>Mode</legend>
|
|
34
|
+
<label class="choice"><input type="radio" name="theme" value="light"><span class="mode-light">Light</span></label>
|
|
35
|
+
<label class="choice"><input type="radio" name="theme" value="dark"><span class="mode-dark">Dark</span></label>
|
|
36
|
+
</fieldset>
|
|
37
|
+
</div>
|
|
28
38
|
<button id="restart-manager" class="btn restart-manager" type="button" hidden>Restart manager</button>
|
|
29
39
|
<button id="stop-manager" class="btn danger stop-manager" type="button" hidden title="Stop the session manager. This ends every session.">Stop manager</button>
|
|
30
40
|
</div>
|