claude-simple 0.2.25 → 0.2.27

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.
@@ -7,6 +7,7 @@ export const AuthScreen = () => `
7
7
  <div class="card-body gap-3 p-8">
8
8
  <h1 class="text-xl font-bold">🤖 Agent UI</h1>
9
9
  <p id="auth-subtitle" class="text-sm text-base-content/60 mb-1">Claude · Codex · Grok · Gemini · Cursor</p>
10
+ <a href="/download/agentui-android.apk" class="btn btn-ghost btn-sm border border-base-300" download>下载 Android App</a>
10
11
  <form id="auth-form" class="flex flex-col gap-3" autocomplete="on" action="#">
11
12
  <label class="form-control">
12
13
  <div class="label py-1"><span class="label-text text-xs uppercase tracking-wide">Username</span></div>
@@ -79,8 +80,8 @@ export const AppShell = (opts = {}) => {
79
80
  <span id="topbar-project" class="text-sm text-base-content/50 flex-1 truncate min-w-0">Select a session</span>
80
81
  <span id="conn-dot" class="w-2 h-2 rounded-full bg-base-content/30 flex-shrink-0" title="连接状态"></span>
81
82
  <div class="flex gap-2 topbar-actions">
82
- <button id="btn-share-session" class="btn btn-ghost btn-xs border border-base-300" title="复制当前会话分享链接">分享</button>
83
83
  <button id="btn-pwa-install" class="btn btn-ghost btn-xs border border-base-300 hidden" title="安装到主屏幕">安装</button>
84
+ <a href="/download/agentui-android.apk" class="btn btn-ghost btn-xs border border-base-300" title="下载 Android APK" download>Android</a>
84
85
  <button id="btn-meta-agent" class="btn btn-ghost btn-xs border border-primary/40 text-primary topbar-icon-btn" title="Meta Agent — 报告 / 问答 / VLM" aria-label="打开 Meta Agent">
85
86
  <svg class="topbar-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" aria-hidden="true"><path d="m12 2 1.6 6.4L20 10l-6.4 1.6L12 18l-1.6-6.4L4 10l6.4-1.6L12 2Z"/><path d="m19 16 .7 2.3L22 19l-2.3.7L19 22l-.7-2.3L16 19l2.3-.7L19 16Z"/></svg><span class="topbar-icon-label">Agent</span>
86
87
  </button>
@@ -92,6 +93,10 @@ export const AppShell = (opts = {}) => {
92
93
  <button id="btn-logout" class="btn btn-ghost btn-xs border border-base-300">Sign out</button>
93
94
  </div>
94
95
  </div>
96
+ <button id="btn-expand-chat-chrome" class="chat-chrome-fab hidden" type="button"
97
+ title="显示会话工具栏" aria-label="显示会话工具栏">
98
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><path d="M7 14l5-5 5 5"/><path d="M5 19h14"/></svg>
99
+ </button>
95
100
  <!-- Fixed panel + backdrop: siblings of topbar so flex layout never clips them -->
96
101
  <div id="recent-menu-backdrop" class="hidden fixed inset-0 z-[55] bg-black/40" aria-hidden="true"></div>
97
102
  <div id="recent-menu" class="hidden fixed z-[60] w-80 max-h-[min(24rem,70vh)] overflow-y-auto
@@ -255,6 +260,7 @@ export const AppShell = (opts = {}) => {
255
260
  <div id="tab-chat" class="flex flex-col flex-1 overflow-hidden relative">
256
261
  <div id="project-notes-bar" class="bg-base-200 border-b border-base-300 px-3 py-1.5 text-xs flex flex-col gap-1" style="display:none"></div>
257
262
  <div id="session-notes-bar" class="bg-base-200/80 border-b border-base-300 px-3 py-1 text-xs flex justify-between items-center gap-2" style="display:none"></div>
263
+ <div id="session-lock-banner" class="session-lock-banner hidden px-3 py-1.5 text-[11px] text-center border-b"></div>
258
264
  <div id="ws-banner" class="hidden px-3 py-1.5 text-[11px] text-center bg-warning/15 text-warning border-b border-warning/20 flex items-center justify-center gap-2">
259
265
  <span id="ws-banner-text"></span>
260
266
  <button type="button" id="ws-banner-retry" class="btn btn-ghost btn-xs h-6 min-h-0 px-2 text-warning border border-warning/30">重连</button>
package/public/shell.js CHANGED
@@ -78,7 +78,8 @@ function showPwaInstallHelp() {
78
78
  <li>点右上角菜单 <strong>⋮</strong></li>
79
79
  <li>选择 <strong>安装应用</strong> 或 <strong>添加到主屏幕</strong></li>
80
80
  </ol>
81
- <p class="text-xs text-base-content/50 mt-3">若菜单里没有该项:请用 <strong>Chrome</strong> 打开,并先接受本站证书提示。自签 HTTPS 下部分机型不弹出一键安装。</p>`;
81
+ <p class="text-xs text-base-content/50 mt-3">若菜单里没有该项:请用 <strong>Chrome</strong> 打开,并先接受本站证书提示。自签 HTTPS 下部分机型不弹出一键安装。</p>
82
+ <a class="btn btn-primary btn-sm mt-4" href="/download/agentui-android.apk" download>下载 Android APK</a>`;
82
83
  } else {
83
84
  body = `<p class="text-sm text-base-content/80">请在浏览器菜单中选择 <strong>安装应用 / 安装网页应用 / 添加到主屏幕</strong>。</p>
