ai-or-die 0.1.75 → 0.1.76
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/package.json +1 -1
- package/src/public/app-identity.js +0 -0
- package/src/public/app.js +57 -19
- package/src/public/auth.js +6 -6
- package/src/public/components/buttons.css +4 -3
- package/src/public/components/cards.css +43 -19
- package/src/public/components/controls.css +422 -0
- package/src/public/components/file-browser.css +4 -4
- package/src/public/components/input-overlay.css +1 -1
- package/src/public/components/menus.css +4 -4
- package/src/public/components/modals.css +9 -9
- package/src/public/components/sticky-note.css +9 -10
- package/src/public/components/tabs.css +8 -1
- package/src/public/components/terminal.css +3 -3
- package/src/public/index.html +177 -140
- package/src/public/service-worker.js +8 -3
- package/src/public/session-manager.js +20 -15
- package/src/public/tokens.css +23 -0
- package/src/server.js +33 -5
package/package.json
CHANGED
|
Binary file
|
package/src/public/app.js
CHANGED
|
@@ -191,6 +191,18 @@ class ClaudeCodeWebInterface {
|
|
|
191
191
|
}
|
|
192
192
|
|
|
193
193
|
await this.loadConfig();
|
|
194
|
+
// Apply per-machine identity (`[HOST] ai-or-die`) to the tab/window
|
|
195
|
+
// title, mobile menu header, aria-label, and PWA meta tags now that
|
|
196
|
+
// this.hostname is populated. Must run before the first notification
|
|
197
|
+
// flash, which saves/restores the then-current document.title.
|
|
198
|
+
if (window.AppIdentity) {
|
|
199
|
+
const identity = window.AppIdentity.formatAppIdentity({ hostname: this.hostname });
|
|
200
|
+
window.AppIdentity.applyAppIdentity(identity);
|
|
201
|
+
// Surface the machine identity on the start screen too.
|
|
202
|
+
const spIdText = document.getElementById('startPromptIdentityText');
|
|
203
|
+
const spId = document.getElementById('startPromptIdentity');
|
|
204
|
+
if (spIdText && spId) { spIdText.textContent = identity; spId.hidden = false; }
|
|
205
|
+
}
|
|
194
206
|
this.setupTerminal();
|
|
195
207
|
this._setupExtraKeys();
|
|
196
208
|
this._setupOrientationHandler();
|
|
@@ -1929,19 +1941,34 @@ class ClaudeCodeWebInterface {
|
|
|
1929
1941
|
});
|
|
1930
1942
|
}
|
|
1931
1943
|
|
|
1932
|
-
//
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
if (
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1944
|
+
// Two-pane settings nav (ARIA tablist): switch panes, roving tabindex,
|
|
1945
|
+
// arrow/Home/End keyboard support. Replaces the old collapsible sections.
|
|
1946
|
+
const settingsTabs = Array.from(modal.querySelectorAll('.settings-tab'));
|
|
1947
|
+
const selectSettingsTab = (tab, focus = true) => {
|
|
1948
|
+
settingsTabs.forEach((t) => {
|
|
1949
|
+
const selected = t === tab;
|
|
1950
|
+
t.setAttribute('aria-selected', String(selected));
|
|
1951
|
+
t.tabIndex = selected ? 0 : -1;
|
|
1952
|
+
const pane = document.getElementById(t.getAttribute('aria-controls'));
|
|
1953
|
+
if (pane) pane.hidden = !selected;
|
|
1954
|
+
});
|
|
1955
|
+
if (focus && tab) tab.focus();
|
|
1956
|
+
};
|
|
1957
|
+
settingsTabs.forEach((tab) => {
|
|
1958
|
+
tab.addEventListener('click', () => selectSettingsTab(tab, false));
|
|
1959
|
+
tab.addEventListener('keydown', (e) => {
|
|
1960
|
+
// Navigate among VISIBLE tabs only (the Install tab is hidden
|
|
1961
|
+
// when running as an installed PWA) so focus never lands on an
|
|
1962
|
+
// invisible element and escapes the modal focus trap.
|
|
1963
|
+
const visible = settingsTabs.filter((t) => t.style.display !== 'none' && !t.hidden);
|
|
1964
|
+
const idx = visible.indexOf(tab);
|
|
1965
|
+
if (idx === -1) return;
|
|
1966
|
+
let next = null;
|
|
1967
|
+
if (e.key === 'ArrowDown' || e.key === 'ArrowRight') next = visible[(idx + 1) % visible.length];
|
|
1968
|
+
else if (e.key === 'ArrowUp' || e.key === 'ArrowLeft') next = visible[(idx - 1 + visible.length) % visible.length];
|
|
1969
|
+
else if (e.key === 'Home') next = visible[0];
|
|
1970
|
+
else if (e.key === 'End') next = visible[visible.length - 1];
|
|
1971
|
+
if (next) { e.preventDefault(); selectSettingsTab(next); }
|
|
1945
1972
|
});
|
|
1946
1973
|
});
|
|
1947
1974
|
|
|
@@ -3917,11 +3944,15 @@ class ClaudeCodeWebInterface {
|
|
|
3917
3944
|
content.classList.remove('closing');
|
|
3918
3945
|
overlay.classList.remove('closing');
|
|
3919
3946
|
overlay.classList.remove('active');
|
|
3920
|
-
|
|
3947
|
+
// Clear (don't set) the inline display so the modal hides via its
|
|
3948
|
+
// base CSS rule (.<modal> { display: none }). Setting an inline
|
|
3949
|
+
// display:none would win over `.active { display: flex }` and
|
|
3950
|
+
// permanently block reopening the modal.
|
|
3951
|
+
overlay.style.removeProperty('display');
|
|
3921
3952
|
}, 150);
|
|
3922
3953
|
} else {
|
|
3923
3954
|
overlay.classList.remove('active');
|
|
3924
|
-
overlay.style.display
|
|
3955
|
+
overlay.style.removeProperty('display');
|
|
3925
3956
|
}
|
|
3926
3957
|
}
|
|
3927
3958
|
|
|
@@ -4196,10 +4227,17 @@ class ClaudeCodeWebInterface {
|
|
|
4196
4227
|
if (installBtn) installBtn.style.display = 'none';
|
|
4197
4228
|
if (iosInstructions) iosInstructions.style.display = 'none';
|
|
4198
4229
|
|
|
4199
|
-
// If running inside installed PWA, hide the
|
|
4200
|
-
const
|
|
4201
|
-
|
|
4202
|
-
|
|
4230
|
+
// If running inside an installed PWA, hide the Install tab + pane.
|
|
4231
|
+
const installTab = document.getElementById('settingsTab-install');
|
|
4232
|
+
const installPane = document.getElementById('settingsPane-install');
|
|
4233
|
+
if (installTab) installTab.style.display = this._isInstalled ? 'none' : '';
|
|
4234
|
+
if (installPane && this._isInstalled) installPane.hidden = true;
|
|
4235
|
+
// If the Install tab was the active one and is now hidden, fall back to
|
|
4236
|
+
// the first visible tab so the pane area is never left blank/unreachable.
|
|
4237
|
+
if (this._isInstalled && installTab && installTab.getAttribute('aria-selected') === 'true') {
|
|
4238
|
+
const firstVisible = Array.from(document.querySelectorAll('.settings-tab'))
|
|
4239
|
+
.find((t) => t.style.display !== 'none');
|
|
4240
|
+
if (firstVisible) firstVisible.click();
|
|
4203
4241
|
}
|
|
4204
4242
|
|
|
4205
4243
|
switch (this._installState) {
|
package/src/public/auth.js
CHANGED
|
@@ -133,7 +133,7 @@ class AuthManager {
|
|
|
133
133
|
left: 0;
|
|
134
134
|
right: 0;
|
|
135
135
|
bottom: 0;
|
|
136
|
-
background: rgba(0, 0, 0, 0.95);
|
|
136
|
+
background: var(--overlay-backdrop-strong, rgba(0, 0, 0, 0.95));
|
|
137
137
|
display: flex;
|
|
138
138
|
align-items: center;
|
|
139
139
|
justify-content: center;
|
|
@@ -143,12 +143,12 @@ class AuthManager {
|
|
|
143
143
|
const loginForm = document.createElement('div');
|
|
144
144
|
loginForm.style.cssText = `
|
|
145
145
|
background: var(--bg-secondary, #1c2128);
|
|
146
|
-
border: 1px solid var(--border-
|
|
146
|
+
border: 1px solid var(--border-default, #30363d);
|
|
147
147
|
border-radius: 12px;
|
|
148
148
|
padding: 32px;
|
|
149
149
|
max-width: 400px;
|
|
150
150
|
width: 90%;
|
|
151
|
-
box-shadow:
|
|
151
|
+
box-shadow: var(--shadow-xl);
|
|
152
152
|
`;
|
|
153
153
|
|
|
154
154
|
loginForm.innerHTML = `
|
|
@@ -157,7 +157,7 @@ class AuthManager {
|
|
|
157
157
|
Authentication Required
|
|
158
158
|
</h2>
|
|
159
159
|
<p style="color: var(--text-secondary, #8b949e); margin: 0 0 24px 0; font-size: 14px;">
|
|
160
|
-
This
|
|
160
|
+
This instance requires authentication.
|
|
161
161
|
</p>
|
|
162
162
|
<form id="auth-form">
|
|
163
163
|
<div style="margin-bottom: 16px;">
|
|
@@ -172,7 +172,7 @@ class AuthManager {
|
|
|
172
172
|
width: 100%;
|
|
173
173
|
padding: 10px 12px;
|
|
174
174
|
background: var(--bg-primary, #0d1117);
|
|
175
|
-
border: 1px solid var(--border-
|
|
175
|
+
border: 1px solid var(--border-default, #30363d);
|
|
176
176
|
border-radius: 6px;
|
|
177
177
|
color: var(--text-primary, #f0f6fc);
|
|
178
178
|
font-family: 'Inter', system-ui, -apple-system, Segoe UI, Roboto, 'JetBrains Mono', monospace;
|
|
@@ -183,7 +183,7 @@ class AuthManager {
|
|
|
183
183
|
required
|
|
184
184
|
/>
|
|
185
185
|
</div>
|
|
186
|
-
<div id="auth-error" style="color: #f85149; margin-bottom: 16px; font-size: 14px; display: none;"></div>
|
|
186
|
+
<div id="auth-error" style="color: var(--status-error, #f85149); margin-bottom: 16px; font-size: 14px; display: none;"></div>
|
|
187
187
|
<button
|
|
188
188
|
type="submit"
|
|
189
189
|
style="
|
|
@@ -163,7 +163,7 @@
|
|
|
163
163
|
border: 2px solid var(--border);
|
|
164
164
|
border-radius: 50%;
|
|
165
165
|
cursor: pointer;
|
|
166
|
-
box-shadow:
|
|
166
|
+
box-shadow: var(--shadow-md);
|
|
167
167
|
transition: all var(--duration-slow, 300ms) var(--ease-default, cubic-bezier(0.4, 0, 0.2, 1));
|
|
168
168
|
width: 56px;
|
|
169
169
|
height: 56px;
|
|
@@ -173,7 +173,7 @@
|
|
|
173
173
|
background-color: var(--bg-tertiary);
|
|
174
174
|
border-color: var(--accent);
|
|
175
175
|
transform: translateY(-2px);
|
|
176
|
-
box-shadow:
|
|
176
|
+
box-shadow: var(--shadow-lg);
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
.mode-switcher-btn:active {
|
|
@@ -212,7 +212,7 @@
|
|
|
212
212
|
border: 2px solid var(--error);
|
|
213
213
|
border-radius: 50%;
|
|
214
214
|
cursor: pointer;
|
|
215
|
-
box-shadow:
|
|
215
|
+
box-shadow: var(--shadow-md);
|
|
216
216
|
transition: all var(--duration-slow, 300ms) var(--ease-default, cubic-bezier(0.4, 0, 0.2, 1));
|
|
217
217
|
width: 56px;
|
|
218
218
|
height: 56px;
|
|
@@ -222,6 +222,7 @@
|
|
|
222
222
|
background-color: var(--bg-tertiary);
|
|
223
223
|
border-color: var(--color-red-400);
|
|
224
224
|
transform: translateY(-2px);
|
|
225
|
+
/* Intentional red destructive-escape glow (not a neutral elevation shadow). */
|
|
225
226
|
box-shadow: 0 6px 16px rgba(248, 113, 113, 0.2);
|
|
226
227
|
}
|
|
227
228
|
|
|
@@ -58,26 +58,26 @@
|
|
|
58
58
|
transform: translateY(-1px);
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
/* Per-tool brand color hover tints */
|
|
61
|
+
/* Per-tool brand color hover tints (tokens shared with the tab badges) */
|
|
62
62
|
.tool-card[data-tool="terminal"]:hover:not(.disabled) {
|
|
63
|
-
border-color: rgba(
|
|
64
|
-
background: rgba(
|
|
63
|
+
border-color: rgba(var(--tool-terminal-rgb), 0.5);
|
|
64
|
+
background: rgba(var(--tool-terminal-rgb), 0.08);
|
|
65
65
|
}
|
|
66
66
|
.tool-card[data-tool="claude"]:hover:not(.disabled) {
|
|
67
|
-
border-color: rgba(
|
|
68
|
-
background: rgba(
|
|
67
|
+
border-color: rgba(var(--tool-claude-rgb), 0.5);
|
|
68
|
+
background: rgba(var(--tool-claude-rgb), 0.08);
|
|
69
69
|
}
|
|
70
70
|
.tool-card[data-tool="codex"]:hover:not(.disabled) {
|
|
71
|
-
border-color: rgba(
|
|
72
|
-
background: rgba(
|
|
71
|
+
border-color: rgba(var(--tool-codex-rgb), 0.5);
|
|
72
|
+
background: rgba(var(--tool-codex-rgb), 0.08);
|
|
73
73
|
}
|
|
74
74
|
.tool-card[data-tool="copilot"]:hover:not(.disabled) {
|
|
75
|
-
border-color: rgba(
|
|
76
|
-
background: rgba(
|
|
75
|
+
border-color: rgba(var(--tool-copilot-rgb), 0.5);
|
|
76
|
+
background: rgba(var(--tool-copilot-rgb), 0.08);
|
|
77
77
|
}
|
|
78
78
|
.tool-card[data-tool="gemini"]:hover:not(.disabled) {
|
|
79
|
-
border-color: rgba(
|
|
80
|
-
background: rgba(
|
|
79
|
+
border-color: rgba(var(--tool-gemini-rgb), 0.5);
|
|
80
|
+
background: rgba(var(--tool-gemini-rgb), 0.08);
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
/* Focus visible for keyboard navigation */
|
|
@@ -112,20 +112,20 @@
|
|
|
112
112
|
|
|
113
113
|
/* Per-tool brand color hover for installable cards (softer than available) */
|
|
114
114
|
.tool-card.installable[data-tool="claude"]:hover {
|
|
115
|
-
border-color: rgba(
|
|
116
|
-
background: rgba(
|
|
115
|
+
border-color: rgba(var(--tool-claude-rgb), 0.3);
|
|
116
|
+
background: rgba(var(--tool-claude-rgb), 0.04);
|
|
117
117
|
}
|
|
118
118
|
.tool-card.installable[data-tool="codex"]:hover {
|
|
119
|
-
border-color: rgba(
|
|
120
|
-
background: rgba(
|
|
119
|
+
border-color: rgba(var(--tool-codex-rgb), 0.3);
|
|
120
|
+
background: rgba(var(--tool-codex-rgb), 0.04);
|
|
121
121
|
}
|
|
122
122
|
.tool-card.installable[data-tool="copilot"]:hover {
|
|
123
|
-
border-color: rgba(
|
|
124
|
-
background: rgba(
|
|
123
|
+
border-color: rgba(var(--tool-copilot-rgb), 0.3);
|
|
124
|
+
background: rgba(var(--tool-copilot-rgb), 0.04);
|
|
125
125
|
}
|
|
126
126
|
.tool-card.installable[data-tool="gemini"]:hover {
|
|
127
|
-
border-color: rgba(
|
|
128
|
-
background: rgba(
|
|
127
|
+
border-color: rgba(var(--tool-gemini-rgb), 0.3);
|
|
128
|
+
background: rgba(var(--tool-gemini-rgb), 0.04);
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
/* Expanded state */
|
|
@@ -474,6 +474,30 @@
|
|
|
474
474
|
margin-bottom: var(--space-2);
|
|
475
475
|
}
|
|
476
476
|
|
|
477
|
+
/* Machine-identity chip — reads like a live terminal status badge */
|
|
478
|
+
.start-prompt-identity {
|
|
479
|
+
display: inline-flex;
|
|
480
|
+
align-items: center;
|
|
481
|
+
gap: var(--space-2);
|
|
482
|
+
margin-bottom: var(--space-3);
|
|
483
|
+
padding: var(--space-1) var(--space-3);
|
|
484
|
+
border: 1px solid var(--border-subtle);
|
|
485
|
+
border-radius: var(--radius-full);
|
|
486
|
+
background: var(--surface-secondary);
|
|
487
|
+
color: var(--text-secondary);
|
|
488
|
+
font-family: var(--font-mono);
|
|
489
|
+
font-size: var(--text-sm);
|
|
490
|
+
font-weight: var(--weight-medium);
|
|
491
|
+
}
|
|
492
|
+
.start-prompt-identity[hidden] { display: none; }
|
|
493
|
+
.start-prompt-identity-dot {
|
|
494
|
+
width: 7px;
|
|
495
|
+
height: 7px;
|
|
496
|
+
border-radius: 50%;
|
|
497
|
+
background: var(--status-success);
|
|
498
|
+
flex: 0 0 auto;
|
|
499
|
+
}
|
|
500
|
+
|
|
477
501
|
/* Start prompt subtitle */
|
|
478
502
|
.start-prompt-subtitle {
|
|
479
503
|
color: var(--text-muted);
|