clay-server 3.4.0-beta.1 → 3.4.0-beta.11
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/daemon-projects.js +3 -3
- package/lib/daemon.js +1 -1
- package/lib/project-connection.js +20 -5
- package/lib/project-debate.js +4 -0
- package/lib/project-mate-interaction.js +21 -1
- package/lib/project-memory.js +3 -0
- package/lib/project-shell-command.js +160 -0
- package/lib/project-user-message.js +10 -0
- package/lib/project.js +19 -4
- package/lib/public/antigravity-avatar.png +0 -0
- package/lib/public/app.js +28 -0
- package/lib/public/copilot-avatar.svg +5 -0
- package/lib/public/css/command-palette.css +22 -2
- package/lib/public/css/icon-strip.css +29 -13
- package/lib/public/css/input.css +75 -0
- package/lib/public/css/mates.css +6 -0
- package/lib/public/css/menus.css +48 -14
- package/lib/public/css/messages.css +9 -0
- package/lib/public/css/pane.css +4 -0
- package/lib/public/css/pwa-mobile.css +17 -0
- package/lib/public/css/title-bar.css +19 -0
- package/lib/public/grok-avatar.svg +4 -0
- package/lib/public/index.html +38 -7
- package/lib/public/junie-avatar.svg +11 -0
- package/lib/public/kimi-avatar.svg +4 -0
- package/lib/public/modules/app-header.js +4 -0
- package/lib/public/modules/app-messages.js +28 -5
- package/lib/public/modules/app-panels.js +28 -8
- package/lib/public/modules/app-projects.js +3 -1
- package/lib/public/modules/app-rendering.js +19 -4
- package/lib/public/modules/input.js +58 -28
- package/lib/public/modules/mate-sidebar.js +11 -3
- package/lib/public/modules/notifications.js +7 -1
- package/lib/public/modules/pane-bridge.js +11 -0
- package/lib/public/modules/pane-links.js +23 -0
- package/lib/public/modules/project-switcher.js +7 -6
- package/lib/public/modules/shell-command.js +148 -0
- package/lib/public/modules/sidebar-mates.js +1 -1
- package/lib/public/modules/sidebar-mobile.js +2 -1
- package/lib/public/modules/sidebar-projects.js +34 -43
- package/lib/public/modules/sidebar-sessions.js +6 -6
- package/lib/public/modules/split-pair-ui.js +3 -2
- package/lib/public/modules/tools.js +6 -1
- package/lib/public/modules/vendor-priority.js +14 -0
- package/lib/public/modules/vendor-selection.js +20 -0
- package/lib/public/modules/worktree-location.js +17 -0
- package/lib/public/qwen-avatar.svg +4 -0
- package/lib/public/style.css +3 -2
- package/lib/sdk-bridge.js +49 -25
- package/lib/sdk-message-processor.js +10 -1
- package/lib/session-notes-mcp-server.js +7 -1
- package/lib/worktree.js +9 -4
- package/lib/ws-schema.js +3 -0
- package/lib/yoke/acp-agent-profiles.js +64 -14
- package/lib/yoke/adapters/antigravity.js +417 -0
- package/lib/yoke/adapters/codex.js +98 -3
- package/lib/yoke/adapters/copilot.js +7 -0
- package/lib/yoke/adapters/grok.js +7 -0
- package/lib/yoke/adapters/junie.js +7 -0
- package/lib/yoke/adapters/kimi.js +7 -0
- package/lib/yoke/adapters/qwen.js +7 -0
- package/lib/yoke/codex-app-server.js +25 -8
- package/lib/yoke/index.js +67 -28
- package/lib/yoke/instructions.js +3 -0
- package/lib/yoke/vendor-registry.js +61 -6
- package/package.json +1 -1
- package/lib/public/gemini-avatar.svg +0 -11
- package/lib/yoke/adapters/gemini.js +0 -7
package/lib/public/css/input.css
CHANGED
|
@@ -790,6 +790,7 @@
|
|
|
790
790
|
opacity: 0.35;
|
|
791
791
|
cursor: default;
|
|
792
792
|
}
|
|
793
|
+
.vendor-toggle-btn.disabled:not(.active) { display: none; }
|
|
793
794
|
.vendor-toggle-icon {
|
|
794
795
|
width: 16px;
|
|
795
796
|
height: 16px;
|
|
@@ -799,6 +800,17 @@
|
|
|
799
800
|
.vendor-toggle-label {
|
|
800
801
|
pointer-events: none;
|
|
801
802
|
}
|
|
803
|
+
.vendor-toggle-btn.experimental::after,
|
|
804
|
+
.vendor-experimental-badge {
|
|
805
|
+
content: "🧪";
|
|
806
|
+
font-size: 10px;
|
|
807
|
+
line-height: 1;
|
|
808
|
+
font-weight: 400;
|
|
809
|
+
filter: saturate(0.85);
|
|
810
|
+
}
|
|
811
|
+
.vendor-experimental-badge {
|
|
812
|
+
margin-left: auto;
|
|
813
|
+
}
|
|
802
814
|
@media (min-width: 901px) {
|
|
803
815
|
.vendor-toggle-btn:not(.active) .vendor-toggle-label { display: none; }
|
|
804
816
|
.vendor-toggle-btn:not(.active) { padding: 0 8px; }
|
|
@@ -826,6 +838,7 @@
|
|
|
826
838
|
|
|
827
839
|
#attach-file-btn,
|
|
828
840
|
#attach-image-btn,
|
|
841
|
+
#shell-command-btn,
|
|
829
842
|
#schedule-btn,
|
|
830
843
|
#input-more-btn {
|
|
831
844
|
width: 36px;
|
|
@@ -844,14 +857,76 @@
|
|
|
844
857
|
|
|
845
858
|
#attach-file-btn .lucide,
|
|
846
859
|
#attach-image-btn .lucide,
|
|
860
|
+
#shell-command-btn .lucide,
|
|
847
861
|
#schedule-btn .lucide,
|
|
848
862
|
#input-more-btn .lucide { width: 20px; height: 20px; flex-shrink: 0; }
|
|
849
863
|
|
|
850
864
|
#attach-file-btn:hover,
|
|
851
865
|
#attach-image-btn:hover,
|
|
866
|
+
#shell-command-btn:hover,
|
|
852
867
|
#schedule-btn:hover,
|
|
853
868
|
#input-more-btn:hover { background: rgba(var(--overlay-rgb), 0.06); color: var(--text); }
|
|
854
869
|
|
|
870
|
+
#shell-command-btn.active {
|
|
871
|
+
background: var(--accent-12);
|
|
872
|
+
color: var(--accent);
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
#input-row.shell-command-mode {
|
|
876
|
+
box-shadow: 0 0 0 1px var(--accent);
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
#input-row.shell-command-mode #input {
|
|
880
|
+
font-family: var(--font-mono, "SFMono-Regular", Consolas, monospace);
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
.shell-command-card {
|
|
884
|
+
width: min(760px, calc(100% - 24px));
|
|
885
|
+
margin: 10px auto;
|
|
886
|
+
border: 1px solid var(--border);
|
|
887
|
+
border-radius: 8px;
|
|
888
|
+
background: var(--input-bg);
|
|
889
|
+
overflow: hidden;
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
.shell-command-card.error { border-color: rgba(239, 68, 68, 0.45); }
|
|
893
|
+
|
|
894
|
+
.shell-command-header {
|
|
895
|
+
display: flex;
|
|
896
|
+
align-items: center;
|
|
897
|
+
gap: 8px;
|
|
898
|
+
padding: 9px 12px;
|
|
899
|
+
border-bottom: 1px solid var(--border);
|
|
900
|
+
color: var(--text-secondary);
|
|
901
|
+
font-size: 12px;
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
.shell-command-header code {
|
|
905
|
+
min-width: 0;
|
|
906
|
+
flex: 1;
|
|
907
|
+
overflow: hidden;
|
|
908
|
+
text-overflow: ellipsis;
|
|
909
|
+
white-space: nowrap;
|
|
910
|
+
color: var(--text);
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
.shell-command-icon { display: inline-flex; }
|
|
914
|
+
.shell-command-icon .lucide { width: 16px; height: 16px; }
|
|
915
|
+
.shell-command-status { flex-shrink: 0; color: var(--text-muted); }
|
|
916
|
+
|
|
917
|
+
.shell-command-card.running .shell-command-status { color: var(--accent); }
|
|
918
|
+
|
|
919
|
+
.shell-command-output {
|
|
920
|
+
max-height: 320px;
|
|
921
|
+
margin: 0;
|
|
922
|
+
padding: 12px;
|
|
923
|
+
overflow: auto;
|
|
924
|
+
color: var(--text-secondary);
|
|
925
|
+
font: 12px/1.5 var(--font-mono, "SFMono-Regular", Consolas, monospace);
|
|
926
|
+
white-space: pre-wrap;
|
|
927
|
+
word-break: break-word;
|
|
928
|
+
}
|
|
929
|
+
|
|
855
930
|
#ask-mate-btn {
|
|
856
931
|
width: 36px;
|
|
857
932
|
height: 36px;
|
package/lib/public/css/mates.css
CHANGED
|
@@ -682,6 +682,12 @@
|
|
|
682
682
|
.mate-vendor-label {
|
|
683
683
|
pointer-events: none;
|
|
684
684
|
}
|
|
685
|
+
.mate-vendor-btn.experimental::after {
|
|
686
|
+
content: "🧪";
|
|
687
|
+
font-size: 9px;
|
|
688
|
+
line-height: 1;
|
|
689
|
+
font-weight: 400;
|
|
690
|
+
}
|
|
685
691
|
.mate-vendor-btn:not(.active) .mate-vendor-label { display: none; }
|
|
686
692
|
|
|
687
693
|
/* Collapse button inside mate header: white to match header style */
|
package/lib/public/css/menus.css
CHANGED
|
@@ -44,29 +44,64 @@
|
|
|
44
44
|
#header-rename-btn .lucide { width: 13px; height: 13px; }
|
|
45
45
|
|
|
46
46
|
#header-add-worker-btn {
|
|
47
|
-
display: flex;
|
|
47
|
+
display: inline-flex;
|
|
48
48
|
align-items: center;
|
|
49
49
|
justify-content: center;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
gap: 7px;
|
|
51
|
+
width: auto;
|
|
52
|
+
height: 28px;
|
|
53
|
+
border: 1px solid color-mix(in srgb, var(--accent2) 28%, var(--border));
|
|
54
|
+
background: var(--accent2-8);
|
|
55
|
+
color: var(--accent2);
|
|
55
56
|
cursor: pointer;
|
|
56
57
|
border-radius: 8px;
|
|
57
58
|
flex-shrink: 0;
|
|
58
|
-
padding: 0;
|
|
59
|
-
margin-left:
|
|
59
|
+
padding: 0 9px 0 7px;
|
|
60
|
+
margin-left: 0;
|
|
61
|
+
font-family: inherit;
|
|
62
|
+
font-size: 11px;
|
|
63
|
+
font-weight: 700;
|
|
64
|
+
line-height: 1;
|
|
65
|
+
white-space: nowrap;
|
|
60
66
|
transition: color 0.15s, background 0.15s, border-color 0.15s;
|
|
61
67
|
}
|
|
62
|
-
#header-add-worker-btn:hover {
|
|
63
|
-
|
|
68
|
+
#header-add-worker-btn:hover {
|
|
69
|
+
color: var(--accent2-hover);
|
|
70
|
+
background: var(--accent2-15);
|
|
71
|
+
border-color: color-mix(in srgb, var(--accent2) 48%, var(--border));
|
|
72
|
+
}
|
|
73
|
+
.header-worker-icon {
|
|
74
|
+
position: relative;
|
|
75
|
+
display: inline-flex;
|
|
76
|
+
align-items: center;
|
|
77
|
+
justify-content: center;
|
|
78
|
+
width: 16px;
|
|
79
|
+
height: 16px;
|
|
80
|
+
flex-shrink: 0;
|
|
81
|
+
}
|
|
82
|
+
.header-worker-icon > .lucide { width: 15px; height: 15px; }
|
|
83
|
+
.header-worker-add-badge {
|
|
84
|
+
position: absolute;
|
|
85
|
+
right: -4px;
|
|
86
|
+
bottom: -3px;
|
|
87
|
+
display: inline-flex;
|
|
88
|
+
align-items: center;
|
|
89
|
+
justify-content: center;
|
|
90
|
+
width: 9px;
|
|
91
|
+
height: 9px;
|
|
92
|
+
border-radius: 50%;
|
|
93
|
+
background: var(--accent2);
|
|
94
|
+
color: var(--bg);
|
|
95
|
+
box-shadow: 0 0 0 2px var(--bg);
|
|
96
|
+
}
|
|
97
|
+
.header-worker-add-badge .lucide { width: 7px; height: 7px; stroke-width: 3; }
|
|
98
|
+
.header-worker-label { letter-spacing: 0.01em; }
|
|
64
99
|
#header-add-worker-btn.hidden { display: none; }
|
|
65
100
|
body.dm-mode #header-add-worker-btn { display: none; }
|
|
66
101
|
|
|
67
|
-
/* "Close terminal" button
|
|
68
|
-
|
|
69
|
-
|
|
102
|
+
/* "Close terminal" button for a live TUI session. Matches the session-control
|
|
103
|
+
chrome; reds out on hover since it stops the running agent while preserving
|
|
104
|
+
the resumable session. */
|
|
70
105
|
#header-tui-close-btn {
|
|
71
106
|
display: flex;
|
|
72
107
|
align-items: center;
|
|
@@ -980,4 +1015,3 @@ body.dm-mode #header-add-worker-btn { display: none; }
|
|
|
980
1015
|
#config-chip .config-chip-icon { display: inline; width: 14px; height: 14px; }
|
|
981
1016
|
#config-chip-label { display: none; }
|
|
982
1017
|
}
|
|
983
|
-
|
|
@@ -5,12 +5,21 @@
|
|
|
5
5
|
#messages {
|
|
6
6
|
flex: 1;
|
|
7
7
|
overflow-y: auto;
|
|
8
|
+
overflow-x: hidden;
|
|
8
9
|
-webkit-overflow-scrolling: touch;
|
|
9
10
|
overscroll-behavior-y: contain;
|
|
10
11
|
padding: 20px 0 12px;
|
|
11
12
|
position: relative;
|
|
12
13
|
}
|
|
13
14
|
|
|
15
|
+
/* Rich message content can contain wide tables, diagrams, or generated HTML.
|
|
16
|
+
Keep that content inside the chat scroller; nested code blocks still own
|
|
17
|
+
their intentional horizontal scrolling. */
|
|
18
|
+
#messages > * {
|
|
19
|
+
min-width: 0;
|
|
20
|
+
max-width: 100%;
|
|
21
|
+
}
|
|
22
|
+
|
|
14
23
|
/* --- Remote cursors (Figma-style) --- */
|
|
15
24
|
.remote-cursor {
|
|
16
25
|
pointer-events: none;
|
package/lib/public/css/pane.css
CHANGED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/* In an iOS Home Screen app, a 100%-tall root can be measured against the
|
|
2
|
+
shortened safe-area viewport. Use the physical viewport for the root while
|
|
3
|
+
retaining safe-area padding on controls inside the app. */
|
|
4
|
+
@media (max-width: 768px) {
|
|
5
|
+
html.pwa-standalone,
|
|
6
|
+
html.pwa-standalone body {
|
|
7
|
+
height: 100vh;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
@media (max-width: 768px) and (display-mode: standalone),
|
|
12
|
+
(max-width: 768px) and (display-mode: fullscreen) {
|
|
13
|
+
html,
|
|
14
|
+
body {
|
|
15
|
+
height: 100vh;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -324,6 +324,25 @@
|
|
|
324
324
|
display: none !important;
|
|
325
325
|
}
|
|
326
326
|
|
|
327
|
+
.title-bar-content {
|
|
328
|
+
height: calc(48px + var(--safe-top));
|
|
329
|
+
padding: var(--safe-top) 16px 0;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/* The inline title editor must own the header while the keyboard is open.
|
|
333
|
+
Leaving the other controls visible made its usable width nearly zero. */
|
|
334
|
+
.title-bar-content.session-renaming .status,
|
|
335
|
+
.title-bar-content.session-renaming #header-left > :not(.header-rename-input) {
|
|
336
|
+
display: none !important;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
.title-bar-content.session-renaming .header-rename-input {
|
|
340
|
+
flex: 1 1 100%;
|
|
341
|
+
width: 100%;
|
|
342
|
+
min-height: 36px;
|
|
343
|
+
font-size: 16px;
|
|
344
|
+
}
|
|
345
|
+
|
|
327
346
|
#sidebar-column {
|
|
328
347
|
width: 0 !important;
|
|
329
348
|
min-width: 0 !important;
|
package/lib/public/index.html
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
(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){}})();
|
|
31
31
|
</script>
|
|
32
32
|
<script>if(window.navigator.standalone||window.matchMedia("(display-mode:standalone)").matches){document.documentElement.classList.add("pwa-standalone")}</script>
|
|
33
|
-
<link rel="stylesheet" href="style.css?v=
|
|
33
|
+
<link rel="stylesheet" href="style.css?v=20260824f">
|
|
34
34
|
<style>
|
|
35
35
|
@media(max-width:768px){
|
|
36
36
|
/* User messages: vertical stack, avatar on top, right-aligned */
|
|
@@ -373,12 +373,11 @@
|
|
|
373
373
|
</div>
|
|
374
374
|
<button id="hamburger-btn" aria-label="Toggle sidebar" title="Toggle sidebar"><i data-lucide="menu"></i></button>
|
|
375
375
|
<span class="header-title" id="header-title">Connecting...</span>
|
|
376
|
+
<button id="header-rename-btn" type="button" title="Rename session"><i data-lucide="pencil"></i></button>
|
|
376
377
|
<button id="header-info-btn" type="button" title="Session info"><i data-lucide="info"></i></button>
|
|
377
378
|
<button id="header-full-access-btn" type="button" class="session-full-access hidden" role="switch" aria-checked="false" title="Skip Permissions is off — permission prompts are on">
|
|
378
379
|
<span class="session-full-access-label">Skip Permissions</span><span class="session-full-access-track" aria-hidden="true"><span></span></span>
|
|
379
380
|
</button>
|
|
380
|
-
<button id="header-rename-btn" type="button" title="Rename session"><i data-lucide="pencil"></i></button>
|
|
381
|
-
<button id="header-add-worker-btn" type="button" title="Add Worker — this session becomes the Driver of a pair"><i data-lucide="user-plus"></i></button>
|
|
382
381
|
<button type="button" id="header-tui-close-btn" class="header-tui-close-btn hidden" title="Close terminal (keeps history, resume anytime)" aria-label="Close terminal"><i data-lucide="power"></i></button>
|
|
383
382
|
<div id="mate-mobile-title" class="mate-mobile-title hidden">
|
|
384
383
|
<img id="mate-mobile-avatar" class="mate-mobile-avatar" alt="">
|
|
@@ -389,6 +388,13 @@
|
|
|
389
388
|
<div id="ralph-sticky" class="hidden"></div>
|
|
390
389
|
<div id="debate-sticky" class="hidden"></div>
|
|
391
390
|
<div class="status">
|
|
391
|
+
<button id="header-add-worker-btn" type="button" aria-label="Add AI Worker" title="Add an AI Worker — this session becomes the Driver of a pair">
|
|
392
|
+
<span class="header-worker-icon" aria-hidden="true">
|
|
393
|
+
<i data-lucide="bot"></i>
|
|
394
|
+
<span class="header-worker-add-badge"><i data-lucide="plus"></i></span>
|
|
395
|
+
</span>
|
|
396
|
+
<span class="header-worker-label">Add Worker</span>
|
|
397
|
+
</button>
|
|
392
398
|
<button type="button" id="header-tui-font-btn" class="header-tui-font-btn hidden" title="Terminal font" aria-label="Terminal font">
|
|
393
399
|
<i data-lucide="type"></i>
|
|
394
400
|
</button>
|
|
@@ -505,6 +511,7 @@
|
|
|
505
511
|
<button id="input-more-btn" type="button" aria-label="More options" title="More options" class="mobile-only"><i data-lucide="plus"></i></button>
|
|
506
512
|
<button id="attach-file-btn" type="button" aria-label="Attach file" title="Attach file" class="desktop-only"><i data-lucide="paperclip"></i></button>
|
|
507
513
|
<button id="attach-image-btn" type="button" aria-label="Attach image" title="Attach image" class="desktop-only"><i data-lucide="image"></i></button>
|
|
514
|
+
<button id="shell-command-btn" type="button" aria-label="Run shell command" aria-pressed="false" title="Run a shell command and add its output to the next agent message" class="desktop-only"><i data-lucide="square-terminal"></i></button>
|
|
508
515
|
<button id="stt-btn" type="button" aria-label="Voice input" title="Voice input"><i data-lucide="mic"></i></button>
|
|
509
516
|
<button id="schedule-btn" type="button" aria-label="Schedule message" title="Schedule message"><i data-lucide="clock"></i></button>
|
|
510
517
|
<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>
|
|
@@ -527,14 +534,34 @@
|
|
|
527
534
|
<img src="/codex-avatar.png" class="vendor-toggle-icon" alt="Codex">
|
|
528
535
|
<span class="vendor-toggle-label">Codex</span>
|
|
529
536
|
</button>
|
|
530
|
-
<button id="vendor-btn-
|
|
531
|
-
<img src="/
|
|
532
|
-
<span class="vendor-toggle-label">
|
|
537
|
+
<button id="vendor-btn-antigravity" class="vendor-toggle-btn" data-vendor="antigravity">
|
|
538
|
+
<img src="/antigravity-avatar.png" class="vendor-toggle-icon" alt="Antigravity">
|
|
539
|
+
<span class="vendor-toggle-label">Antigravity CLI</span>
|
|
533
540
|
</button>
|
|
534
541
|
<button id="vendor-btn-opencode" class="vendor-toggle-btn" data-vendor="opencode">
|
|
535
542
|
<img src="/opencode-avatar.svg" class="vendor-toggle-icon" alt="OpenCode">
|
|
536
543
|
<span class="vendor-toggle-label">OpenCode</span>
|
|
537
544
|
</button>
|
|
545
|
+
<button id="vendor-btn-kimi" class="vendor-toggle-btn" data-vendor="kimi">
|
|
546
|
+
<img src="/kimi-avatar.svg" class="vendor-toggle-icon" alt="Kimi">
|
|
547
|
+
<span class="vendor-toggle-label">Kimi Code</span>
|
|
548
|
+
</button>
|
|
549
|
+
<button id="vendor-btn-grok" class="vendor-toggle-btn" data-vendor="grok">
|
|
550
|
+
<img src="/grok-avatar.svg" class="vendor-toggle-icon" alt="Grok">
|
|
551
|
+
<span class="vendor-toggle-label">Grok Build</span>
|
|
552
|
+
</button>
|
|
553
|
+
<button id="vendor-btn-copilot" class="vendor-toggle-btn" data-vendor="copilot">
|
|
554
|
+
<img src="/copilot-avatar.svg" class="vendor-toggle-icon" alt="GitHub Copilot">
|
|
555
|
+
<span class="vendor-toggle-label">GitHub Copilot CLI</span>
|
|
556
|
+
</button>
|
|
557
|
+
<button id="vendor-btn-qwen" class="vendor-toggle-btn" data-vendor="qwen">
|
|
558
|
+
<img src="/qwen-avatar.svg" class="vendor-toggle-icon" alt="Qwen">
|
|
559
|
+
<span class="vendor-toggle-label">Qwen Code</span>
|
|
560
|
+
</button>
|
|
561
|
+
<button id="vendor-btn-junie" class="vendor-toggle-btn" data-vendor="junie">
|
|
562
|
+
<img src="/junie-avatar.svg" class="vendor-toggle-icon" alt="Junie">
|
|
563
|
+
<span class="vendor-toggle-label">Junie CLI</span>
|
|
564
|
+
</button>
|
|
538
565
|
<button id="vendor-btn-kiro" class="vendor-toggle-btn" data-vendor="kiro">
|
|
539
566
|
<img src="/kiro-avatar.svg" class="vendor-toggle-icon" alt="Kiro">
|
|
540
567
|
<span class="vendor-toggle-label">Kiro CLI</span>
|
|
@@ -615,6 +642,10 @@
|
|
|
615
642
|
<i data-lucide="image"></i>
|
|
616
643
|
<span>Image</span>
|
|
617
644
|
</button>
|
|
645
|
+
<button class="input-more-action" id="input-more-shell">
|
|
646
|
+
<i data-lucide="square-terminal"></i>
|
|
647
|
+
<span>Shell command</span>
|
|
648
|
+
</button>
|
|
618
649
|
</div>
|
|
619
650
|
<div class="input-more-divider"></div>
|
|
620
651
|
<div class="input-more-section-label">
|
|
@@ -2333,7 +2364,7 @@
|
|
|
2333
2364
|
<script src="https://cdn.jsdelivr.net/npm/@xterm/addon-fit@0/lib/addon-fit.min.js"></script>
|
|
2334
2365
|
<script src="https://cdn.jsdelivr.net/npm/@xterm/addon-web-links@0/lib/addon-web-links.min.js"></script>
|
|
2335
2366
|
<script src="https://cdn.jsdelivr.net/npm/@xterm/addon-webgl@0/lib/addon-webgl.min.js"></script>
|
|
2336
|
-
<script type="module" src="app.js"></script>
|
|
2367
|
+
<script type="module" src="app.js?v=20260824g"></script>
|
|
2337
2368
|
<div id="pwa-install-modal" class="pwa-modal hidden">
|
|
2338
2369
|
<div class="pwa-modal-backdrop"></div>
|
|
2339
2370
|
<div class="pwa-modal-card">
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="Junie">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="junie-gradient" x1="8" y1="8" x2="56" y2="56" gradientUnits="userSpaceOnUse">
|
|
4
|
+
<stop stop-color="#8B5CF6"/>
|
|
5
|
+
<stop offset="1" stop-color="#F97316"/>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
</defs>
|
|
8
|
+
<rect width="64" height="64" rx="15" fill="url(#junie-gradient)"/>
|
|
9
|
+
<path d="M39 15v26c0 7.7-5.4 12-13.2 12-5.3 0-9.4-2.2-12-6.4l7.1-5c1.3 2 2.7 3 4.6 3 2.5 0 4-1.4 4-4.4V15H39Z" fill="#fff"/>
|
|
10
|
+
<circle cx="47.5" cy="17.5" r="4.5" fill="#fff" fill-opacity=".9"/>
|
|
11
|
+
</svg>
|
|
@@ -93,6 +93,8 @@ export function initHeader() {
|
|
|
93
93
|
input.type = "text";
|
|
94
94
|
input.className = "header-rename-input";
|
|
95
95
|
input.value = currentText;
|
|
96
|
+
var titleBar = headerTitleEl.closest(".title-bar-content");
|
|
97
|
+
if (titleBar) titleBar.classList.add("session-renaming");
|
|
96
98
|
headerTitleEl.style.display = "none";
|
|
97
99
|
headerRenameBtn.style.display = "none";
|
|
98
100
|
headerTitleEl.parentNode.insertBefore(input, headerTitleEl.nextSibling);
|
|
@@ -117,6 +119,7 @@ export function initHeader() {
|
|
|
117
119
|
}
|
|
118
120
|
}
|
|
119
121
|
input.remove();
|
|
122
|
+
if (titleBar) titleBar.classList.remove("session-renaming");
|
|
120
123
|
headerTitleEl.style.display = "";
|
|
121
124
|
headerRenameBtn.style.display = "";
|
|
122
125
|
}
|
|
@@ -126,6 +129,7 @@ export function initHeader() {
|
|
|
126
129
|
if (e.key === "Escape") {
|
|
127
130
|
e.preventDefault();
|
|
128
131
|
input.remove();
|
|
132
|
+
if (titleBar) titleBar.classList.remove("session-renaming");
|
|
129
133
|
headerTitleEl.style.display = "";
|
|
130
134
|
headerRenameBtn.style.display = "";
|
|
131
135
|
}
|
|
@@ -22,7 +22,7 @@ import { handleFindInSessionResults } from './session-search.js';
|
|
|
22
22
|
import { syncPaneTitles, maybeRestoreSplitGroup, openGroup } from './split-view.js';
|
|
23
23
|
import { showPairDialog, handlePairCreated, handleSplitDelegation, showWorkerDelegationNotice, hideWorkerDelegationNotice } from './split-pair-ui.js';
|
|
24
24
|
import { renderWorkerProposal, updateWorkerProposal } from './worker-proposal.js';
|
|
25
|
-
import { handleInputSync, autoResize, builtinCommands, setScheduleBtnDisabled } from './input.js';
|
|
25
|
+
import { handleInputSync, autoResize, builtinCommands, setScheduleBtnDisabled, sendShellResultToAgent } from './input.js';
|
|
26
26
|
import { startThinking, appendThinking, stopThinking, resetThinkingGroup, createToolItem, updateToolExecuting, updateToolResult, markAllToolsDone, closeToolGroup, removeToolFromGroup, resetToolState, getTools, getPlanContent, setPlanContent, renderPlanBanner, renderPlanCard, getTodoTools, handleTodoWrite, handleTaskCreate, handleTaskUpdate, applyDeadSessionTodoCompaction, isPlanFilePath, enableMainInput, addTurnMeta, updateSubagentActivity, addSubagentToolEntry, markSubagentDone, initSubagentStop, updateSubagentProgress, updateSubagentTaskStatus, renderAskUserQuestion, markAskUserAnswered, renderPermissionRequest, markPermissionCancelled, markPermissionResolved, renderElicitationRequest, markElicitationResolved, renderUserDialogRequest, markUserDialogResolved, updateThinkingTokens } from './tools.js';
|
|
27
27
|
import { showDoneNotification, playDoneSound, isNotifAlertEnabled, isNotifSoundEnabled } from './notifications.js';
|
|
28
28
|
import { handleFsList, handleFsRead, handleFileChanged, handleDirChanged, handleFileHistory, handleGitDiff, handleFileAt, refreshIfOpen, getPendingNavigate, handleFsSearch, presentMarkdownEdit } from './filebrowser.js';
|
|
@@ -42,6 +42,7 @@ import { checkAdminAccess } from './admin.js';
|
|
|
42
42
|
import { mateAvatarUrl } from './avatar.js';
|
|
43
43
|
import { showImageModal, sendExtensionCommand, handleMcpToolCallMessage } from './app-misc.js';
|
|
44
44
|
import { handleMcpServersState } from './mcp-ui.js';
|
|
45
|
+
import { handleShellCommandResult } from './shell-command.js';
|
|
45
46
|
import { handleLoopRegistryUpdated, handleScheduleRunStarted, handleScheduleRunFinished, handleLoopScheduled, isSchedulerOpen, enterCraftingMode, exitCraftingMode, handleLoopRegistryFiles } from './scheduler.js';
|
|
46
47
|
|
|
47
48
|
// --- App module imports ---
|
|
@@ -51,6 +52,7 @@ import { setStatus } from './app-connection.js';
|
|
|
51
52
|
import { handleWhatsNewState, handleWhatsNewSeenResult, setKnownEntries as setWhatsNewKnownEntries } from './whats-new.js';
|
|
52
53
|
import { closeArticle as closeWhatsNewArticle } from './whats-new-article.js';
|
|
53
54
|
import { resolvePaneSession, resolveSwitchedVendor } from './pane-session.js';
|
|
55
|
+
import { selectDefaultVendorForBlankSession } from './vendor-selection.js';
|
|
54
56
|
import { getModelEffortLevels, accumulateUsage, updateUsagePanel, accumulateContext, updateContextPanel, renderCtxPopover, updateStatusPanel } from './app-panels.js';
|
|
55
57
|
import { updateProjectList, resetClientState, showUpdateAvailable, handleRemoveProjectCheckResult, handleRemoveProjectResult, handleBrowseDirResult, handleAddProjectResult, handleCloneProgress } from './app-projects.js';
|
|
56
58
|
import { updateHistorySentinel, prependOlderHistory } from './app-header.js';
|
|
@@ -413,6 +415,15 @@ export function processMessage(msg) {
|
|
|
413
415
|
break;
|
|
414
416
|
|
|
415
417
|
case "model_info": {
|
|
418
|
+
// Installation state applies across vendors. Keep it even when the
|
|
419
|
+
// model payload itself is stale for the active session.
|
|
420
|
+
var _vendorState = {};
|
|
421
|
+
if (msg.availableVendors) _vendorState.availableVendors = msg.availableVendors;
|
|
422
|
+
if (msg.installedVendors) _vendorState.installedVendors = msg.installedVendors;
|
|
423
|
+
if (Object.keys(_vendorState).length > 0) {
|
|
424
|
+
store.set(_vendorState);
|
|
425
|
+
selectDefaultVendorForBlankSession();
|
|
426
|
+
}
|
|
416
427
|
// Drop stale model_info from a vendor that doesn't match the active
|
|
417
428
|
// session's vendor. On high-latency connections, the server's default-
|
|
418
429
|
// adapter model_info can arrive after session_switched has already
|
|
@@ -446,8 +457,6 @@ export function processMessage(msg) {
|
|
|
446
457
|
_miUpdate.currentModel = store.get('currentModel');
|
|
447
458
|
}
|
|
448
459
|
if (msg.vendor && !store.get('vendorSelectionLocked')) _miUpdate.currentVendor = msg.vendor;
|
|
449
|
-
if (msg.availableVendors) _miUpdate.availableVendors = msg.availableVendors;
|
|
450
|
-
if (msg.installedVendors) _miUpdate.installedVendors = msg.installedVendors;
|
|
451
460
|
if (msg.capabilities) _miUpdate.vendorCapabilities = msg.capabilities;
|
|
452
461
|
store.set(_miUpdate);
|
|
453
462
|
updateSettingsModels(_modelVal, msg.models || []);
|
|
@@ -660,7 +669,7 @@ export function processMessage(msg) {
|
|
|
660
669
|
var _effectiveTerminalId = (typeof msg.runtimeTerminalId === "number")
|
|
661
670
|
? msg.runtimeTerminalId
|
|
662
671
|
: (typeof msg.terminalId === "number" ? msg.terminalId : null);
|
|
663
|
-
store.set({ activeSessionId: msg.id, cliSessionId: msg.cliSessionId || null, currentModel: msg.model || store.get('currentModel'), currentEffort: msg.effort || store.get('currentEffort'), vendorCapabilities: msg.capabilities || {}, sessionIsProcessing: !!msg.isProcessing, activeSessionMode: _effectiveMode, activeTerminalId: _effectiveTerminalId, sessionHasHistory: !!msg.hasHistory, sessionFullAccess: msg.permissionMode === "bypassPermissions", currentMode: msg.permissionMode || store.get('currentMode') });
|
|
672
|
+
store.set({ activeSessionId: msg.id, cliSessionId: msg.cliSessionId || null, currentModel: msg.model || store.get('currentModel'), 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') });
|
|
664
673
|
// TUI sessions swap the chat UI for an embedded xterm running
|
|
665
674
|
// `claude` inside a real PTY. Mount or tear down before the rest of
|
|
666
675
|
// the chat-side bookkeeping runs so we don't waste work on hidden DOM.
|
|
@@ -705,7 +714,7 @@ export function processMessage(msg) {
|
|
|
705
714
|
}
|
|
706
715
|
}
|
|
707
716
|
if (!msg.hasHistory && !msg.vendor) {
|
|
708
|
-
|
|
717
|
+
selectDefaultVendorForBlankSession();
|
|
709
718
|
}
|
|
710
719
|
// Vendor toggle visibility + active-vendor indicator next to the
|
|
711
720
|
// model chip.
|
|
@@ -1209,6 +1218,15 @@ export function processMessage(msg) {
|
|
|
1209
1218
|
addConflictMessage(msg);
|
|
1210
1219
|
break;
|
|
1211
1220
|
|
|
1221
|
+
case "session_writer_conflict":
|
|
1222
|
+
removeMatePreThinking();
|
|
1223
|
+
setActivity(null);
|
|
1224
|
+
stopThinking();
|
|
1225
|
+
markAllToolsDone();
|
|
1226
|
+
closeToolGroup();
|
|
1227
|
+
addSystemMessage(msg.text || "This session is already open in another process.", true);
|
|
1228
|
+
break;
|
|
1229
|
+
|
|
1212
1230
|
case "context_overflow":
|
|
1213
1231
|
removeMatePreThinking();
|
|
1214
1232
|
setActivity(null);
|
|
@@ -1371,6 +1389,11 @@ export function processMessage(msg) {
|
|
|
1371
1389
|
updateTerminalList(msg.terminals);
|
|
1372
1390
|
break;
|
|
1373
1391
|
|
|
1392
|
+
case "shell_command_result":
|
|
1393
|
+
handleShellCommandResult(msg);
|
|
1394
|
+
if (!msg.error) sendShellResultToAgent(msg);
|
|
1395
|
+
break;
|
|
1396
|
+
|
|
1374
1397
|
case "context_sources_state":
|
|
1375
1398
|
handleContextSourcesState(msg);
|
|
1376
1399
|
break;
|
|
@@ -5,7 +5,7 @@ import { refreshIcons } from "./icons.js";
|
|
|
5
5
|
import { escapeHtml, showToast } from "./utils.js";
|
|
6
6
|
import { store } from './store.js';
|
|
7
7
|
import { getWs } from './ws-ref.js';
|
|
8
|
-
import { VENDOR_NAMES } from './app-rendering.js';
|
|
8
|
+
import { VENDOR_NAMES, isExperimentalVendor } from './app-rendering.js';
|
|
9
9
|
import { reportPaneContext } from './pane-bridge.js';
|
|
10
10
|
|
|
11
11
|
// --- Module-owned state (not in store) ---
|
|
@@ -89,7 +89,7 @@ var EFFORT_LEVELS = ["low", "medium", "high", "xhigh", "max"];
|
|
|
89
89
|
var EFFORT_LEVELS_BY_VENDOR = {
|
|
90
90
|
claude: ["low", "medium", "high", "xhigh", "max"],
|
|
91
91
|
codex: ["minimal", "low", "medium", "high", "xhigh"],
|
|
92
|
-
|
|
92
|
+
antigravity: [],
|
|
93
93
|
opencode: [],
|
|
94
94
|
kiro: ["low", "medium", "high", "xhigh", "max"],
|
|
95
95
|
};
|
|
@@ -443,14 +443,24 @@ export function initPanels() {
|
|
|
443
443
|
var vendorToggleWrap = $("vendor-toggle-wrap");
|
|
444
444
|
var vendorBtnClaude = $("vendor-btn-claude");
|
|
445
445
|
var vendorBtnCodex = $("vendor-btn-codex");
|
|
446
|
-
var
|
|
446
|
+
var vendorBtnAntigravity = $("vendor-btn-antigravity");
|
|
447
447
|
var vendorBtnOpenCode = $("vendor-btn-opencode");
|
|
448
|
+
var vendorBtnKimi = $("vendor-btn-kimi");
|
|
449
|
+
var vendorBtnGrok = $("vendor-btn-grok");
|
|
450
|
+
var vendorBtnCopilot = $("vendor-btn-copilot");
|
|
451
|
+
var vendorBtnQwen = $("vendor-btn-qwen");
|
|
452
|
+
var vendorBtnJunie = $("vendor-btn-junie");
|
|
448
453
|
var vendorBtnKiro = $("vendor-btn-kiro");
|
|
449
454
|
var vendorBtns = {
|
|
450
455
|
claude: vendorBtnClaude,
|
|
451
456
|
codex: vendorBtnCodex,
|
|
452
|
-
|
|
457
|
+
antigravity: vendorBtnAntigravity,
|
|
453
458
|
opencode: vendorBtnOpenCode,
|
|
459
|
+
kimi: vendorBtnKimi,
|
|
460
|
+
grok: vendorBtnGrok,
|
|
461
|
+
copilot: vendorBtnCopilot,
|
|
462
|
+
qwen: vendorBtnQwen,
|
|
463
|
+
junie: vendorBtnJunie,
|
|
454
464
|
kiro: vendorBtnKiro,
|
|
455
465
|
};
|
|
456
466
|
|
|
@@ -466,7 +476,10 @@ export function initPanels() {
|
|
|
466
476
|
var isInstalled = installed.indexOf(v) !== -1;
|
|
467
477
|
btn.classList.toggle("active", v === current);
|
|
468
478
|
btn.classList.toggle("disabled", !isInstalled);
|
|
469
|
-
btn.
|
|
479
|
+
btn.classList.toggle("experimental", isExperimentalVendor(v));
|
|
480
|
+
var title = isInstalled ? (VENDOR_NAMES[v] || v) : (VENDOR_NAMES[v] || v) + " is not installed";
|
|
481
|
+
if (isExperimentalVendor(v)) title += " · Experimental integration; not yet validated through direct use testing";
|
|
482
|
+
btn.title = title;
|
|
470
483
|
}
|
|
471
484
|
}
|
|
472
485
|
|
|
@@ -474,15 +487,20 @@ export function initPanels() {
|
|
|
474
487
|
if (vendor === (store.get('currentVendor') || "claude")) return;
|
|
475
488
|
var installed = store.get('installedVendors') || [];
|
|
476
489
|
if (installed.indexOf(vendor) === -1) return;
|
|
477
|
-
store.set({ currentVendor: vendor, currentModel: "", currentModels: [], vendorSelectionLocked: true });
|
|
490
|
+
store.set({ currentVendor: vendor, currentModel: "", currentModels: [], vendorSelectionLocked: true, sessionVendorBound: true });
|
|
478
491
|
var ws = getWs();
|
|
479
492
|
if (ws) ws.send(JSON.stringify({ type: "set_vendor", vendor: vendor }));
|
|
480
493
|
}
|
|
481
494
|
|
|
482
495
|
if (vendorBtnClaude) vendorBtnClaude.addEventListener("click", function() { onVendorClick("claude"); });
|
|
483
496
|
if (vendorBtnCodex) vendorBtnCodex.addEventListener("click", function() { onVendorClick("codex"); });
|
|
484
|
-
if (
|
|
497
|
+
if (vendorBtnAntigravity) vendorBtnAntigravity.addEventListener("click", function() { onVendorClick("antigravity"); });
|
|
485
498
|
if (vendorBtnOpenCode) vendorBtnOpenCode.addEventListener("click", function() { onVendorClick("opencode"); });
|
|
499
|
+
if (vendorBtnKimi) vendorBtnKimi.addEventListener("click", function() { onVendorClick("kimi"); });
|
|
500
|
+
if (vendorBtnGrok) vendorBtnGrok.addEventListener("click", function() { onVendorClick("grok"); });
|
|
501
|
+
if (vendorBtnCopilot) vendorBtnCopilot.addEventListener("click", function() { onVendorClick("copilot"); });
|
|
502
|
+
if (vendorBtnQwen) vendorBtnQwen.addEventListener("click", function() { onVendorClick("qwen"); });
|
|
503
|
+
if (vendorBtnJunie) vendorBtnJunie.addEventListener("click", function() { onVendorClick("junie"); });
|
|
486
504
|
if (vendorBtnKiro) vendorBtnKiro.addEventListener("click", function() { onVendorClick("kiro"); });
|
|
487
505
|
|
|
488
506
|
// --- Reactive UI sync ---
|
|
@@ -861,7 +879,9 @@ export function updateContextPanel() {
|
|
|
861
879
|
hCtxEl = document.createElement("div");
|
|
862
880
|
hCtxEl.className = "header-context";
|
|
863
881
|
hCtxEl.innerHTML = '<div class="header-context-bar"><div class="header-context-fill"></div></div><span class="header-context-label"></span>';
|
|
864
|
-
|
|
882
|
+
var workerBtn = document.getElementById("header-add-worker-btn");
|
|
883
|
+
var contextAnchor = workerBtn && workerBtn.parentNode === statusArea ? workerBtn.nextSibling : statusArea.firstChild;
|
|
884
|
+
statusArea.insertBefore(hCtxEl, contextAnchor);
|
|
865
885
|
hCtxEl.addEventListener("mouseenter", function() {
|
|
866
886
|
if (store.get('richContextUsage')) {
|
|
867
887
|
showCtxPopover();
|
|
@@ -24,6 +24,7 @@ import { isSchedulerOpen, closeScheduler, resetScheduler } from './scheduler.js'
|
|
|
24
24
|
import { connect, cancelReconnect, setStatus } from './app-connection.js';
|
|
25
25
|
import { setTurnCounter, setPrependAnchor, setActivityEl, setIsUserScrolledUp, hideSuggestionChips } from './app-rendering.js';
|
|
26
26
|
import { resetToolState, enableMainInput, resetTurnMetaCost } from './tools.js';
|
|
27
|
+
import { resetShellCommand } from './shell-command.js';
|
|
27
28
|
import { clearPendingImages } from './input.js';
|
|
28
29
|
import { clearAllMentionActive } from './sidebar-mates.js';
|
|
29
30
|
import { setRewindMode } from './rewind.js';
|
|
@@ -321,7 +322,7 @@ export function renderProjectList() {
|
|
|
321
322
|
isWorktree: p.isWorktree || false,
|
|
322
323
|
parentSlug: p.parentSlug || null,
|
|
323
324
|
branch: p.branch || null,
|
|
324
|
-
|
|
325
|
+
worktreeExternal: p.worktreeExternal === true,
|
|
325
326
|
};
|
|
326
327
|
});
|
|
327
328
|
var st = store.snap();
|
|
@@ -368,6 +369,7 @@ export function resetClientState() {
|
|
|
368
369
|
store.set({ currentFullText: "" });
|
|
369
370
|
resetToolState();
|
|
370
371
|
clearPendingImages();
|
|
372
|
+
resetShellCommand();
|
|
371
373
|
clearAllMentionActive();
|
|
372
374
|
setActivityEl(null);
|
|
373
375
|
store.set({ processing: false });
|