84
85
  <p class="text-xs text-base-content/50 mt-3">Chrome / Edge 地址栏右侧有时也会出现安装图标。</p>`;
@@ -310,6 +311,12 @@ export function initShell(opts = {}) {
310
311
  initSidebarResize();
311
312
  initSidebarToggle();
312
313
  initNotifications({ openSession: resumeSession });
314
+ const setChatChromeCollapsed = (collapsed) => {
315
+ $('app')?.classList.toggle('chat-chrome-collapsed', collapsed);
316
+ $('btn-expand-chat-chrome')?.classList.toggle('hidden', !collapsed);
317
+ localStorage.setItem('chatChromeCollapsed', collapsed ? '1' : '0');
318
+ };
319
+ setChatChromeCollapsed(localStorage.getItem('chatChromeCollapsed') === '1');
313
320
 
314
321
  let sessionsChangedTimer = null;
315
322
  document.addEventListener('sessions-changed', () => {
@@ -336,13 +343,17 @@ export function initShell(opts = {}) {
336
343
  });
337
344
 
338
345
  delegate.on('click', '#btn-home', goHome);
339
- delegate.on('click', '#btn-share-session', async (_, el) => {
346
+ delegate.on('click', '#btn-share-session, #btn-share-session-current', async (_, el) => {
340
347
  const url = currentSessionShareUrl();
341
348
  if (!url) return;
342
349
  try {
343
350
  await navigator.clipboard.writeText(url);
344
- el.textContent = '已复制';
345
- setTimeout(() => { el.textContent = '分享'; }, 1400);
351
+ el.classList.add('is-copied');
352
+ el.title = '已复制分享链接';
353
+ setTimeout(() => {
354
+ el.classList.remove('is-copied');
355
+ el.title = '复制当前会话分享链接';
356
+ }, 1400);
346
357
  } catch {
347
358
  window.prompt('复制会话链接:', url);
348
359
  }
@@ -432,6 +443,8 @@ export function initShell(opts = {}) {
432
443
  document.getElementById('btn-pwa-install')?.classList.remove('hidden');
433
444
  });
434
445
  delegate.on('click', '#btn-settings', openSettings);
446
+ delegate.on('click', '#btn-collapse-chat-chrome', () => setChatChromeCollapsed(true));
447
+ delegate.on('click', '#btn-expand-chat-chrome', () => setChatChromeCollapsed(false));
435
448
  delegate.on('click', '#btn-meta-agent', () => toggleMetaAgent());
436
449
  delegate.on('click', '#btn-meta-agent-welcome', () => openMetaAgent('chat'));
437
450
  delegate.on('click', '#btn-theme', toggleTheme);
@@ -610,7 +623,7 @@ export function initShell(opts = {}) {
610
623
  });
611
624
  document.addEventListener('agent-changed', refreshModelSelect);
612
625
 
613
- delegate.on('click', '#btn-new-session, #btn-new-session-welcome', openNewSessionModal);
626
+ delegate.on('click', '#btn-new-session, #btn-new-session-current, #btn-new-session-welcome', openNewSessionModal);
614
627
  delegate.on('click', '#new-session-cancel', () => $('modal-new-session').close());
615
628
  delegate.on('click', '#new-session-start', startNewSession);
616
629
  delegate.on('change', '#new-session-agent', updateNewSessionAgentUI);
package/public/state.js CHANGED
@@ -108,6 +108,9 @@ export const ctx = {
108
108
  shellBubble: null,
109
109
  configDir: null,
110
110
  externalSessionReadOnly: false,
111
+ role: null,
112
+ username: null,
113
+ lock: { key: null, token: null, holder: null, held: false, foreign: false },
111
114
  };
112
115
 
113
116
  /** Select edge machine (hub). Keeps signal + ctx + localStorage in sync. */
package/public/style.css CHANGED
@@ -23,13 +23,17 @@
23
23
  #chat-input {
24
24
  min-height: 32px !important;
25
25
  max-height: 72px !important;
26
- padding: 0 !important;
26
+ padding: 8px 12px 4px !important;
27
27
  border-radius: 0.65rem 0.65rem 0 0;
28
28
  /* 16px prevents iOS Safari auto-zoom on focus */
29
29
  font-size: 16px !important;
30
30
  line-height: 1.4 !important;
31
31
  }
32
- .composer-icon-btn { width: 40px; height: 40px; font-size: 19px; }
32
+ /* Two fixed icon slots: settings + attachment never wrap below the input. */
33
+ .composer-tools { flex: 0 0 64px; flex-wrap: nowrap; gap: 0; }
34
+ .composer-icon-btn { width: 32px; height: 32px; min-width: 32px; font-size: 17px; }
35
+ .composer-actions { flex-wrap: nowrap; gap: .35rem; }
36
+ .composer-submit { min-width: 0; flex-shrink: 1; }
33
37
  .composer-send-btn, .composer-stop-btn { min-height: 40px; height: 40px; }
34
38
  .composer-hint { display: none; }
35
39
  #chat-opts {
@@ -541,6 +545,37 @@ html.pwa-standalone .ma-panel {
541
545
  white-space: pre;
542
546
  overflow-x: auto;
543
547
  }
548
+
549
+ /* Markdown files open as a rendered document; source remains one tap away. */
550
+ .file-markdown-toolbar {
551
+ display: flex;
552
+ gap: 0.25rem;
553
+ padding: 0.4rem 1rem;
554
+ border-bottom: 1px solid color-mix(in oklch, var(--color-base-content) 10%, transparent);
555
+ background: color-mix(in oklch, var(--color-base-200) 75%, transparent);
556
+ }
557
+ .file-markdown-mode {
558
+ border: 1px solid transparent;
559
+ border-radius: 0.375rem;
560
+ padding: 0.18rem 0.55rem;
561
+ color: color-mix(in oklch, var(--color-base-content) 58%, transparent);
562
+ background: transparent;
563
+ font-size: 0.72rem;
564
+ font-weight: 600;
565
+ cursor: pointer;
566
+ }
567
+ .file-markdown-mode:hover {
568
+ color: var(--color-base-content);
569
+ background: color-mix(in oklch, var(--color-base-content) 7%, transparent);
570
+ }
571
+ .file-markdown-mode.active {
572
+ color: var(--color-primary);
573
+ border-color: color-mix(in oklch, var(--color-primary) 35%, transparent);
574
+ background: color-mix(in oklch, var(--color-primary) 12%, transparent);
575
+ }
576
+ .file-markdown-preview {
577
+ min-height: 0;
578
+ }
544
579
  /* Reuse chat token palette outside .md so file preview is colored even if CDN theme lags */
545
580
  .file-preview .hljs-comment,
546
581
  .file-preview .hljs-quote {
@@ -1126,7 +1161,7 @@ html.pwa-standalone .ma-panel {
1126
1161
  width: 100%;
1127
1162
  min-height: 32px;
1128
1163
  max-height: 72px;
1129
- padding: 0;
1164
+ padding: 8px 12px 4px;
1130
1165
  border: 0;
1131
1166
  border-radius: 0.75rem 0.75rem 0 0;
1132
1167
  background: transparent;
@@ -1184,6 +1219,51 @@ html.pwa-standalone .ma-panel {
1184
1219
  flex: 0 0 auto;
1185
1220
  }
1186
1221
  .topbar-icon-label { display: inline; }
1222
+ .session-title-actions { margin-left: .1rem; }
1223
+ #session-notes-text { min-width: 0; flex: 1 1 4rem; }
1224
+ .session-bar-icon,
1225
+ #session-notes-bar .session-hide-btn {
1226
+ width: 26px;
1227
+ height: 26px;
1228
+ padding: 0;
1229
+ display: inline-flex;
1230
+ align-items: center;
1231
+ justify-content: center;
1232
+ border: 0;
1233
+ border-radius: .4rem;
1234
+ background: transparent;
1235
+ color: color-mix(in oklch, var(--color-base-content) 62%, transparent);
1236
+ cursor: pointer;
1237
+ }
1238
+ .session-bar-icon:hover,
1239
+ #session-notes-bar .session-hide-btn:hover { background: color-mix(in oklch, var(--color-base-content) 9%, transparent); color: var(--color-base-content); }
1240
+ .session-bar-icon.is-copied { color: var(--color-success); }
1241
+ .session-bar-icon svg,
1242
+ #session-notes-bar .session-hide-btn svg,
1243
+ .chat-chrome-fab svg { width: 15px; height: 15px; }
1244
+ .chat-chrome-fab {
1245
+ position: fixed;
1246
+ top: max(.6rem, env(safe-area-inset-top, 0px));
1247
+ left: max(.6rem, env(safe-area-inset-left, 0px));
1248
+ z-index: 40;
1249
+ width: 34px;
1250
+ height: 34px;
1251
+ display: inline-flex;
1252
+ align-items: center;
1253
+ justify-content: center;
1254
+ border: 1px solid color-mix(in oklch, var(--color-base-content) 16%, transparent);
1255
+ border-radius: 999px;
1256
+ color: var(--color-base-content);
1257
+ background: color-mix(in oklch, var(--color-base-100) 88%, transparent);
1258
+ box-shadow: 0 4px 14px color-mix(in oklch, black 24%, transparent);
1259
+ }
1260
+ .chat-chrome-fab.hidden { display: none; }
1261
+ #app.chat-chrome-collapsed #topbar,
1262
+ #app.chat-chrome-collapsed #project-view > .flex.bg-base-200,
1263
+ #app.chat-chrome-collapsed #project-notes-bar,
1264
+ #app.chat-chrome-collapsed #session-notes-bar,
1265
+ #app.chat-chrome-collapsed #session-lock-banner,
1266
+ #app.chat-chrome-collapsed #ws-banner { display: none !important; }
1187
1267
  .mermaid-diagram {
1188
1268
  overflow-x: auto;
1189
1269
  padding: .75rem .25rem .25rem;
@@ -1749,3 +1829,21 @@ html.settings-open #app { visibility: hidden; }
1749
1829
  .set-nav { flex-direction: row; overflow-x: auto; gap: 0.25rem; }
1750
1830
  .set-nav-item { white-space: nowrap; }
1751
1831
  }
1832
+
1833
+ /* Overlays must not eat keystrokes when hidden */
1834
+ #sidebar-overlay.hidden,
1835
+ .mermaid-zoom-overlay.hidden,
1836
+ #session-lock-banner.hidden {
1837
+ display: none !important;
1838
+ pointer-events: none !important;
1839
+ }
1840
+ #session-lock-banner {
1841
+ background: color-mix(in oklch, var(--color-warning) 16%, var(--color-base-200));
1842
+ color: color-mix(in oklch, var(--color-warning) 80%, var(--color-base-content));
1843
+ pointer-events: none;
1844
+ }
1845
+ #chat-input:disabled,
1846
+ #chat-input[readonly] {
1847
+ cursor: not-allowed;
1848
+ opacity: .78;
1849
+ }
package/public/sw.js CHANGED
@@ -1,12 +1,12 @@
1
1
  /* Agent UI service worker — cache shell assets only.
2
2
  * Never intercepts WebSocket or mutates API semantics beyond offline fallback.
3
3
  * Bump CACHE when shipping UI that must invalidate old shells. */
4
- const CACHE = 'agent-ui-shell-v25';
4
+ const CACHE = 'agent-ui-shell-v27';
5
5
  const PRECACHE = [
6
6
  '/',
7
7
  '/index.html',
8
8
  '/manifest.webmanifest',
9
- '/style.css?v=ui-20',
9
+ '/style.css?v=ui-22',
10
10
  '/style.css',
11
11
  '/ui.min.css',
12
12
  '/vendor/mini-react.min.js',
@@ -16,7 +16,7 @@ const PRECACHE = [
16
16
  '/vendor/mermaid.min.js',
17
17
  '/vendor/katex.min.js',
18
18
  '/vendor/katex.min.css',
19
- '/app.js?v=ui-20',
19
+ '/app.js?v=ui-22',
20
20
  '/icons/icon-192.png',
21
21
  '/icons/icon-512.png',
22
22
  '/icons/icon-maskable-512.png',