claude-simple 0.2.12 → 0.2.14

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-simple",
3
- "version": "0.2.12",
3
+ "version": "0.2.14",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "claude-simple": "server.js",
@@ -40,6 +40,7 @@
40
40
  "jszip": "^3.10.1",
41
41
  "mammoth": "^1.8.0",
42
42
  "marked": "^9.1.6",
43
+ "mermaid": "^11.17.1",
43
44
  "pdfjs-dist": "^3.11.174",
44
45
  "ws": "^8.16.0",
45
46
  "xlsx": "^0.18.5"
@@ -5,6 +5,7 @@
5
5
  import { esc, $ } from './lib.js';
6
6
  import { api, authHeaders, currentMachineId } from './api.js';
7
7
  import { hubMode, ctx, currentAgent, currentProject } from './state.js';
8
+ import { renderMermaid } from './mermaid.js';
8
9
 
9
10
  let panelOpen = false;
10
11
  let mode = 'chat'; // chat | report | history | config
@@ -35,10 +36,13 @@ function mdHtml(text) {
35
36
  }
36
37
 
37
38
  function highlight(root) {
38
- if (!root || typeof hljs === 'undefined') return;
39
- root.querySelectorAll('pre code').forEach((el) => {
40
- try { hljs.highlightElement(el); } catch {}
41
- });
39
+ if (!root) return;
40
+ if (typeof hljs !== 'undefined') {
41
+ root.querySelectorAll('pre code').forEach((el) => {
42
+ try { hljs.highlightElement(el); } catch {}
43
+ });
44
+ }
45
+ renderMermaid(root);
42
46
  }
43
47
 
44
48
  /** Fetch SSE with auth (+ hub machine routing). */
package/public/chat.js CHANGED
@@ -6,6 +6,7 @@ import { ctx, isProcessing, currentProject, currentTab, currentModel, currentEff
6
6
  import { sendWs, api, authHeaders, flushWsQueue, clearWsQueue } from './api.js';
7
7
  import { initWakeLock, setWakeLockDesired } from './wake-lock.js';
8
8
  import { pushNotification } from './notifications.js';
9
+ import { renderMermaid } from './mermaid.js';
9
10
 
10
11
  function assistantLabel() {
11
12
  return AGENT_LABELS[currentAgent.peek()] || 'Assistant';
@@ -513,7 +514,7 @@ function finalizeAssistantStream() {
513
514
  liveAsstBody.classList.remove('whitespace-pre-wrap');
514
515
  liveAsstBody.classList.add('md');
515
516
  liveAsstBody.innerHTML = renderMarkdown(text);
516
- highlightCode(liveAsstEl);
517
+ enhanceMarkdown(liveAsstEl);
517
518
  } else {
518
519
  liveAsstEl.remove();
519
520
  }
@@ -1005,7 +1006,7 @@ export function appendMsg(role, _label, text, opts = {}) {
1005
1006
  if (!msgs) return;
1006
1007
  const ts = coerceTs(opts.ts) ?? (role === 'system' ? null : Date.now());
1007
1008
  msgs.insertAdjacentHTML('beforeend', bubbleHtml(role, text, ts));
1008
- highlightCode(msgs.lastElementChild);
1009
+ enhanceMarkdown(msgs.lastElementChild);
1009
1010
  stickBottom(msgs, role === 'user');
1010
1011
  }
1011
1012
 
@@ -1523,6 +1524,11 @@ function highlightCode(root) {
1523
1524
  });
1524
1525
  }
1525
1526
 
1527
+ function enhanceMarkdown(root) {
1528
+ highlightCode(root);
1529
+ renderMermaid(root);
1530
+ }
1531
+
1526
1532
  // ── Init (called after HTML is in DOM) ────────────────────────────────────────
1527
1533
  export function initChat() {
1528
1534
  applyChatDensity();
package/public/index.html CHANGED
@@ -82,7 +82,8 @@
82
82
  <script src="/vendor/marked.min.js"></script>
83
83
  <link id="hljs-theme" rel="stylesheet" href="/vendor/highlight-dark.min.css">
84
84
  <script src="/vendor/highlight.min.js"></script>
85
- <link rel="stylesheet" href="style.css?v=ui-12">
85
+ <script src="/vendor/mermaid.min.js"></script>
86
+ <link rel="stylesheet" href="style.css?v=ui-14">
86
87
  </head>
87
88
  <body class="h-dvh overflow-hidden flex flex-col bg-base-100 text-base-content">
88
89
  <div id="root" class="flex flex-col flex-1 overflow-hidden"></div>
@@ -98,6 +99,6 @@
98
99
  }
99
100
  }, 10000);
100
101
  </script>
101
- <script type="module" src="app.js?v=ui-12"></script>
102
+ <script type="module" src="app.js?v=ui-14"></script>
102
103
  </body>
103
104
  </html>
