clay-server 4.0.0-beta.2 → 4.0.0-beta.21
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/lib/background-task-timing.js +105 -0
- package/lib/capsule-display-floor.js +51 -0
- package/lib/capsule-frame-server.js +255 -0
- package/lib/capsule-mate-turn.js +105 -0
- package/lib/capsule-pig-logic.js +300 -0
- package/lib/capsule-server-runtimes.js +39 -0
- package/lib/capsules/pig/display.js +198 -0
- package/lib/capsules/pig/manifest.json +9 -0
- package/lib/capsules/pig/ui.json +84 -0
- package/lib/config.js +25 -1
- package/lib/daemon-projects.js +13 -8
- package/lib/daemon.js +127 -14
- package/lib/git-cli.js +95 -1
- package/lib/knowledge-import.js +436 -0
- package/lib/knowledge-record-store.js +188 -0
- package/lib/knowledge-search.js +240 -0
- package/lib/mate-knowledge-mcp-server.js +151 -0
- package/lib/mate-knowledge-migration.js +283 -0
- package/lib/mate-knowledge-service.js +488 -0
- package/lib/mate-knowledge-sync.js +482 -0
- package/lib/migrate-single-user.js +2 -0
- package/lib/notes-lifecycle.js +149 -0
- package/lib/notes.js +60 -3
- package/lib/os-users.js +3 -1
- package/lib/project-capsule-catalog.js +9 -1
- package/lib/project-capsule-turn.js +96 -0
- package/lib/project-connection.js +14 -1
- package/lib/project-http.js +15 -1
- package/lib/project-knowledge.js +22 -0
- package/lib/project-log-context.js +172 -0
- package/lib/project-log-feedback-delivery.js +118 -0
- package/lib/project-logs-comments.js +137 -0
- package/lib/project-logs-context-state.js +42 -0
- package/lib/project-logs-mcp-server.js +328 -0
- package/lib/project-logs-query.js +185 -0
- package/lib/project-logs-root.js +75 -0
- package/lib/project-logs-schema.js +259 -0
- package/lib/project-logs-service.js +463 -0
- package/lib/project-logs-snapshot.js +205 -0
- package/lib/project-logs-store.js +495 -0
- package/lib/project-logs-versioning.js +132 -0
- package/lib/project-logs.js +400 -0
- package/lib/project-mate-interaction.js +14 -0
- package/lib/project-mate-knowledge.js +110 -0
- package/lib/project-memory.js +22 -0
- package/lib/project-message-delivery.js +70 -0
- package/lib/project-pair-lifecycle.js +460 -0
- package/lib/project-session-handoff.js +1 -1
- package/lib/project-session-notes.js +64 -13
- package/lib/project-session-pair.js +159 -146
- package/lib/project-session-spawn.js +1 -1
- package/lib/project-sessions.js +58 -13
- package/lib/project-user-message.js +53 -4
- package/lib/project-vendor-login.js +20 -3
- package/lib/project-worker-permission.js +430 -0
- package/lib/project-worker-proposal.js +208 -62
- package/lib/project.js +178 -6
- package/lib/public/app.js +58 -35
- package/lib/public/css/admin.css +2 -2
- package/lib/public/css/capsule-ui.css +38 -0
- package/lib/public/css/command-palette.css +19 -9
- package/lib/public/css/git-placard.css +154 -0
- package/lib/public/css/home-hub.css +4 -0
- package/lib/public/css/home-session-actions.css +66 -0
- package/lib/public/css/home-sidebar.css +66 -0
- package/lib/public/css/input.css +163 -28
- package/lib/public/css/mobile-nav.css +80 -0
- package/lib/public/css/notifications-center.css +67 -0
- package/lib/public/css/pane.css +52 -0
- package/lib/public/css/project-logs.css +198 -0
- package/lib/public/css/scheduler.css +1 -1
- package/lib/public/css/session-actions.css +16 -101
- package/lib/public/css/sidebar.css +103 -0
- package/lib/public/css/sticky-notes.css +237 -229
- package/lib/public/css/worker-proposal.css +34 -1
- package/lib/public/index.html +45 -11
- package/lib/public/modules/admin.js +8 -8
- package/lib/public/modules/app-connection.js +109 -4
- package/lib/public/modules/app-home-hub.js +19 -7
- package/lib/public/modules/app-message-cards.js +2 -1
- package/lib/public/modules/app-messages.js +84 -7
- package/lib/public/modules/app-misc.js +2 -14
- package/lib/public/modules/app-notifications.js +11 -7
- package/lib/public/modules/app-panels.js +46 -4
- package/lib/public/modules/app-projects.js +13 -8
- package/lib/public/modules/app-rendering.js +1 -0
- package/lib/public/modules/background-tasks-ui.js +139 -16
- package/lib/public/modules/capsule-preference.js +44 -0
- package/lib/public/modules/chat-bubble-renderer.js +1 -1
- package/lib/public/modules/clay-log-links.js +70 -0
- package/lib/public/modules/command-palette.js +52 -15
- package/lib/public/modules/context-sources.js +0 -3
- package/lib/public/modules/git-agent-sessions.js +85 -0
- package/lib/public/modules/git-panel.js +111 -84
- package/lib/public/modules/git-placard.js +161 -0
- package/lib/public/modules/home-chat-empty-state.js +39 -0
- package/lib/public/modules/home-chat-identity.js +9 -0
- package/lib/public/modules/home-conversations-sheet.js +102 -48
- package/lib/public/modules/home-mate-chat.js +15 -35
- package/lib/public/modules/home-session-actions.js +6 -0
- package/lib/public/modules/home-sidebar-chat-list.js +101 -41
- package/lib/public/modules/home-sidebar.js +7 -0
- package/lib/public/modules/home-tool-frame.js +182 -0
- package/lib/public/modules/home-tools.js +138 -1
- package/lib/public/modules/input.js +38 -7
- package/lib/public/modules/markdown.js +2 -0
- package/lib/public/modules/mate-sidebar.js +0 -8
- package/lib/public/modules/message-delivery.js +97 -0
- package/lib/public/modules/paste-modal.js +84 -0
- package/lib/public/modules/project-logs-render.js +405 -0
- package/lib/public/modules/project-logs.js +461 -0
- package/lib/public/modules/project-removal-target.js +26 -0
- package/lib/public/modules/scheduler.js +17 -3
- package/lib/public/modules/session-actions.js +29 -105
- package/lib/public/modules/session-hierarchy.js +54 -0
- package/lib/public/modules/sidebar-mobile.js +40 -15
- package/lib/public/modules/sidebar-session-hierarchy.js +214 -0
- package/lib/public/modules/sidebar-sessions.js +77 -11
- package/lib/public/modules/sidebar.js +17 -5
- package/lib/public/modules/split-group-helpers.js +8 -0
- package/lib/public/modules/split-view.js +5 -2
- package/lib/public/modules/sticky-note-markdown.js +5 -0
- package/lib/public/modules/sticky-notes-browser.js +326 -0
- package/lib/public/modules/sticky-notes-card.js +360 -0
- package/lib/public/modules/sticky-notes-editor.js +291 -0
- package/lib/public/modules/sticky-notes-shared.js +90 -0
- package/lib/public/modules/sticky-notes.js +170 -946
- package/lib/public/modules/tool-palette-order.js +143 -0
- package/lib/public/modules/tool-palette-overlays.js +159 -0
- package/lib/public/modules/tool-palette.js +21 -188
- package/lib/public/modules/tools.js +21 -1
- package/lib/public/modules/update-snooze.js +169 -0
- package/lib/public/modules/user-settings.js +4 -0
- package/lib/public/modules/worker-pane-lock.js +176 -0
- package/lib/public/modules/worker-proposal-state.js +16 -0
- package/lib/public/modules/worker-proposal.js +49 -12
- package/lib/public/style.css +3 -1
- package/lib/sdk-bridge.js +132 -46
- package/lib/sdk-message-processor.js +60 -14
- package/lib/server-experimental-settings.js +49 -0
- package/lib/server-global-ws.js +11 -0
- package/lib/server-home-chat-events.js +31 -1
- package/lib/server-home-chat.js +27 -4
- package/lib/server-home-clay-entry.js +1 -1
- package/lib/server-home-clay-session-links.js +34 -5
- package/lib/server-settings.js +5 -0
- package/lib/server-tools.js +127 -9
- package/lib/server.js +124 -18
- package/lib/session-driver-eligibility.js +38 -0
- package/lib/session-driver-orchestration.js +31 -0
- package/lib/session-hygiene.js +3 -0
- package/lib/session-notes-mcp-server.js +25 -5
- package/lib/session-pair-factory.js +247 -0
- package/lib/session-pair-mcp-server.js +46 -8
- package/lib/session-pair-prompts.js +79 -0
- package/lib/session-pair-turn-control.js +153 -0
- package/lib/session-provenance.js +119 -0
- package/lib/session-spawn-mcp-server.js +1 -1
- package/lib/session-split-groups.js +4 -1
- package/lib/session-title-policy.js +60 -0
- package/lib/session-visibility.js +39 -0
- package/lib/sessions.js +61 -11
- package/lib/tools-registry.js +89 -10
- package/lib/update-snooze.js +437 -0
- package/lib/users-experimental-preferences.js +30 -0
- package/lib/users-permissions.js +2 -2
- package/lib/users.js +22 -16
- package/lib/workspace-query-access.js +102 -0
- package/lib/workspace-query-service.js +24 -17
- package/lib/worktree.js +25 -38
- package/lib/ws-schema.js +38 -7
- package/lib/yoke/adapters/claude-worker.js +16 -6
- package/lib/yoke/adapters/claude.js +81 -4
- package/lib/yoke/adapters/codex.js +63 -15
- package/lib/yoke/codex-background-tasks.js +8 -2
- package/lib/yoke/vendor-registry.js +1 -1
- package/package.json +3 -3
package/lib/public/index.html
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
(function(){try{var k="clay-theme-vars",v=localStorage.getItem(k),r=document.documentElement;if(v){var o=JSON.parse(v),p;for(p in o)r.style.setProperty(p,o[p]);var vt=localStorage.getItem(k.replace("-vars","-variant"));if(vt==="light"){r.classList.add("light-theme");r.classList.remove("dark-theme")}else{r.classList.add("dark-theme");r.classList.remove("light-theme")}var m=document.querySelector('meta[name="theme-color"]');if(m&&o["--bg"])m.setAttribute("content",o["--bg"])}else{var sl=window.matchMedia&&window.matchMedia("(prefers-color-scheme: light)").matches;if(sl){r.classList.add("light-theme");r.classList.remove("dark-theme")}}}catch(e){}})();
|
|
32
32
|
</script>
|
|
33
33
|
<script>if(window.navigator.standalone||window.matchMedia("(display-mode:standalone)").matches){document.documentElement.classList.add("pwa-standalone")}</script>
|
|
34
|
-
<link rel="stylesheet" href="style.css?v=
|
|
34
|
+
<link rel="stylesheet" href="style.css?v=20260908-log-links2">
|
|
35
35
|
<style>
|
|
36
36
|
@media(max-width:768px){
|
|
37
37
|
/* User messages: vertical stack, avatar on top, right-aligned */
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
}
|
|
51
51
|
</style>
|
|
52
52
|
</head>
|
|
53
|
-
<body>
|
|
53
|
+
<body class="capsules-disabled">
|
|
54
54
|
<div id="layout">
|
|
55
55
|
<!-- === Top Bar (full width, forms reverse-ㄱ with icon strip) === -->
|
|
56
56
|
<div id="top-bar">
|
|
@@ -137,6 +137,7 @@
|
|
|
137
137
|
<nav class="home-sidebar-primary-actions" aria-label="Home actions">
|
|
138
138
|
<button id="home-sidebar-new" class="home-sidebar-action home-sidebar-new" type="button" title="New Chat" aria-label="Start a new chat with the current Mate" disabled><span class="home-sidebar-action-icon" aria-hidden="true"><i data-lucide="message-square-plus"></i></span><span>New Chat</span></button>
|
|
139
139
|
<button id="home-sidebar-debate" class="home-sidebar-action" type="button" title="Browse debates" aria-label="Browse debates" aria-pressed="false"><span class="home-sidebar-action-icon" aria-hidden="true"><i data-lucide="messages-square"></i></span><span>Debates</span></button>
|
|
140
|
+
<button id="home-scheduler-btn" class="home-sidebar-action" type="button" title="Scheduled Tasks" aria-label="Scheduled Tasks"><span class="home-sidebar-action-icon" aria-hidden="true"><i data-lucide="calendar-clock"></i></span><span>Scheduled Tasks</span></button>
|
|
140
141
|
<button id="home-tools-btn" class="home-sidebar-action" type="button" title="Capsules" aria-label="Capsules" aria-expanded="false" aria-controls="home-tool-workbench"><span class="home-sidebar-action-icon" aria-hidden="true"><i data-lucide="box"></i></span><span id="home-tools-label">Capsules</span><span id="home-tools-activity" class="home-tools-activity" aria-hidden="true"></span></button>
|
|
141
142
|
</nav>
|
|
142
143
|
<section class="home-sidebar-section home-sidebar-mate-section" aria-labelledby="home-sidebar-mate-label">
|
|
@@ -246,6 +247,15 @@
|
|
|
246
247
|
</div>
|
|
247
248
|
<div id="session-actions"></div>
|
|
248
249
|
<div id="session-actions-hidden" class="tool-palette-hidden-section hidden"></div>
|
|
250
|
+
<!-- Repository placard. Hidden until a real Git repository is
|
|
251
|
+
confirmed, so non-Git projects and pending detection show
|
|
252
|
+
nothing rather than an empty block. -->
|
|
253
|
+
<div id="git-placard" class="git-placard hidden" role="group">
|
|
254
|
+
<div id="git-placard-body" class="git-placard-body" aria-hidden="true"></div>
|
|
255
|
+
<button id="git-placard-more" class="git-placard-more" type="button" aria-label="Open Git panel for more repository detail" title="More Git detail">
|
|
256
|
+
<span>More</span><i data-lucide="chevron-right"></i>
|
|
257
|
+
</button>
|
|
258
|
+
</div>
|
|
249
259
|
</div>
|
|
250
260
|
<div id="sidebar-sessions-header">
|
|
251
261
|
<div id="sessions-header-content">
|
|
@@ -412,9 +422,6 @@
|
|
|
412
422
|
<div id="ralph-sticky" class="hidden"></div>
|
|
413
423
|
<div id="debate-sticky" class="hidden"></div>
|
|
414
424
|
<div class="status">
|
|
415
|
-
<button id="header-session-actions-btn" type="button" aria-label="Session actions" aria-haspopup="menu" aria-expanded="false">
|
|
416
|
-
<i data-lucide="bot"></i><span>Add Split Worker</span><i class="session-actions-trigger-chevron" data-lucide="chevron-down"></i>
|
|
417
|
-
</button>
|
|
418
425
|
<button type="button" id="header-tui-font-btn" class="header-tui-font-btn hidden" title="Terminal font" aria-label="Terminal font">
|
|
419
426
|
<i data-lucide="type"></i>
|
|
420
427
|
</button>
|
|
@@ -501,12 +508,14 @@
|
|
|
501
508
|
<div class="usage-section-label">Session Tokens</div>
|
|
502
509
|
<div class="usage-row"><span class="usage-label">Input</span><span id="context-input" class="usage-value">0</span></div>
|
|
503
510
|
<div class="usage-row"><span class="usage-label">Output</span><span id="context-output" class="usage-value">0</span></div>
|
|
511
|
+
<div class="usage-row hidden" id="context-thinking-row" title="Extended thinking tokens, already counted inside Output"><span class="usage-label">Thinking</span><span id="context-thinking" class="usage-value">0</span></div>
|
|
504
512
|
<div class="usage-row"><span class="usage-label">Cache read</span><span id="context-cache-read" class="usage-value">0</span></div>
|
|
505
513
|
<div class="usage-row"><span class="usage-label">Cache write</span><span id="context-cache-write" class="usage-value">0</span></div>
|
|
506
514
|
<div class="usage-divider"></div>
|
|
507
515
|
<div class="usage-section-label">Model</div>
|
|
508
516
|
<div class="usage-row"><span class="usage-label">Name</span><span id="context-model" class="usage-value">-</span></div>
|
|
509
517
|
<div class="usage-row"><span class="usage-label">Cost</span><span id="context-cost" class="usage-value">$0.0000</span></div>
|
|
518
|
+
<div class="usage-row hidden" id="context-cost-basis-row" title="Which price table this cost was computed from"><span class="usage-label">Priced at</span><span id="context-cost-basis" class="usage-value">-</span></div>
|
|
510
519
|
<div class="usage-row"><span class="usage-label">Turns</span><span id="context-turns" class="usage-value">0</span></div>
|
|
511
520
|
</div>
|
|
512
521
|
</div>
|
|
@@ -539,13 +548,15 @@
|
|
|
539
548
|
<button id="schedule-btn" type="button" aria-label="Schedule message" title="Schedule message"><i data-lucide="clock"></i></button>
|
|
540
549
|
<button id="ask-mate-btn" type="button" aria-label="Ask Mate" title="Ask a Mate for advice on this session"><i data-lucide="at-sign"></i></button>
|
|
541
550
|
<div id="context-sources-btn-wrap" class="desktop-only">
|
|
542
|
-
<button id="context-sources-add" type="button" title="Add context sources"><i data-lucide="library"></i
|
|
551
|
+
<button id="context-sources-add" type="button" aria-label="Add context" title="Add context sources"><i data-lucide="library"></i></button>
|
|
543
552
|
<div id="context-sources-picker" class="hidden">
|
|
544
553
|
<div class="context-picker-section" id="context-picker-email"></div>
|
|
545
554
|
<div class="context-picker-section" id="context-picker-terminals"></div>
|
|
546
555
|
<div class="context-picker-section" id="context-picker-tabs"></div>
|
|
547
556
|
</div>
|
|
548
557
|
</div>
|
|
558
|
+
<button id="composer-add-worker-btn" type="button" class="composer-session-action desktop-only" aria-label="Add Split Worker" title="Add Split Worker"><i data-lucide="bot"></i></button>
|
|
559
|
+
<button id="composer-handoff-btn" type="button" class="composer-session-action desktop-only" aria-label="Continue in another agent" title="Continue in another agent"><i data-lucide="send"></i></button>
|
|
549
560
|
</div>
|
|
550
561
|
<div id="input-bottom-right">
|
|
551
562
|
<div id="active-vendor-indicator" class="hidden" title="Session vendor">
|
|
@@ -996,6 +1007,7 @@
|
|
|
996
1007
|
<option value="us-appearance">Appearance</option>
|
|
997
1008
|
<option value="us-chat">Chat</option>
|
|
998
1009
|
<option value="us-mates">Mates</option>
|
|
1010
|
+
<option value="us-experimental">Experimental</option>
|
|
999
1011
|
<option value="us-email">Email</option>
|
|
1000
1012
|
</select>
|
|
1001
1013
|
<div class="us-modal-nav-items">
|
|
@@ -1003,6 +1015,7 @@
|
|
|
1003
1015
|
<button class="us-nav-item" data-section="us-appearance"><span>Appearance</span></button>
|
|
1004
1016
|
<button class="us-nav-item" data-section="us-chat"><span>Chat</span></button>
|
|
1005
1017
|
<button class="us-nav-item" data-section="us-mates"><span>Mates</span></button>
|
|
1018
|
+
<button class="us-nav-item" data-section="us-experimental"><span>Experimental</span></button>
|
|
1006
1019
|
<button class="us-nav-item" data-section="us-email"><span>Email</span></button>
|
|
1007
1020
|
<div class="us-nav-separator"></div>
|
|
1008
1021
|
<button class="us-nav-item us-nav-danger" data-section="us-logout"><span>Log Out</span></button>
|
|
@@ -1158,6 +1171,22 @@
|
|
|
1158
1171
|
</div>
|
|
1159
1172
|
</div>
|
|
1160
1173
|
|
|
1174
|
+
<!-- Experimental section -->
|
|
1175
|
+
<div class="us-section" data-section="us-experimental">
|
|
1176
|
+
<h2>Experimental</h2>
|
|
1177
|
+
<p class="settings-hint">Preview features may change or behave unexpectedly.</p>
|
|
1178
|
+
<div class="settings-card">
|
|
1179
|
+
<label class="settings-toggle-row">
|
|
1180
|
+
<div>
|
|
1181
|
+
<span class="settings-label">Capsules</span>
|
|
1182
|
+
<div class="settings-hint">Enable persistent mini-apps that you and your Mates can use.</div>
|
|
1183
|
+
</div>
|
|
1184
|
+
<input type="checkbox" id="us-capsules-enabled">
|
|
1185
|
+
<span class="toggle-track"><span class="toggle-thumb"></span></span>
|
|
1186
|
+
</label>
|
|
1187
|
+
</div>
|
|
1188
|
+
</div>
|
|
1189
|
+
|
|
1161
1190
|
<!-- Email section -->
|
|
1162
1191
|
<div class="us-section" data-section="us-email">
|
|
1163
1192
|
<h2>Email Accounts</h2>
|
|
@@ -1514,17 +1543,22 @@
|
|
|
1514
1543
|
</div>
|
|
1515
1544
|
</div>
|
|
1516
1545
|
|
|
1517
|
-
<div id="paste-modal" class="hidden">
|
|
1546
|
+
<div id="paste-modal" class="hidden" role="dialog" aria-modal="true" aria-labelledby="paste-modal-title">
|
|
1518
1547
|
<div class="confirm-backdrop"></div>
|
|
1519
1548
|
<div class="confirm-dialog paste-modal-dialog">
|
|
1520
1549
|
<div class="paste-modal-header">
|
|
1521
|
-
<span class="paste-modal-title">Pasted content</span>
|
|
1550
|
+
<span class="paste-modal-title" id="paste-modal-title">Pasted content</span>
|
|
1522
1551
|
<div class="paste-modal-actions">
|
|
1523
|
-
<button class="paste-modal-copy" title="Copy to clipboard"><i data-lucide="copy" style="width:15px;height:15px"></i></button>
|
|
1524
|
-
<button class="paste-modal-close"><i data-lucide="x" style="width:16px;height:16px"></i></button>
|
|
1552
|
+
<button class="paste-modal-copy" type="button" title="Copy to clipboard" aria-label="Copy pasted content"><i data-lucide="copy" style="width:15px;height:15px"></i></button>
|
|
1553
|
+
<button class="paste-modal-close" type="button" aria-label="Close pasted content"><i data-lucide="x" style="width:16px;height:16px"></i></button>
|
|
1525
1554
|
</div>
|
|
1526
1555
|
</div>
|
|
1527
1556
|
<pre class="paste-modal-body" id="paste-modal-body"></pre>
|
|
1557
|
+
<textarea class="paste-modal-editor" id="paste-modal-editor" aria-label="Pasted content"></textarea>
|
|
1558
|
+
<div class="paste-modal-footer" id="paste-modal-footer">
|
|
1559
|
+
<button class="paste-modal-cancel" type="button">Cancel</button>
|
|
1560
|
+
<button class="paste-modal-save" id="paste-modal-save" type="button">Save changes</button>
|
|
1561
|
+
</div>
|
|
1528
1562
|
</div>
|
|
1529
1563
|
</div>
|
|
1530
1564
|
|
|
@@ -2303,7 +2337,7 @@
|
|
|
2303
2337
|
<script src="https://cdn.jsdelivr.net/npm/@xterm/addon-fit@0/lib/addon-fit.min.js"></script>
|
|
2304
2338
|
<script src="https://cdn.jsdelivr.net/npm/@xterm/addon-web-links@0/lib/addon-web-links.min.js"></script>
|
|
2305
2339
|
<script src="https://cdn.jsdelivr.net/npm/@xterm/addon-webgl@0/lib/addon-webgl.min.js"></script>
|
|
2306
|
-
<script type="module" src="app.js?v=
|
|
2340
|
+
<script type="module" src="app.js?v=20260908-log-links2"></script>
|
|
2307
2341
|
<div id="pwa-install-modal" class="pwa-modal hidden">
|
|
2308
2342
|
<div class="pwa-modal-backdrop"></div>
|
|
2309
2343
|
<div class="pwa-modal-card">
|
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
import { iconHtml, refreshIcons } from './icons.js';
|
|
3
3
|
import { showToast, copyToClipboard, escapeHtml } from './utils.js';
|
|
4
4
|
|
|
5
|
-
function showConfirmDialog(message, onConfirm) {
|
|
5
|
+
function showConfirmDialog(message, actionLabel, onConfirm) {
|
|
6
6
|
var modal = document.createElement("div");
|
|
7
7
|
modal.className = "admin-modal-overlay";
|
|
8
|
-
var html = '<div class="admin-modal">' +
|
|
8
|
+
var html = '<div class="admin-modal" role="dialog" aria-modal="true" aria-label="Confirm action">' +
|
|
9
9
|
'<div class="admin-modal-body" style="padding:20px 16px 16px">' +
|
|
10
10
|
'<p class="admin-modal-desc" style="margin:0;font-size:14px;color:var(--text)">' + escapeHtml(message) + '</p>' +
|
|
11
11
|
'</div>' +
|
|
12
12
|
'<div class="admin-modal-footer">' +
|
|
13
|
-
'<button class="admin-modal-save admin-modal-confirm-danger">
|
|
13
|
+
'<button class="admin-modal-save admin-modal-confirm-danger">' + escapeHtml(actionLabel) + '</button>' +
|
|
14
14
|
'<button class="admin-modal-cancel">Cancel</button>' +
|
|
15
15
|
'</div></div>';
|
|
16
16
|
modal.innerHTML = html;
|
|
@@ -198,9 +198,9 @@ function renderUsersTab(body) {
|
|
|
198
198
|
var userId = this.dataset.userId;
|
|
199
199
|
var user = cachedUsers.find(function (u) { return u.id === userId; });
|
|
200
200
|
var name = user ? (user.displayName || user.username) : "this user";
|
|
201
|
-
|
|
201
|
+
showConfirmDialog("Remove " + name + "? This cannot be undone.", "Remove user", function () {
|
|
202
202
|
removeUser(userId, body);
|
|
203
|
-
}
|
|
203
|
+
});
|
|
204
204
|
});
|
|
205
205
|
}
|
|
206
206
|
}
|
|
@@ -509,7 +509,7 @@ function renderInvitesTab(body) {
|
|
|
509
509
|
revokeBtns[k].addEventListener("click", function () {
|
|
510
510
|
var code = this.dataset.code;
|
|
511
511
|
var btn = this;
|
|
512
|
-
showConfirmDialog("Revoke this invite? The link will no longer work.", function () {
|
|
512
|
+
showConfirmDialog("Revoke this invite? The link will no longer work.", "Revoke", function () {
|
|
513
513
|
btn.disabled = true;
|
|
514
514
|
fetch("/api/admin/invites/" + encodeURIComponent(code), { method: "DELETE" })
|
|
515
515
|
.then(function (r) { return r.json(); })
|
|
@@ -751,12 +751,12 @@ function renderSmtpTab(body, cfg) {
|
|
|
751
751
|
var removeBtn = body.querySelector("#smtp-remove");
|
|
752
752
|
if (removeBtn) {
|
|
753
753
|
removeBtn.addEventListener("click", function () {
|
|
754
|
-
|
|
754
|
+
showConfirmDialog("Remove SMTP configuration? Users will need to use PIN login.", "Remove SMTP", function () {
|
|
755
755
|
apiPost("/api/admin/smtp", { host: "", user: "", pass: "", from: "" }).then(function () {
|
|
756
756
|
showToast("SMTP configuration removed");
|
|
757
757
|
loadSmtpTab(body);
|
|
758
758
|
});
|
|
759
|
-
}
|
|
759
|
+
});
|
|
760
760
|
});
|
|
761
761
|
}
|
|
762
762
|
}
|
|
@@ -23,8 +23,80 @@ var connectTimeoutId = null;
|
|
|
23
23
|
var connectOverlay = null;
|
|
24
24
|
var hasConnectedOnce = false;
|
|
25
25
|
|
|
26
|
+
// The connect overlay is a full-viewport opaque panel. Revealing it for a
|
|
27
|
+
// reconnect that resolves in under a second reads as the whole screen
|
|
28
|
+
// blinking, so after the first successful connection it is only revealed once
|
|
29
|
+
// a disconnect has actually persisted. The status dot carries the state
|
|
30
|
+
// immediately and without covering anything.
|
|
31
|
+
var OVERLAY_GRACE_MS = 800;
|
|
32
|
+
var overlayGraceTimer = null;
|
|
33
|
+
|
|
34
|
+
// Keeps the socket from looking idle to an intermediary proxy. A proxy resets
|
|
35
|
+
// its upstream read timeout on data flowing back from the server, so this only
|
|
36
|
+
// protects the connection because the server answers with a pong: the project
|
|
37
|
+
// socket via project-connection.js and the slug-less socket via
|
|
38
|
+
// server-global-ws.js. Well under the common 60s proxy read timeout, and one
|
|
39
|
+
// timer per live socket.
|
|
40
|
+
var HEARTBEAT_MS = 25000;
|
|
41
|
+
var heartbeatTimer = null;
|
|
42
|
+
var heartbeatDeadlineTimer = null;
|
|
43
|
+
var disconnectedAt = 0;
|
|
44
|
+
|
|
45
|
+
function clearOverlayGrace() {
|
|
46
|
+
if (overlayGraceTimer) {
|
|
47
|
+
clearTimeout(overlayGraceTimer);
|
|
48
|
+
overlayGraceTimer = null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function showOverlayNow() {
|
|
53
|
+
if (!connectOverlay) return;
|
|
54
|
+
if (hasConnectedOnce) {
|
|
55
|
+
var overlayMessage = document.getElementById("connect-overlay-msg");
|
|
56
|
+
if (overlayMessage) overlayMessage.textContent = "Reconnecting to server…";
|
|
57
|
+
}
|
|
58
|
+
connectOverlay.classList.remove("hidden");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function stopHeartbeat() {
|
|
62
|
+
if (heartbeatTimer) {
|
|
63
|
+
clearInterval(heartbeatTimer);
|
|
64
|
+
heartbeatTimer = null;
|
|
65
|
+
}
|
|
66
|
+
if (heartbeatDeadlineTimer) {
|
|
67
|
+
clearTimeout(heartbeatDeadlineTimer);
|
|
68
|
+
heartbeatDeadlineTimer = null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Started once per live socket. The socket it was started for is captured, so
|
|
73
|
+
// a timer that outlives its socket stops itself instead of writing to a stale
|
|
74
|
+
// connection. The pong the server sends back keeps a proxy's upstream read
|
|
75
|
+
// timeout from expiring. A missing pong also identifies a half-open socket,
|
|
76
|
+
// which browsers can otherwise leave OPEN while silently losing sends.
|
|
77
|
+
export function startHeartbeat(socket) {
|
|
78
|
+
stopHeartbeat();
|
|
79
|
+
if (!socket) return;
|
|
80
|
+
heartbeatTimer = setInterval(function () {
|
|
81
|
+
if (!socket || socket.readyState !== 1 || getWs() !== socket) {
|
|
82
|
+
stopHeartbeat();
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
try { socket.send(JSON.stringify({ type: "ping" })); } catch (e) {}
|
|
86
|
+
if (heartbeatDeadlineTimer) clearTimeout(heartbeatDeadlineTimer);
|
|
87
|
+
heartbeatDeadlineTimer = setTimeout(function () {
|
|
88
|
+
heartbeatDeadlineTimer = null;
|
|
89
|
+
if (getWs() === socket && socket.readyState === 1) connect();
|
|
90
|
+
}, 10000);
|
|
91
|
+
}, HEARTBEAT_MS);
|
|
92
|
+
}
|
|
93
|
+
|
|
26
94
|
export function initConnection() {
|
|
27
95
|
connectOverlay = document.getElementById("connect-overlay");
|
|
96
|
+
window.addEventListener("clay-message-delivery-timeout", function (event) {
|
|
97
|
+
var socket = event.detail && event.detail.socket;
|
|
98
|
+
if (!socket || getWs() === socket) connect();
|
|
99
|
+
});
|
|
28
100
|
|
|
29
101
|
// --- Reactive UI sync for connected/processing state ---
|
|
30
102
|
store.subscribe(function (state, prev) {
|
|
@@ -44,18 +116,30 @@ export function initConnection() {
|
|
|
44
116
|
if (state.connected !== prev.connected) {
|
|
45
117
|
var sendBtn = getSendBtn();
|
|
46
118
|
if (state.connected) {
|
|
119
|
+
// Cancel a pending reveal and hide immediately: a reconnect that beat
|
|
120
|
+
// the grace delay must never flash the overlay at all.
|
|
121
|
+
clearOverlayGrace();
|
|
47
122
|
hasConnectedOnce = true;
|
|
48
123
|
if (sendBtn) sendBtn.disabled = false;
|
|
49
124
|
if (connectOverlay) connectOverlay.classList.add("hidden");
|
|
50
125
|
var updPill = document.getElementById("update-pill-wrap");
|
|
51
126
|
if (updPill) updPill.classList.add("hidden");
|
|
52
127
|
} else {
|
|
128
|
+
// The composer stays disabled while the socket is down because there
|
|
129
|
+
// is no outbound queue: every sender drops on readyState !== 1, so
|
|
130
|
+
// enabling it here would silently discard the message.
|
|
53
131
|
if (sendBtn) sendBtn.disabled = true;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
132
|
+
clearOverlayGrace();
|
|
133
|
+
if (!hasConnectedOnce) {
|
|
134
|
+
// First connection of the page: the startup overlay is the intended
|
|
135
|
+
// presentation and appears immediately.
|
|
136
|
+
showOverlayNow();
|
|
137
|
+
} else {
|
|
138
|
+
overlayGraceTimer = setTimeout(function () {
|
|
139
|
+
overlayGraceTimer = null;
|
|
140
|
+
if (!store.get('connected')) showOverlayNow();
|
|
141
|
+
}, OVERLAY_GRACE_MS);
|
|
57
142
|
}
|
|
58
|
-
if (connectOverlay) connectOverlay.classList.remove("hidden");
|
|
59
143
|
}
|
|
60
144
|
}
|
|
61
145
|
|
|
@@ -133,6 +217,10 @@ function onConnected() {
|
|
|
133
217
|
|
|
134
218
|
export function connect() {
|
|
135
219
|
var ws = getWs();
|
|
220
|
+
// Tear down the previous socket's heartbeat before a new socket exists, so
|
|
221
|
+
// two sockets can never both be pinging.
|
|
222
|
+
stopHeartbeat();
|
|
223
|
+
if (ws && ws.readyState === 1) setStatus("disconnected");
|
|
136
224
|
if (ws) { ws.onclose = null; ws.close(); }
|
|
137
225
|
if (connectTimeoutId) { clearTimeout(connectTimeoutId); connectTimeoutId = null; }
|
|
138
226
|
|
|
@@ -152,7 +240,12 @@ export function connect() {
|
|
|
152
240
|
|
|
153
241
|
newWs.onopen = function () {
|
|
154
242
|
if (connectTimeoutId) { clearTimeout(connectTimeoutId); connectTimeoutId = null; }
|
|
243
|
+
if (hasConnectedOnce && disconnectedAt) {
|
|
244
|
+
console.log("[clay] WebSocket reconnected after " + (Date.now() - disconnectedAt) + "ms");
|
|
245
|
+
}
|
|
246
|
+
disconnectedAt = 0;
|
|
155
247
|
setStatus("connected");
|
|
248
|
+
startHeartbeat(newWs);
|
|
156
249
|
reconnectDelay = 1000;
|
|
157
250
|
if (reconnectTimer) { clearTimeout(reconnectTimer); reconnectTimer = null; }
|
|
158
251
|
|
|
@@ -175,6 +268,14 @@ export function connect() {
|
|
|
175
268
|
|
|
176
269
|
newWs.onclose = function (e) {
|
|
177
270
|
if (connectTimeoutId) { clearTimeout(connectTimeoutId); connectTimeoutId = null; }
|
|
271
|
+
stopHeartbeat();
|
|
272
|
+
disconnectedAt = Date.now();
|
|
273
|
+
// Abnormal closes are the ones worth reporting: a clean close is either a
|
|
274
|
+
// deliberate navigation or a server shutdown the user already knows about.
|
|
275
|
+
if (e && !e.wasClean) {
|
|
276
|
+
console.warn("[clay] WebSocket closed abnormally: code=" + e.code +
|
|
277
|
+
" reason=" + (e.reason || "(none)") + " wasClean=false");
|
|
278
|
+
}
|
|
178
279
|
closeDmUserPicker();
|
|
179
280
|
setStatus("disconnected");
|
|
180
281
|
setActivity(null);
|
|
@@ -194,6 +295,10 @@ export function connect() {
|
|
|
194
295
|
blinkIO();
|
|
195
296
|
var msg;
|
|
196
297
|
try { msg = JSON.parse(event.data); } catch (e) { return; }
|
|
298
|
+
if (msg.type === "pong" && heartbeatDeadlineTimer) {
|
|
299
|
+
clearTimeout(heartbeatDeadlineTimer);
|
|
300
|
+
heartbeatDeadlineTimer = null;
|
|
301
|
+
}
|
|
197
302
|
processMessage(msg);
|
|
198
303
|
};
|
|
199
304
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { store } from './store.js';
|
|
4
4
|
import { getWs } from './ws-ref.js';
|
|
5
|
-
import { getCachedProjects } from './app-projects.js';
|
|
5
|
+
import { getCachedProjects, switchProject } from './app-projects.js';
|
|
6
6
|
import { mateAvatarUrl } from './avatar.js';
|
|
7
7
|
import { exitDmMode } from './app-dm.js';
|
|
8
8
|
import { closeHomeDock, initHomeDock, renderDock, requestHomeDockPreference } from './home-dock.js';
|
|
@@ -41,7 +41,22 @@ function syncHomePresentation() {
|
|
|
41
41
|
function syncHomeCloseControl() {
|
|
42
42
|
var close = document.getElementById("home-close-control");
|
|
43
43
|
if (!close) return;
|
|
44
|
-
close.classList.toggle("hidden", !
|
|
44
|
+
close.classList.toggle("hidden", !getHomeReturnSlug());
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function getHomeReturnSlug() {
|
|
48
|
+
var projects = getCachedProjects() || [];
|
|
49
|
+
var candidates = [store.get('currentSlug'), store.get('homeSurfaceProjectSlug')];
|
|
50
|
+
for (var ci = 0; ci < candidates.length; ci++) {
|
|
51
|
+
if (!candidates[ci]) continue;
|
|
52
|
+
for (var pi = 0; pi < projects.length; pi++) {
|
|
53
|
+
if (projects[pi] && !projects[pi].isMate && projects[pi].slug === candidates[ci]) return candidates[ci];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
for (var i = 0; i < projects.length; i++) {
|
|
57
|
+
if (projects[i] && !projects[i].isMate && projects[i].slug) return projects[i].slug;
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
45
60
|
}
|
|
46
61
|
|
|
47
62
|
function getVisibleMates() {
|
|
@@ -390,13 +405,10 @@ export function hideHomeHub() {
|
|
|
390
405
|
}
|
|
391
406
|
|
|
392
407
|
export function minimizeHomeHub() {
|
|
393
|
-
var slug =
|
|
408
|
+
var slug = getHomeReturnSlug();
|
|
394
409
|
if (!slug || !homeHubVisible) return;
|
|
395
410
|
rememberHomePrimarySurface("project");
|
|
396
|
-
|
|
397
|
-
var route = "/p/" + slug + "/";
|
|
398
|
-
if (document.documentElement.classList.contains("pwa-standalone")) history.replaceState(null, "", route);
|
|
399
|
-
else history.pushState(null, "", route);
|
|
411
|
+
switchProject(slug);
|
|
400
412
|
var projectInput = document.getElementById("input");
|
|
401
413
|
if (projectInput && !projectInput.disabled) projectInput.focus({ preventScroll: true });
|
|
402
414
|
}
|
|
@@ -6,7 +6,8 @@ import { escapeHtml, copyToClipboard } from './utils.js';
|
|
|
6
6
|
import { renderMarkdown, highlightCodeBlocks } from './markdown.js';
|
|
7
7
|
import { iconHtml, refreshIcons } from './icons.js';
|
|
8
8
|
import { userAvatarUrl } from './avatar.js';
|
|
9
|
-
import { showImageModal
|
|
9
|
+
import { showImageModal } from './app-misc.js';
|
|
10
|
+
import { showPasteModal } from './paste-modal.js';
|
|
10
11
|
import { addToMessages, scrollToBottom, forceScrollToBottom, getMsgTime, shouldGroupMessage, getTurnCounter, setTurnCounter, VENDOR_AVATARS } from './chat-render-runtime.js';
|
|
11
12
|
|
|
12
13
|
export function addUserMessage(text, images, pastes, fromUserId, fromUserName, delegatedMeta) {
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// All dependencies are direct imports; no context injection needed.
|
|
4
4
|
|
|
5
5
|
import { store } from './store.js';
|
|
6
|
+
import { acknowledgeMessage, replayPendingMessages } from './message-delivery.js';
|
|
6
7
|
import { getWs } from './ws-ref.js';
|
|
7
8
|
|
|
8
9
|
// --- Leaf module imports ---
|
|
@@ -15,7 +16,7 @@ import { updateDmBadge, setMentionActive, renderUserStrip } from './sidebar-mate
|
|
|
15
16
|
import { renderSidebarPresence } from './sidebar-presence.js';
|
|
16
17
|
import { refreshMobileChatSheet } from './sidebar-mobile.js';
|
|
17
18
|
import { renderMateSessionList, handleMateSearchResults, updateMateSidebarProfile } from './mate-sidebar.js';
|
|
18
|
-
import { openHomeChat, handleHomeMateHistory, handleHomeMateDelta, handleHomeMateDone, handleHomeMateError, handleHomeMateSessionsState } from './home-mate-chat.js';
|
|
19
|
+
import { openHomeChat, handleHomeMateHistory, handleHomeMateDelta, handleHomeMateSegment, handleHomeMateDone, handleHomeMateError, handleHomeMateSessionsState } from './home-mate-chat.js';
|
|
19
20
|
import { handleHomeSurfaceState } from './home-surface.js';
|
|
20
21
|
import { handleHomeMateMemoryState, handleHomeMateKnowledgeState } from './home-mate-settings.js';
|
|
21
22
|
import { renderKnowledgeList, handleKnowledgeContent } from './mate-knowledge.js';
|
|
@@ -41,6 +42,7 @@ import { tuiModalHandleTermOutput, tuiModalHandleTermResized, tuiModalHandleTerm
|
|
|
41
42
|
import { updateTerminalList, handleContextSourcesState, updateEmailAccountList, updateEmailUnreadCounts, handleEmailTestResult, handleEmailAddResult, handleEmailRemoveResult } from './context-sources.js';
|
|
42
43
|
import { refreshEmailSettings } from './user-settings.js';
|
|
43
44
|
import { handleNotesList, handleNoteCreated, handleNoteUpdated, handleNoteDeleted, handleNoteWritten } from './sticky-notes.js';
|
|
45
|
+
import { handleProjectLogsState, handleProjectLogEntry, handleProjectLogCommented, handleProjectLogCommentReviewed, handleProjectLogDeleted, handleProjectLogUpdated, handleProjectLogsError } from './project-logs.js';
|
|
44
46
|
import { handleSkillInstalled, handleSkillUninstalled } from './skills.js';
|
|
45
47
|
import { showRewindModal, onRewindComplete, setRewindMode, onRewindError, clearPendingRewindUuid, addRewindButton } from './rewind.js';
|
|
46
48
|
import { checkAdminAccess } from './admin.js';
|
|
@@ -64,8 +66,9 @@ import { getModelEffortLevels, accumulateUsage, updateUsagePanel, accumulateCont
|
|
|
64
66
|
import { updateProjectList, resetClientState, showUpdateAvailable, handleRemoveProjectCheckResult, handleRemoveProjectResult, handleBrowseDirResult, handleAddProjectResult, handleCloneProgress } from './app-projects.js';
|
|
65
67
|
import { updateHistorySentinel, prependOlderHistory } from './app-header.js';
|
|
66
68
|
import { hideHomeHub, showHomeHub } from './app-home-hub.js';
|
|
67
|
-
import { handleToolsState, handleToolInstalled, handleToolRemoved, handleToolStorageResult, handleToolLlmResult, handleToolsError, handleToolControlRequest } from './home-tools.js';
|
|
69
|
+
import { handleToolsState, handleToolInstalled, handleToolRemoved, handleToolStorageResult, handleToolLlmResult, handleToolsError, handleToolControlRequest, handleToolServerState, handleToolServerEvent, handleCapsuleGameSession } from './home-tools.js';
|
|
68
70
|
import { handleHomeDockState } from './home-dock.js';
|
|
71
|
+
import { handleToolFrameUrlState } from './home-tool-frame.js';
|
|
69
72
|
import { enterDmMode, exitDmMode, handleMateCreatedInApp, updateMateIconStatus, appendDmMessage, showDmTypingIndicator, buildMateInterviewPrompt } from './app-dm.js';
|
|
70
73
|
import { handleRateLimitEvent, updateRateLimitUsage, addScheduledMessageBubble, removeScheduledMessageBubble, handleFastModeState } from './app-rate-limit.js';
|
|
71
74
|
import { handleRemoteCursorMove, handleRemoteCursorLeave, handleRemoteSelection, clearRemoteCursors } from './app-cursors.js';
|
|
@@ -73,6 +76,7 @@ import { showLoopBanner, updateLoopBanner, updateLoopInputVisibility, showRalphA
|
|
|
73
76
|
import { showDebateSticky, showDebateConcludeConfirm, showDebateUserFloor, exitDebateFloorMode, exitDebateConcludeMode, exitDebateEndedMode, updateDebateRound, renderDebateUserFloorDone } from './app-debate-ui.js';
|
|
74
77
|
import { handleSkillInstallWs } from './app-skills-install.js';
|
|
75
78
|
import { handleNotificationsState, handleNotificationCreated, handleNotificationDismissed, handleNotificationDismissedAll, showUpdateBanner } from './app-notifications.js';
|
|
79
|
+
import { handleUpdateSnoozed } from './update-snooze.js';
|
|
76
80
|
import { autoStartLoginIfNeeded, handleVendorLoginReady, handleVendorLoginState, handleVendorLoginError, handleAuthRefreshed } from './vendor-login.js';
|
|
77
81
|
import { handleDebatePreparing, handleDebateBriefReady, renderDebateBriefReady, handleDebateStarted, renderDebateStarted, handleDebateTurn, handleDebateActivity, handleDebateStream, handleDebateTurnDone, handleDebateCommentQueued, handleDebateCommentInjected, renderDebateCommentInjected, handleDebateResumed, handleDebateEnded, renderDebateEnded, handleDebateError, isDebateActive, renderMcpDebateProposal, renderDebateUserResume } from './debate.js';
|
|
78
82
|
import { handleMentionStart, handleMentionActivity, handleMentionStream, handleMentionDone, handleMentionError, renderMentionUser, renderMentionResponse, renderUserMention } from './mention.js';
|
|
@@ -160,6 +164,20 @@ export function processMessage(msg) {
|
|
|
160
164
|
}
|
|
161
165
|
|
|
162
166
|
switch (msg.type) {
|
|
167
|
+
case "message_ack":
|
|
168
|
+
var acknowledgedEl = msg.clientMessageId
|
|
169
|
+
? messagesEl.querySelector('[data-client-message-id="' + msg.clientMessageId + '"]')
|
|
170
|
+
: null;
|
|
171
|
+
acknowledgeMessage(msg.clientMessageId);
|
|
172
|
+
if (!acknowledgedEl && msg.message) {
|
|
173
|
+
addUserMessage(msg.message.text, msg.message.images || null, msg.message.pastes || null, msg.message.from, msg.message.fromName);
|
|
174
|
+
var acknowledgedUsers = messagesEl.querySelectorAll(".msg-user");
|
|
175
|
+
if (acknowledgedUsers.length > 0) {
|
|
176
|
+
acknowledgedUsers[acknowledgedUsers.length - 1].dataset.clientMessageId = msg.clientMessageId;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
break;
|
|
180
|
+
|
|
163
181
|
case "history_meta":
|
|
164
182
|
store.set({ historyFrom: msg.from, historyTotal: msg.total, replayingHistory: true });
|
|
165
183
|
updateHistorySentinel();
|
|
@@ -330,7 +348,9 @@ export function processMessage(msg) {
|
|
|
330
348
|
break;
|
|
331
349
|
|
|
332
350
|
case "update_available":
|
|
333
|
-
//
|
|
351
|
+
// The server already refuses to send this frame to anyone who is not
|
|
352
|
+
// admin-grade, so this check is defence in depth for the UI, not the
|
|
353
|
+
// access control.
|
|
334
354
|
if (store.get('isMultiUserMode')) {
|
|
335
355
|
checkAdminAccess().then(function (isAdmin) {
|
|
336
356
|
if (!isAdmin) return;
|
|
@@ -343,6 +363,10 @@ export function processMessage(msg) {
|
|
|
343
363
|
}
|
|
344
364
|
break;
|
|
345
365
|
|
|
366
|
+
case "update_snoozed":
|
|
367
|
+
handleUpdateSnoozed(msg);
|
|
368
|
+
break;
|
|
369
|
+
|
|
346
370
|
case "up_to_date":
|
|
347
371
|
var utdBtn = document.getElementById("settings-update-check");
|
|
348
372
|
if (utdBtn) {
|
|
@@ -619,6 +643,26 @@ export function processMessage(msg) {
|
|
|
619
643
|
handleToolControlRequest(msg);
|
|
620
644
|
break;
|
|
621
645
|
|
|
646
|
+
case "tool_server_state":
|
|
647
|
+
handleToolServerState(msg);
|
|
648
|
+
break;
|
|
649
|
+
|
|
650
|
+
case "tool_server_event":
|
|
651
|
+
handleToolServerEvent(msg);
|
|
652
|
+
break;
|
|
653
|
+
|
|
654
|
+
case "tool_frame_url_state":
|
|
655
|
+
handleToolFrameUrlState(msg);
|
|
656
|
+
break;
|
|
657
|
+
|
|
658
|
+
case "capsule_game_session":
|
|
659
|
+
handleCapsuleGameSession(msg);
|
|
660
|
+
break;
|
|
661
|
+
|
|
662
|
+
case "home_mate_segment":
|
|
663
|
+
handleHomeMateSegment(msg);
|
|
664
|
+
break;
|
|
665
|
+
|
|
622
666
|
case "input_sync":
|
|
623
667
|
if (!store.get('dmMode')) handleInputSync(msg.text);
|
|
624
668
|
break;
|
|
@@ -737,6 +781,7 @@ export function processMessage(msg) {
|
|
|
737
781
|
? msg.runtimeTerminalId
|
|
738
782
|
: (typeof msg.terminalId === "number" ? msg.terminalId : null);
|
|
739
783
|
store.set({ activeSessionId: msg.id, cliSessionId: msg.cliSessionId || null, currentModel: msg.model || "", currentEffort: msg.effort || store.get('currentEffort'), vendorCapabilities: msg.capabilities || {}, sessionIsProcessing: !!msg.isProcessing, activeSessionMode: _effectiveMode, activeTerminalId: _effectiveTerminalId, sessionHasHistory: !!msg.hasHistory, sessionVendorBound: !!msg.vendor || !!msg.hasHistory, sessionFullAccess: msg.permissionMode === "bypassPermissions", currentMode: msg.permissionMode || store.get('currentMode') });
|
|
784
|
+
replayPendingMessages(msg.id);
|
|
740
785
|
// TUI sessions swap the chat UI for an embedded xterm running
|
|
741
786
|
// `claude` inside a real PTY. Mount or tear down before the rest of
|
|
742
787
|
// the chat-side bookkeeping runs so we don't waste work on hidden DOM.
|
|
@@ -858,6 +903,10 @@ export function processMessage(msg) {
|
|
|
858
903
|
} else {
|
|
859
904
|
addUserMessage(msg.text, msg.images || null, msg.pastes || null, msg.from, msg.fromName, msg.delegated ? msg : null);
|
|
860
905
|
}
|
|
906
|
+
if (msg.clientMessageId) {
|
|
907
|
+
var replayedUsers = messagesEl.querySelectorAll(".msg-user");
|
|
908
|
+
if (replayedUsers.length > 0) replayedUsers[replayedUsers.length - 1].dataset.clientMessageId = msg.clientMessageId;
|
|
909
|
+
}
|
|
861
910
|
// Split Worker pane: a delegated instruction starts (or replays into) a
|
|
862
911
|
// driven turn; surface the composer notice. Cleared on "done".
|
|
863
912
|
if (msg.delegated) showWorkerDelegationNotice(msg.delegatedByTitle || null);
|
|
@@ -1300,10 +1349,10 @@ export function processMessage(msg) {
|
|
|
1300
1349
|
appendDelta((msg.text || "Authentication required.") + "\n");
|
|
1301
1350
|
setStatus("connected");
|
|
1302
1351
|
if (!store.get('loopActive')) enableMainInput();
|
|
1303
|
-
// Open the login flow for
|
|
1304
|
-
//
|
|
1305
|
-
//
|
|
1306
|
-
autoStartLoginIfNeeded(msg);
|
|
1352
|
+
// Open the login flow only for a live auth failure. Older Clay
|
|
1353
|
+
// versions recorded this transient event in session history; replaying
|
|
1354
|
+
// one must not reopen a login terminal after the user signed in.
|
|
1355
|
+
if (!store.get('replayingHistory')) autoStartLoginIfNeeded(msg);
|
|
1307
1356
|
break;
|
|
1308
1357
|
|
|
1309
1358
|
case "vendor_login_ready":
|
|
@@ -1567,6 +1616,34 @@ export function processMessage(msg) {
|
|
|
1567
1616
|
handleNoteDeleted(msg);
|
|
1568
1617
|
break;
|
|
1569
1618
|
|
|
1619
|
+
case "project_logs_state":
|
|
1620
|
+
handleProjectLogsState(msg);
|
|
1621
|
+
break;
|
|
1622
|
+
|
|
1623
|
+
case "project_log_entry":
|
|
1624
|
+
handleProjectLogEntry(msg);
|
|
1625
|
+
break;
|
|
1626
|
+
|
|
1627
|
+
case "project_log_commented":
|
|
1628
|
+
handleProjectLogCommented(msg);
|
|
1629
|
+
break;
|
|
1630
|
+
|
|
1631
|
+
case "project_log_comment_reviewed":
|
|
1632
|
+
handleProjectLogCommentReviewed(msg);
|
|
1633
|
+
break;
|
|
1634
|
+
|
|
1635
|
+
case "project_log_deleted":
|
|
1636
|
+
handleProjectLogDeleted(msg);
|
|
1637
|
+
break;
|
|
1638
|
+
|
|
1639
|
+
case "project_log_updated":
|
|
1640
|
+
handleProjectLogUpdated(msg);
|
|
1641
|
+
break;
|
|
1642
|
+
|
|
1643
|
+
case "project_logs_error":
|
|
1644
|
+
handleProjectLogsError(msg);
|
|
1645
|
+
break;
|
|
1646
|
+
|
|
1570
1647
|
case "process_stats":
|
|
1571
1648
|
updateStatusPanel(msg);
|
|
1572
1649
|
updateSettingsStats(msg);
|