@@ -0,0 +1,48 @@
1
+ // Local Mermaid integration. It is loaded from /vendor in index.html so Hub
2
+ // diagrams keep working when public CDNs are unavailable.
3
+ let initialized = false;
4
+ let sequence = 0;
5
+
6
+ function setup() {
7
+ const api = globalThis.mermaid;
8
+ if (!api || initialized) return api;
9
+ api.initialize({
10
+ startOnLoad: false,
11
+ securityLevel: 'strict',
12
+ theme: document.documentElement.dataset.theme === 'dark' ? 'dark' : 'default',
13
+ flowchart: { htmlLabels: false },
14
+ });
15
+ initialized = true;
16
+ return api;
17
+ }
18
+
19
+ /** Render fenced ```mermaid blocks below a freshly-rendered Markdown root. */
20
+ export function renderMermaid(root) {
21
+ const api = setup();
22
+ if (!api || !root) return;
23
+ root.querySelectorAll('pre code.language-mermaid, pre code.lang-mermaid').forEach(code => {
24
+ if (code.dataset.mermaidHandled) return;
25
+ const pre = code.closest('pre');
26
+ const source = code.textContent?.trim();
27
+ if (!pre || !source) return;
28
+ code.dataset.mermaidHandled = '1';
29
+
30
+ const host = document.createElement('div');
31
+ host.className = 'mermaid-diagram';
32
+ host.setAttribute('role', 'img');
33
+ host.setAttribute('aria-label', 'Mermaid diagram');
34
+ pre.replaceWith(host);
35
+ const id = `mermaid-diagram-${++sequence}`;
36
+
37
+ Promise.resolve(api.render(id, source)).then(({ svg, bindFunctions }) => {
38
+ host.innerHTML = svg;
39
+ bindFunctions?.(host);
40
+ }).catch(error => {
41
+ // Syntax errors remain inspectable/copyable as the original code block.
42
+ host.replaceWith(pre);
43
+ delete code.dataset.mermaidHandled;
44
+ pre.classList.add('mermaid-error');
45
+ pre.title = `Mermaid render failed: ${error?.message || 'invalid diagram'}`;
46
+ });
47
+ });
48
+ }
package/public/state.js CHANGED
@@ -384,7 +384,6 @@ function asSessionArray(v) {
384
384
 
385
385
  /** Sessions after local filters (agent / time / workspace / text / favorites). */
386
386
  export const filteredSessions = computed(() => {
387
- const filter = sessionFilter.value;
388
387
  const search = sessionSearch.value.toLowerCase().trim();
389
388
  const sort = sessionSort.value;
390
389
  const aFilter = agentFilter.value;
@@ -398,7 +397,9 @@ export const filteredSessions = computed(() => {
398
397
  ? asSessionArray(hits.results)
399
398
  : asSessionArray(sessionsData.value);
400
399
 
401
- if (filter) list = list.filter(s => s && (s.cwd === filter || s.configDir === filter));
400
+ // `sessionFilter` is the active Files/Git workspace path. It must not
401
+ // constrain the sidebar: otherwise opening a session (or a session without
402
+ // a recorded cwd) makes every project folder disappear from the project UI.
402
403
  // Hub: only show sessions on the currently selected machine
403
404
  const mid = selectedMachineId.value;
404
405
  if (hubMode.value && mid) {
@@ -431,7 +432,7 @@ export const filteredSessions = computed(() => {
431
432
  });
432
433
 
433
434
  // Cap timeline dump when no filter/search
434
- if (!filter && !search && !favOnly) return list.slice(0, 120);
435
+ if (!search && !favOnly) return list.slice(0, 120);
435
436
  return list;
436
437
  });
437
438
 
package/public/style.css CHANGED
@@ -1153,6 +1153,13 @@ html.pwa-standalone .ma-panel {
1153
1153
  flex: 0 0 auto;
1154
1154
  }
1155
1155
  .topbar-icon-label { display: inline; }
1156
+ .mermaid-diagram {
1157
+ overflow-x: auto;
1158
+ padding: .75rem .25rem .25rem;
1159
+ text-align: center;
1160
+ }
1161
+ .mermaid-diagram svg { max-width: 100%; height: auto; }
1162
+ .mermaid-error { border-color: color-mix(in oklch, var(--color-error) 55%, var(--color-base-300)); }
1156
1163
  @media (max-width: 640px) {
1157
1164
  #recent-menu {
1158
1165
  min-width: 0;
package/public/sw.js CHANGED
@@ -1,19 +1,20 @@
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-v17';
4
+ const CACHE = 'agent-ui-shell-v19';
5
5
  const PRECACHE = [
6
6
  '/',
7
7
  '/index.html',
8
8
  '/manifest.webmanifest',
9
- '/style.css?v=ui-12',
9
+ '/style.css?v=ui-14',
10
10
  '/style.css',
11
11
  '/ui.min.css',
12
12
  '/vendor/mini-react.min.js',
13
13
  '/vendor/marked.min.js',
14
14
  '/vendor/highlight.min.js',
15
15
  '/vendor/highlight-dark.min.css',
16
- '/app.js?v=ui-12',
16
+ '/vendor/mermaid.min.js',
17
+ '/app.js?v=ui-14',
17
18
  '/icons/icon-192.png',
18
19
  '/icons/icon-512.png',
19
20
  '/icons/icon-maskable-512.png',