claude-remote-cli 2.8.0 → 2.9.1
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/README.md +5 -2
- package/dist/frontend/assets/index-BnHx9G72.js +47 -0
- package/dist/frontend/assets/index-CEuXqdk2.css +32 -0
- package/dist/frontend/index.html +2 -2
- package/dist/server/config.js +1 -0
- package/dist/server/index.js +27 -9
- package/dist/server/sessions.js +25 -9
- package/dist/test/config.test.js +2 -0
- package/dist/test/sessions.test.js +35 -0
- package/package.json +1 -1
- package/dist/frontend/assets/index-CUkDx_1l.js +0 -47
- package/dist/frontend/assets/index-Not5cXLa.css +0 -32
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
.pin-gate.svelte-1qp96yb{display:flex;align-items:center;justify-content:center;height:100vh;background:var(--bg);padding:1rem}.pin-container.svelte-1qp96yb{display:flex;flex-direction:column;align-items:center;gap:1rem;width:100%;max-width:320px;text-align:center}.pin-container.svelte-1qp96yb h1:where(.svelte-1qp96yb){font-size:1.5rem;color:var(--text)}.pin-container.svelte-1qp96yb p:where(.svelte-1qp96yb){color:var(--text-muted);font-size:.95rem}input.svelte-1qp96yb{width:100%;padding:14px 16px;background:var(--surface);border:1px solid var(--border);border-radius:8px;color:var(--text);font-size:1.2rem;text-align:center;outline:none;-webkit-appearance:none}input.svelte-1qp96yb:focus{border-color:var(--accent)}button.svelte-1qp96yb{width:100%;padding:14px;background:var(--accent);color:#fff;border:none;border-radius:8px;font-size:1rem;font-weight:600;cursor:pointer;touch-action:manipulation}button.svelte-1qp96yb:active{opacity:.8}.error.svelte-1qp96yb{color:var(--accent);font-size:.9rem}.agent-badge.svelte-1ydsu2f{width:10px;height:10px;color:var(--text-muted);flex-shrink:0}li.svelte-ix4pl2{position:relative;display:flex;align-items:flex-start;padding:8px 10px;cursor:pointer;border-radius:6px;margin:2px 6px;font-size:.8rem;color:var(--text-muted);touch-action:manipulation;transition:background .15s,border-color .15s}li.active-session.svelte-ix4pl2{background:var(--bg)}li.active-session.svelte-ix4pl2:hover,li.active-session.svelte-ix4pl2.longpress{background:var(--border)}li.active-session.selected.svelte-ix4pl2{background:var(--accent);color:#fff}li.active-session.selected.svelte-ix4pl2 .session-sub:where(.svelte-ix4pl2),li.active-session.selected.svelte-ix4pl2 .session-time:where(.svelte-ix4pl2){color:#ffffffb3}li.inactive-worktree.svelte-ix4pl2{background:transparent;border:1px solid var(--border);color:var(--text-muted);opacity:.7}li.inactive-worktree.svelte-ix4pl2:hover,li.inactive-worktree.svelte-ix4pl2.longpress{opacity:1;border-color:var(--accent)}li.loading.svelte-ix4pl2{pointer-events:none;opacity:.5}li.loading.svelte-ix4pl2:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0;border-radius:inherit;background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.04) 50%,transparent 100%);background-size:200% 100%;animation:svelte-ix4pl2-shimmer 1.5s ease-in-out infinite;pointer-events:none}@media(prefers-reduced-motion:reduce){li.loading.svelte-ix4pl2:after{animation:none}}@keyframes svelte-ix4pl2-shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}.session-info.svelte-ix4pl2{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.session-row-1.svelte-ix4pl2{display:flex;align-items:center;min-width:0}.status-dot.svelte-ix4pl2{display:inline-block;width:8px;height:8px;border-radius:50%;flex-shrink:0;margin-right:8px}.status-dot--running.svelte-ix4pl2{background:#4ade80}.status-dot--idle.svelte-ix4pl2{background:#60a5fa}.status-dot--attention.svelte-ix4pl2{background:#f59e0b;box-shadow:0 0 6px 2px #f59e0b80;animation:svelte-ix4pl2-attention-glow 2s ease-in-out infinite}.status-dot--inactive.svelte-ix4pl2{background:#6b7280}@keyframes svelte-ix4pl2-attention-glow{0%,to{box-shadow:0 0 4px 1px #f59e0b4d}50%{box-shadow:0 0 8px 3px #f59e0b99}}.session-name.svelte-ix4pl2{flex:1;min-width:0;overflow:hidden;white-space:nowrap;font-weight:500;color:var(--text)}.session-name-text.svelte-ix4pl2{display:inline-block;white-space:nowrap;will-change:transform}.session-name.has-overflow.svelte-ix4pl2{mask-image:linear-gradient(to right,black calc(100% - 32px),transparent);-webkit-mask-image:linear-gradient(to right,black calc(100% - 32px),transparent)}li.svelte-ix4pl2:hover .session-name.has-overflow:where(.svelte-ix4pl2),li.svelte-ix4pl2.longpress .session-name.has-overflow:where(.svelte-ix4pl2){mask-image:none;-webkit-mask-image:none}li.active-session.selected.svelte-ix4pl2 .session-name:where(.svelte-ix4pl2){color:#fff}li.active-session.selected.svelte-ix4pl2 .session-name.has-overflow:where(.svelte-ix4pl2){mask-image:linear-gradient(to right,white calc(100% - 32px),transparent);-webkit-mask-image:linear-gradient(to right,white calc(100% - 32px),transparent)}li.active-session.selected.svelte-ix4pl2:hover .session-name.has-overflow:where(.svelte-ix4pl2),li.active-session.selected.svelte-ix4pl2.longpress .session-name.has-overflow:where(.svelte-ix4pl2){mask-image:none;-webkit-mask-image:none}.action-pill.svelte-ix4pl2{background:var(--border);border:none;color:var(--text);font-size:.75rem;cursor:pointer;padding:2px 8px;border-radius:12px;touch-action:manipulation;flex-shrink:0;min-height:24px;display:inline-flex;align-items:center;transition:background .15s,color .15s;line-height:1}.action-pill.svelte-ix4pl2:hover{background:#505050}.action-pill--mono.svelte-ix4pl2{font-family:monospace;font-size:.65rem;letter-spacing:.02em}.action-pill--danger.svelte-ix4pl2:hover{background:#4a2020;color:#e74c3c}li.active-session.selected.svelte-ix4pl2 .action-pill:where(.svelte-ix4pl2){background:#b35a3a;color:#fff}li.active-session.selected.svelte-ix4pl2 .action-pill:where(.svelte-ix4pl2):hover{background:#9a4d32}li.active-session.selected.svelte-ix4pl2 .action-pill--danger:where(.svelte-ix4pl2):hover{background:#8b2020;color:#fca5a5}.session-actions.svelte-ix4pl2{position:absolute;right:10px;top:50%;transform:translateY(-50%);display:flex;align-items:center;gap:4px;opacity:0;visibility:hidden;transition:opacity .15s .1s,visibility .15s .1s}li.svelte-ix4pl2:hover .session-actions:where(.svelte-ix4pl2),li.svelte-ix4pl2:focus-within .session-actions:where(.svelte-ix4pl2),li.svelte-ix4pl2.longpress .session-actions:where(.svelte-ix4pl2){opacity:1;visibility:visible}.session-row-2.svelte-ix4pl2{display:flex;align-items:center;gap:4px;min-width:0;padding-left:16px}.session-row-2.has-badge.svelte-ix4pl2{padding-left:2px}.pr-icon.svelte-ix4pl2{font-size:.65rem;flex-shrink:0}.pr-open.svelte-ix4pl2{color:#4ade80}.pr-merged.svelte-ix4pl2{color:#a78bfa}.pr-closed.svelte-ix4pl2{color:#f87171}.session-sub.svelte-ix4pl2{font-size:.7rem;color:var(--text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.session-row-3.svelte-ix4pl2{display:flex;align-items:center;gap:6px;min-width:0;padding-left:16px}.session-time.svelte-ix4pl2{font-size:.65rem;color:var(--text-muted);opacity:.6}.git-diff.svelte-ix4pl2{display:flex;gap:4px;font-size:.65rem;font-family:monospace}.diff-add.svelte-ix4pl2{color:#4ade80}.diff-del.svelte-ix4pl2{color:#f87171}.sidebar-filters.svelte-1o5d4l8{display:flex;flex-direction:column;gap:4px;padding:6px 8px;flex-shrink:0}select.svelte-1o5d4l8{padding:6px 8px;background:var(--bg);border:1px solid var(--border);border-radius:6px;color:var(--text);font-size:.75rem;outline:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23aaa' fill='none' stroke-width='1.5'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 8px center;cursor:pointer;transition:border-color .15s,box-shadow .3s}select.svelte-1o5d4l8:focus{border-color:var(--accent)}input.svelte-1o5d4l8{padding:6px 8px;background:var(--bg);border:1px solid var(--border);border-radius:6px;color:var(--text);font-size:.75rem;outline:none;-webkit-appearance:none}input.svelte-1o5d4l8:focus{border-color:var(--accent)}.role-filter.svelte-1o5d4l8{display:flex;gap:0;border:1px solid var(--border);border-radius:6px;overflow:hidden}.role-btn.svelte-1o5d4l8{flex:1;padding:5px 8px;background:var(--bg);border:none;border-right:1px solid var(--border);color:var(--text-muted);font-size:.7rem;cursor:pointer;transition:background .15s,color .15s}.role-btn.svelte-1o5d4l8:last-child{border-right:none}.role-btn.svelte-1o5d4l8:hover{color:var(--text)}.role-btn.active.svelte-1o5d4l8{background:var(--accent);color:#fff}li.pr-item.svelte-jhsg4e{position:relative;display:flex;align-items:flex-start;padding:8px 10px;cursor:pointer;border-radius:6px;margin:2px 6px;font-size:.8rem;color:var(--text-muted);touch-action:manipulation;transition:background .15s,border-color .15s;background:transparent;border:1px solid var(--border);opacity:.8}li.pr-item.svelte-jhsg4e:hover,li.pr-item.svelte-jhsg4e.longpress{opacity:1;border-color:var(--accent)}li.pr-item.active-session.svelte-jhsg4e{background:var(--bg);border-color:var(--accent);opacity:1}li.pr-item.selected.svelte-jhsg4e{background:var(--accent);border-color:var(--accent);color:#fff;opacity:1}li.pr-item.selected.svelte-jhsg4e .pr-title:where(.svelte-jhsg4e){color:#fff}li.pr-item.selected.svelte-jhsg4e .pr-meta:where(.svelte-jhsg4e),li.pr-item.selected.svelte-jhsg4e .pr-time:where(.svelte-jhsg4e){color:#ffffffb3}li.pr-item.selected.svelte-jhsg4e .role-badge:where(.svelte-jhsg4e){background:#fff3;color:#fff}.pr-info.svelte-jhsg4e{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.pr-row-1.svelte-jhsg4e{display:flex;align-items:center;min-width:0}.pr-state{font-size:.65rem;flex-shrink:0;width:16px;text-align:center;margin-right:4px}.pr-open{color:#4ade80}.pr-merged{color:#a78bfa}.pr-closed{color:#f87171}.pr-title.svelte-jhsg4e{flex:1;min-width:0;overflow:hidden;white-space:nowrap;font-weight:500;color:var(--text)}.pr-title-text.svelte-jhsg4e{display:inline-block;white-space:nowrap;will-change:transform}.pr-title.has-overflow.svelte-jhsg4e{mask-image:linear-gradient(to right,black calc(100% - 32px),transparent);-webkit-mask-image:linear-gradient(to right,black calc(100% - 32px),transparent)}li.svelte-jhsg4e:hover .pr-title.has-overflow:where(.svelte-jhsg4e),li.svelte-jhsg4e.longpress .pr-title.has-overflow:where(.svelte-jhsg4e){mask-image:none;-webkit-mask-image:none}.pr-actions.svelte-jhsg4e{position:absolute;right:10px;top:50%;transform:translateY(-50%);display:flex;align-items:center;gap:2px;opacity:0;visibility:hidden;transition:opacity .15s .1s,visibility .15s .1s}li.svelte-jhsg4e:hover .pr-actions:where(.svelte-jhsg4e),li.svelte-jhsg4e:focus-within .pr-actions:where(.svelte-jhsg4e),li.svelte-jhsg4e.longpress .pr-actions:where(.svelte-jhsg4e){opacity:1;visibility:visible}.action-pill.svelte-jhsg4e{background:var(--border);border:none;color:var(--text);font-size:.75rem;cursor:pointer;padding:2px 8px;border-radius:12px;touch-action:manipulation;flex-shrink:0;min-height:24px;display:inline-flex;align-items:center;transition:background .15s,color .15s;line-height:1}.action-pill.svelte-jhsg4e:hover{background:#505050}.action-pill--mono.svelte-jhsg4e{font-family:monospace;font-size:.65rem;letter-spacing:.02em}li.pr-item.selected.svelte-jhsg4e .action-pill:where(.svelte-jhsg4e){background:#b35a3a;color:#fff}li.pr-item.selected.svelte-jhsg4e .action-pill:where(.svelte-jhsg4e):hover{background:#9a4d32}.external-link-btn.svelte-jhsg4e{background:none;border:none;color:var(--text-muted);cursor:pointer;padding:2px 4px;border-radius:4px;touch-action:manipulation;flex-shrink:0;display:inline-flex;align-items:center;transition:color .15s,transform .15s}.external-link-btn.svelte-jhsg4e:hover{color:var(--accent);transform:scale(1.1)}li.pr-item.selected.svelte-jhsg4e .external-link-btn:where(.svelte-jhsg4e){color:#ffffffb3}li.pr-item.selected.svelte-jhsg4e .external-link-btn:where(.svelte-jhsg4e):hover{color:#fff}.review-badge.svelte-jhsg4e{font-size:.7rem;padding:0 3px}.review-approved.svelte-jhsg4e{color:#4ade80}.review-changes.svelte-jhsg4e{color:#f87171}.review-pending.svelte-jhsg4e{color:#f59e0b}.pr-row-2.svelte-jhsg4e{display:flex;align-items:center;gap:4px;min-width:0;padding-left:20px}.pr-meta.svelte-jhsg4e{font-size:.7rem;color:var(--text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.role-badge.svelte-jhsg4e{font-size:.6rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;padding:1px 5px;border-radius:3px;flex-shrink:0}.role-author.svelte-jhsg4e{background:#60a5fa26;color:#60a5fa}.role-reviewer.svelte-jhsg4e{background:#a78bfa26;color:#a78bfa}.pr-row-3.svelte-jhsg4e{display:flex;align-items:center;gap:6px;min-width:0;padding-left:20px}.pr-time.svelte-jhsg4e{font-size:.65rem;color:var(--text-muted);opacity:.6}.git-diff.svelte-jhsg4e{display:flex;gap:4px;font-size:.65rem;font-family:monospace}.diff-add.svelte-jhsg4e{color:#4ade80}.diff-del.svelte-jhsg4e{color:#f87171}.repo-group-refresh.svelte-1ekl114{background:none;border:none;color:var(--text-muted);font-size:.75rem;cursor:pointer;padding:0 4px;flex-shrink:0;transition:color .15s}.repo-group-refresh.svelte-1ekl114:hover{color:var(--accent)}.repo-group-refresh.svelte-1ekl114:disabled{opacity:.5;cursor:not-allowed}.spinning.svelte-1ekl114{display:inline-block;animation:svelte-1ekl114-spin 1s linear infinite}@keyframes svelte-1ekl114-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.session-list-tabs.svelte-ynafm7{display:flex;padding:0 8px;border-bottom:1px solid var(--border)}.sidebar-tab.svelte-ynafm7{flex:1;background:none;border:none;border-bottom:2px solid transparent;color:var(--text-muted);font-size:.7rem;padding:6px 4px;cursor:pointer;transition:color .15s,border-color .15s;text-align:center}.sidebar-tab.svelte-ynafm7:hover{color:var(--text)}.sidebar-tab.active.svelte-ynafm7{color:var(--accent);border-bottom-color:var(--accent)}.tab-count.svelte-ynafm7{opacity:.7}.session-list.svelte-ynafm7{list-style:none;flex:1;overflow-y:auto;padding:8px 0}.session-divider{font-size:.65rem;font-weight:600;color:var(--text-muted);text-transform:uppercase;letter-spacing:.05em;padding:8px 12px 4px;opacity:.6;list-style:none}.repo-group-header{display:flex;align-items:center;gap:4px;padding:6px 10px;cursor:pointer;list-style:none;transition:background .15s;border-radius:4px;margin:2px 6px}.repo-group-header:hover{background:var(--border)}.chevron{display:inline-block;font-size:.55rem;transition:transform .15s;color:var(--text-muted);flex-shrink:0}.chevron.expanded{transform:rotate(90deg)}.repo-group-name{font-size:.7rem;font-weight:600;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.repo-group-root{font-size:.6rem;color:var(--text-muted);opacity:.6;flex-shrink:0}.repo-group-count{font-size:.6rem;color:var(--text-muted);opacity:.5;margin-left:auto;flex-shrink:0}.repo-group-add{background:none;border:none;color:var(--text-muted);font-size:.8rem;font-weight:600;cursor:pointer;padding:0 4px;flex-shrink:0;line-height:1;transition:color .15s;opacity:0}.repo-group-header:hover .repo-group-add{opacity:1}.repo-group-add:hover,.repo-group-add:focus-visible{color:var(--accent);opacity:1}.pr-hint{font-size:.75rem;color:var(--text-muted);text-align:center;padding:20px 12px;opacity:.6;list-style:none}.pr-hint-sub{font-size:.65rem;opacity:.8;display:block;margin-top:4px}.pr-hint code{background:var(--bg);padding:1px 4px;border-radius:3px;font-size:.65rem}.sidebar.svelte-owj5vn{position:relative;display:flex;flex-direction:column;background:var(--surface);border-right:1px solid var(--border);overflow:hidden;transition:transform .25s ease,width .2s ease,min-width .2s ease;z-index:100}.resize-handle.svelte-owj5vn{position:absolute;top:0;right:0;width:4px;height:100%;cursor:col-resize;z-index:10;transition:background .15s}.resize-handle.svelte-owj5vn:hover{background:var(--accent)}.sidebar-header.svelte-owj5vn{display:flex;align-items:center;justify-content:space-between;padding:12px 10px;border-bottom:1px solid var(--border);flex-shrink:0}.sidebar-label.svelte-owj5vn{flex:1;font-size:.85rem;font-weight:600;color:var(--text-muted);text-transform:uppercase;letter-spacing:.05em}.collapse-btn.svelte-owj5vn{background:none;border:none;color:var(--text-muted);font-size:1.1rem;cursor:pointer;padding:4px 8px;border-radius:4px;flex-shrink:0;line-height:1}.collapse-btn.svelte-owj5vn:hover{color:var(--text);background:var(--border)}.sidebar.collapsed.svelte-owj5vn .sidebar-header:where(.svelte-owj5vn){justify-content:center;padding:12px 4px}.icon-btn.svelte-owj5vn{background:none;border:none;color:var(--text);font-size:1.2rem;cursor:pointer;padding:4px 6px;border-radius:4px;touch-action:manipulation;display:none}.icon-btn.svelte-owj5vn:active{background:var(--border)}.new-session-btn.svelte-owj5vn{margin:8px;padding:10px 12px;background:none;border:1px solid var(--border);border-radius:6px;color:var(--text);font-size:.875rem;cursor:pointer;touch-action:manipulation;text-align:center;flex-shrink:0}.new-session-btn.svelte-owj5vn:active{background:var(--border)}.settings-btn.svelte-owj5vn{margin:0 8px 8px;padding:10px 12px;background:none;border:1px solid var(--border);border-radius:6px;color:var(--text-muted);font-size:.8rem;cursor:pointer;touch-action:manipulation;text-align:center;flex-shrink:0}.settings-btn.svelte-owj5vn:active{background:var(--border)}@media(max-width:600px){.sidebar.svelte-owj5vn{position:fixed;top:0;left:0;height:100%;transform:translate(-100%);box-shadow:2px 0 12px #00000080;transition:transform .25s ease}.sidebar.open.svelte-owj5vn{transform:translate(0)}.collapse-btn.svelte-owj5vn{display:none}.icon-btn.svelte-owj5vn{display:block;font-size:1.4rem;padding:4px 8px}.resize-handle.svelte-owj5vn{display:none}}/**
|
|
2
|
+
* Copyright (c) 2014 The xterm.js authors. All rights reserved.
|
|
3
|
+
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
|
|
4
|
+
* https://github.com/chjj/term.js
|
|
5
|
+
* @license MIT
|
|
6
|
+
*
|
|
7
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
* in the Software without restriction, including without limitation the rights
|
|
10
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
* furnished to do so, subject to the following conditions:
|
|
13
|
+
*
|
|
14
|
+
* The above copyright notice and this permission notice shall be included in
|
|
15
|
+
* all copies or substantial portions of the Software.
|
|
16
|
+
*
|
|
17
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23
|
+
* THE SOFTWARE.
|
|
24
|
+
*
|
|
25
|
+
* Originally forked from (with the author's permission):
|
|
26
|
+
* Fabrice Bellard's javascript vt100 for jslinux:
|
|
27
|
+
* http://bellard.org/jslinux/
|
|
28
|
+
* Copyright (c) 2011 Fabrice Bellard
|
|
29
|
+
* The original design remains. The terminal itself
|
|
30
|
+
* has been extended to include xterm CSI codes, among
|
|
31
|
+
* other features.
|
|
32
|
+
*/.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{font-family:monospace;-webkit-user-select:text;user-select:text;white-space:pre}.xterm .xterm-accessibility-tree>div{transform-origin:left;width:fit-content}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}.xterm .xterm-scrollable-element>.scrollbar{cursor:default}.xterm .xterm-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important}.xterm .xterm-scrollable-element>.visible{opacity:1;background:#0000;transition:opacity .1s linear;z-index:11}.xterm .xterm-scrollable-element>.invisible{opacity:0;pointer-events:none}.xterm .xterm-scrollable-element>.invisible.fade{transition:opacity .8s linear}.xterm .xterm-scrollable-element>.shadow{position:absolute;display:none}.xterm .xterm-scrollable-element>.shadow.top{display:block;top:0;left:3px;height:3px;width:100%;box-shadow:var(--vscode-scrollbar-shadow, #000) 0 6px 6px -6px inset}.xterm .xterm-scrollable-element>.shadow.left{display:block;top:3px;left:0;height:100%;width:3px;box-shadow:var(--vscode-scrollbar-shadow, #000) 6px 0 6px -6px inset}.xterm .xterm-scrollable-element>.shadow.top-left-corner{display:block;top:0;left:0;height:3px;width:3px}.xterm .xterm-scrollable-element>.shadow.top.left{box-shadow:var(--vscode-scrollbar-shadow, #000) 6px 0 6px -6px inset}.terminal-wrapper.svelte-5qgfij{display:flex;flex:1;min-height:0;position:relative;overflow:hidden}.terminal-container.svelte-5qgfij{flex:1;min-width:0;min-height:0;overflow:hidden;padding:4px}.terminal-wrapper.drag-over.svelte-5qgfij{outline:2px dashed var(--accent);outline-offset:-2px}.terminal-scrollbar.svelte-5qgfij{width:8px;background:transparent;position:relative;flex-shrink:0}.terminal-scrollbar-thumb.svelte-5qgfij{position:absolute;right:0;width:6px;background:var(--border);border-radius:3px;cursor:pointer}@media(hover:none){.terminal-wrapper.selection-mode.svelte-5qgfij .terminal-container:where(.svelte-5qgfij){outline:2px solid var(--accent);outline-offset:-2px}.terminal-container.svelte-5qgfij{touch-action:none}.terminal-scrollbar.svelte-5qgfij{width:12px}.terminal-scrollbar-thumb.svelte-5qgfij{width:8px;min-height:44px}.scroll-fabs.svelte-5qgfij{position:absolute;right:16px;top:50%;transform:translateY(-50%);display:flex;flex-direction:column;gap:12px;z-index:1;opacity:.6;pointer-events:auto}.scroll-fab.svelte-5qgfij{width:44px;height:44px;border-radius:50%;border:1px solid var(--border);background:var(--surface);color:var(--text);font-size:18px;display:flex;align-items:center;justify-content:center;cursor:pointer;touch-action:manipulation;-webkit-user-select:none;user-select:none}.scroll-fab.svelte-5qgfij:active{opacity:1;background:var(--border)}}.toolbar.svelte-k7we1m{background:var(--surface);border-top:1px solid var(--border);padding:4px;padding-bottom:calc(4px + env(safe-area-inset-bottom,0px));flex-shrink:0}.toolbar-grid.svelte-k7we1m{display:grid;grid-template-columns:repeat(6,1fr);gap:4px}.tb-btn.svelte-k7we1m{background:var(--bg);border:1px solid var(--border);border-radius:6px;color:var(--text);font-size:.85rem;padding:8px 4px;cursor:pointer;touch-action:manipulation;min-height:40px;display:flex;align-items:center;justify-content:center;user-select:none;-webkit-user-select:none}.tb-btn.svelte-k7we1m:active{background:var(--border)}.tb-enter.svelte-k7we1m{background:var(--accent);border-color:var(--accent);color:#fff}.tb-enter.svelte-k7we1m:active{opacity:.8}.mobile-header.svelte-wp0i5g{display:none;align-items:center;gap:8px;padding:8px 12px;background:var(--surface);border-bottom:1px solid var(--border);min-height:44px;flex-shrink:0}@media(max-width:768px){.mobile-header.svelte-wp0i5g{display:flex}.mobile-header.hidden.svelte-wp0i5g{display:none}}.mobile-title.svelte-wp0i5g{font-size:.95rem;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}.icon-btn.svelte-wp0i5g{background:none;border:none;color:var(--text);font-size:1.2rem;cursor:pointer;padding:6px;min-width:36px;min-height:36px;display:flex;align-items:center;justify-content:center;border-radius:6px;touch-action:manipulation}.icon-btn.svelte-wp0i5g:hover{background:var(--border)}.mobile-input-form.svelte-us0qpd{position:fixed;top:0;left:0;width:1px;height:1px;padding:0;margin:0;overflow:hidden;clip-path:inset(50%);opacity:0;pointer-events:none}.mobile-input.svelte-us0qpd{width:100%;height:100%;background:transparent;border:none;outline:none;color:transparent;caret-color:transparent;font-size:16px}.mobile-input.svelte-us0qpd::-webkit-search-cancel-button,.mobile-input.svelte-us0qpd::-webkit-search-decoration{-webkit-appearance:none;-moz-appearance:none;appearance:none}.debug-toggle.svelte-us0qpd{position:fixed;bottom:60px;right:8px;z-index:10000;background:#333;color:#0f0;border:1px solid #0f0;border-radius:6px;font:12px monospace;padding:6px 10px;min-width:44px;min-height:44px;touch-action:manipulation}.debug-panel.svelte-us0qpd{position:fixed;top:0;left:0;right:0;bottom:0;overflow-y:scroll;-webkit-overflow-scrolling:touch;background:#000000eb;color:#0f0;font:11px/1.4 monospace;padding:6px 6px 6px 40px;z-index:9999;white-space:pre-wrap;word-break:break-all;overscroll-behavior:contain}.update-toast.svelte-1trivgv{position:fixed;bottom:0;left:0;right:0;z-index:150;display:flex;justify-content:center;padding:12px 12px calc(12px + env(safe-area-inset-bottom));pointer-events:none;animation:svelte-1trivgv-toast-slide-up .25s ease-out}@keyframes svelte-1trivgv-toast-slide-up{0%{transform:translateY(100%);opacity:0}to{transform:translateY(0);opacity:1}}.update-toast-content.svelte-1trivgv{display:flex;flex-direction:row;align-items:center;gap:12px;background:var(--surface);border:1px solid var(--border);border-radius:10px;padding:12px 16px;max-width:500px;box-shadow:0 4px 16px #0000004d;pointer-events:auto}.update-toast-text.svelte-1trivgv{flex:1;font-size:.85rem;color:var(--text)}.update-toast-actions.svelte-1trivgv{display:flex;gap:8px;flex-shrink:0}.update-toast-btn.svelte-1trivgv{padding:8px 14px;border-radius:6px;font-size:.8rem;border:none;background:var(--accent);color:#fff;cursor:pointer;white-space:nowrap}.update-toast-btn.svelte-1trivgv:disabled{opacity:.6;cursor:not-allowed}.update-toast-dismiss.svelte-1trivgv{background:none;border:none;color:var(--text-muted);font-size:1.2rem;padding:4px 6px;cursor:pointer}.update-toast-dismiss.svelte-1trivgv:hover{color:var(--text)}.image-toast.svelte-1y8sviv{position:fixed;bottom:60px;left:50%;transform:translate(-50%);z-index:1000;background:var(--surface);border:1px solid var(--border);border-radius:8px;padding:8px 14px;color:var(--text);font-size:13px;max-width:90vw;box-shadow:0 4px 12px #0006}.image-toast-content.svelte-1y8sviv{display:flex;align-items:center;gap:10px}.image-toast-text.svelte-1y8sviv{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:60vw}.image-toast-actions.svelte-1y8sviv{display:flex;gap:6px;align-items:center;flex-shrink:0}.image-toast-insert.svelte-1y8sviv{background:var(--accent);color:#fff;border:none;border-radius:4px;padding:4px 10px;font-size:12px;cursor:pointer}.image-toast-insert.svelte-1y8sviv:active{opacity:.8}.image-toast-dismiss.svelte-1y8sviv{background:none;border:none;color:var(--text-muted);cursor:pointer;font-size:16px;padding:2px 6px}.image-toast-dismiss.svelte-1y8sviv:hover{color:var(--text)}.dialog.svelte-thtd9b{background:var(--surface);color:var(--text);border:1px solid var(--border);border-radius:10px;padding:0;width:min(480px,95vw);max-height:90vh;overflow:hidden}.dialog.svelte-thtd9b::backdrop{background:#0009}.dialog-content.svelte-thtd9b{display:flex;flex-direction:column;max-height:90vh;overflow:hidden}.dialog-title.svelte-thtd9b{font-size:1.1rem;font-weight:600;padding:16px 20px 12px;margin:0;border-bottom:1px solid var(--border);flex-shrink:0}.dialog-tabs.svelte-thtd9b{display:flex;border-bottom:1px solid var(--border);flex-shrink:0}.dialog-tab.svelte-thtd9b{flex:1;padding:10px;background:none;border:none;color:var(--text-muted);font-size:.9rem;cursor:pointer;border-bottom:2px solid transparent;transition:color .15s,border-color .15s}.dialog-tab.active.svelte-thtd9b{color:var(--accent);border-bottom-color:var(--accent)}.dialog-tab.svelte-thtd9b:hover:not(.active){color:var(--text)}.dialog-body.svelte-thtd9b{padding:16px 20px;overflow-y:auto;flex:1;display:flex;flex-direction:column;gap:14px}.dialog-field.svelte-thtd9b{display:flex;flex-direction:column;gap:5px}.dialog-field--inline.svelte-thtd9b{flex-direction:row;align-items:center;gap:8px}.dialog-label.svelte-thtd9b{font-size:.85rem;color:var(--text-muted)}.dialog-label-inline.svelte-thtd9b{font-size:.9rem;cursor:pointer}.dialog-select.svelte-thtd9b,.dialog-input.svelte-thtd9b{background:var(--bg);border:1px solid var(--border);border-radius:6px;color:var(--text);font-size:.9rem;padding:7px 10px;width:100%;box-sizing:border-box}.dialog-select.svelte-thtd9b:disabled{opacity:.5;cursor:not-allowed}.dialog-checkbox.svelte-thtd9b{width:16px;height:16px;accent-color:var(--accent);cursor:pointer;flex-shrink:0}.branch-input-wrap.svelte-thtd9b{position:relative}.branch-dropdown.svelte-thtd9b{position:absolute;top:calc(100% + 2px);left:0;right:0;background:var(--surface);border:1px solid var(--border);border-radius:6px;list-style:none;margin:0;padding:4px 0;z-index:100;max-height:180px;overflow-y:auto}.branch-dropdown.svelte-thtd9b li:where(.svelte-thtd9b){padding:7px 12px;font-size:.9rem;cursor:pointer}.branch-dropdown.svelte-thtd9b li:where(.svelte-thtd9b):hover{background:var(--border)}.branch-create-new.svelte-thtd9b{color:var(--accent);border-bottom:1px solid var(--border)}.dialog-footer.svelte-thtd9b{display:flex;justify-content:flex-end;gap:10px;padding:12px 20px 16px;border-top:1px solid var(--border);flex-shrink:0}.btn.svelte-thtd9b{padding:8px 18px;border-radius:6px;font-size:.9rem;cursor:pointer;border:1px solid transparent;font-weight:500;transition:opacity .15s}.btn.svelte-thtd9b:disabled{opacity:.4;cursor:not-allowed}.btn-primary.svelte-thtd9b{background:var(--accent);color:#fff}.btn-primary.svelte-thtd9b:hover:not(:disabled){opacity:.9}.btn-ghost.svelte-thtd9b{background:transparent;color:var(--text-muted);border-color:var(--border)}.btn-ghost.svelte-thtd9b:hover{background:var(--border);color:var(--text)}.dialog.svelte-fdtoa4{background:var(--surface);color:var(--text);border:1px solid var(--border);border-radius:10px;padding:0;width:min(460px,95vw);max-height:90vh;overflow:hidden}.dialog.svelte-fdtoa4::backdrop{background:#0009}.dialog-content.svelte-fdtoa4{display:flex;flex-direction:column;max-height:90vh;overflow:hidden}.dialog-header.svelte-fdtoa4{display:flex;align-items:center;justify-content:space-between;padding:16px 20px 12px;border-bottom:1px solid var(--border);flex-shrink:0}.dialog-title.svelte-fdtoa4{font-size:1.1rem;font-weight:600;margin:0}.close-btn.svelte-fdtoa4{background:none;border:none;color:var(--text-muted);font-size:1rem;cursor:pointer;padding:4px 6px;border-radius:4px}.close-btn.svelte-fdtoa4:hover{background:var(--border);color:var(--text)}.dialog-body.svelte-fdtoa4{padding:16px 20px;overflow-y:auto;flex:1;display:flex;flex-direction:column;gap:20px}.settings-section.svelte-fdtoa4{display:flex;flex-direction:column;gap:10px}.section-title.svelte-fdtoa4{font-size:.9rem;font-weight:600;color:var(--text);margin:0}.section-desc.svelte-fdtoa4{font-size:.82rem;color:var(--text-muted);margin:0}.empty-msg.svelte-fdtoa4{font-size:.85rem;color:var(--text-muted);font-style:italic;margin:0}.roots-list.svelte-fdtoa4{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}.root-item.svelte-fdtoa4{display:flex;align-items:center;justify-content:space-between;gap:8px;background:var(--bg);border:1px solid var(--border);border-radius:6px;padding:7px 10px}.root-path.svelte-fdtoa4{font-size:.85rem;font-family:monospace;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}.remove-btn.svelte-fdtoa4{background:none;border:none;color:var(--text-muted);cursor:pointer;font-size:.9rem;padding:2px 5px;border-radius:4px;flex-shrink:0;line-height:1}.remove-btn.svelte-fdtoa4:hover{background:var(--border);color:var(--text)}.add-root-row.svelte-fdtoa4{display:flex;gap:8px}.add-root-input.svelte-fdtoa4{flex:1;background:var(--bg);border:1px solid var(--border);border-radius:6px;color:var(--text);font-size:.9rem;padding:7px 10px}.error-msg.svelte-fdtoa4{font-size:.82rem;color:#e74c3c;margin:0}.agent-select.svelte-fdtoa4{background:var(--bg);border:1px solid var(--border);border-radius:6px;color:var(--text);font-size:.9rem;padding:7px 10px;width:100%;box-sizing:border-box}.devtools-row.svelte-fdtoa4{display:flex;align-items:center;gap:8px}.dialog-checkbox.svelte-fdtoa4{width:16px;height:16px;accent-color:var(--accent);cursor:pointer;flex-shrink:0}.devtools-label.svelte-fdtoa4{font-size:.9rem;cursor:pointer}.dialog-footer.svelte-fdtoa4{display:flex;justify-content:flex-end;gap:10px;padding:12px 20px 16px;border-top:1px solid var(--border);flex-shrink:0}.btn.svelte-fdtoa4{padding:8px 18px;border-radius:6px;font-size:.9rem;cursor:pointer;border:1px solid transparent;font-weight:500}.btn-primary.svelte-fdtoa4{background:var(--accent);color:#fff;flex-shrink:0}.btn-primary.svelte-fdtoa4:hover{opacity:.9}.btn-ghost.svelte-fdtoa4{background:transparent;color:var(--text-muted);border-color:var(--border)}.btn-ghost.svelte-fdtoa4:hover{background:var(--border);color:var(--text)}.dialog.svelte-15sco2n{background:var(--surface);color:var(--text);border:1px solid var(--border);border-radius:10px;padding:0;width:min(400px,95vw);overflow:hidden}.dialog.svelte-15sco2n::backdrop{background:#0009}.dialog-content.svelte-15sco2n{display:flex;flex-direction:column}.dialog-title.svelte-15sco2n{font-size:1.1rem;font-weight:600;padding:16px 20px 12px;margin:0;border-bottom:1px solid var(--border)}.dialog-body.svelte-15sco2n{padding:16px 20px;display:flex;flex-direction:column;gap:8px}.confirm-msg.svelte-15sco2n{font-size:.95rem;margin:0;line-height:1.5}.wt-name.svelte-15sco2n{color:var(--text)}.wt-path.svelte-15sco2n{font-size:.82rem;color:var(--text-muted);font-family:monospace;margin:0;word-break:break-all}.warning-msg.svelte-15sco2n{font-size:.82rem;color:#e74c3c;margin:0}.error-msg.svelte-15sco2n{font-size:.85rem;color:#e74c3c;margin:0;padding:8px 10px;background:#e74c3c1a;border-radius:6px;border:1px solid rgba(231,76,60,.3)}.dialog-footer.svelte-15sco2n{display:flex;justify-content:flex-end;gap:10px;padding:12px 20px 16px;border-top:1px solid var(--border)}.btn.svelte-15sco2n{padding:8px 18px;border-radius:6px;font-size:.9rem;cursor:pointer;border:1px solid transparent;font-weight:500}.btn.svelte-15sco2n:disabled{opacity:.4;cursor:not-allowed}.btn-danger.svelte-15sco2n{background:#e74c3c;color:#fff}.btn-danger.svelte-15sco2n:hover:not(:disabled){opacity:.9}.btn-ghost.svelte-15sco2n{background:transparent;color:var(--text-muted);border-color:var(--border)}.btn-ghost.svelte-15sco2n:hover:not(:disabled){background:var(--border);color:var(--text)}.main-app.svelte-13zv0lp{display:flex;flex-direction:row;width:100%;height:100vh;height:100dvh;overflow:hidden}.sidebar-overlay.svelte-13zv0lp{display:none}.terminal-area.svelte-13zv0lp{flex:1;display:flex;flex-direction:column;min-width:0;overflow:hidden;position:relative}.no-session-msg.svelte-13zv0lp{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);color:var(--text-muted);font-size:.95rem;text-align:center;pointer-events:none}@media(max-width:600px){.main-app.svelte-13zv0lp{position:fixed;top:0;right:0;bottom:0;left:0;width:100%}.sidebar-overlay.svelte-13zv0lp{display:block;position:fixed;top:0;right:0;bottom:0;left:0;background:#00000080;z-index:99}.terminal-area.svelte-13zv0lp{width:100%}}:root{--bg: #1a1a1a;--surface: #2b2b2b;--accent: #d97757;--text: #ececec;--text-muted: #9b9b9b;--border: #3d3d3d;--sidebar-width: 240px;--toolbar-height: auto}[hidden]{display:none!important}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}dialog{margin:auto}html,body{height:100%;overflow:hidden;overscroll-behavior:none;background:var(--bg);color:var(--text);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;font-size:15px}::-webkit-scrollbar{width:4px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--border);border-radius:4px}
|
package/dist/frontend/index.html
CHANGED
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
12
12
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
|
13
13
|
<meta name="theme-color" content="#1a1a1a" />
|
|
14
|
-
<script type="module" crossorigin src="/assets/index-
|
|
15
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
14
|
+
<script type="module" crossorigin src="/assets/index-BnHx9G72.js"></script>
|
|
15
|
+
<link rel="stylesheet" crossorigin href="/assets/index-CEuXqdk2.css">
|
|
16
16
|
</head>
|
|
17
17
|
<body>
|
|
18
18
|
<div id="app"></div>
|
package/dist/server/config.js
CHANGED
package/dist/server/index.js
CHANGED
|
@@ -11,6 +11,7 @@ import cookieParser from 'cookie-parser';
|
|
|
11
11
|
import { loadConfig, saveConfig, DEFAULTS, readMeta, writeMeta, deleteMeta, ensureMetaDir } from './config.js';
|
|
12
12
|
import * as auth from './auth.js';
|
|
13
13
|
import * as sessions from './sessions.js';
|
|
14
|
+
import { AGENT_CONTINUE_ARGS } from './sessions.js';
|
|
14
15
|
import { setupWebSocket } from './ws.js';
|
|
15
16
|
import { WorktreeWatcher, WORKTREE_DIRS, isValidWorktreePath, parseWorktreeListPorcelain, parseAllWorktrees } from './watcher.js';
|
|
16
17
|
import { isInstalled as serviceIsInstalled } from './service.js';
|
|
@@ -500,6 +501,21 @@ async function main() {
|
|
|
500
501
|
broadcastEvent('worktrees-changed');
|
|
501
502
|
res.json(config.rootDirs);
|
|
502
503
|
});
|
|
504
|
+
// GET /config/defaultAgent — get default coding agent
|
|
505
|
+
app.get('/config/defaultAgent', requireAuth, (_req, res) => {
|
|
506
|
+
res.json({ defaultAgent: config.defaultAgent || 'claude' });
|
|
507
|
+
});
|
|
508
|
+
// PATCH /config/defaultAgent — set default coding agent
|
|
509
|
+
app.patch('/config/defaultAgent', requireAuth, (req, res) => {
|
|
510
|
+
const { defaultAgent } = req.body;
|
|
511
|
+
if (!defaultAgent || (defaultAgent !== 'claude' && defaultAgent !== 'codex')) {
|
|
512
|
+
res.status(400).json({ error: 'defaultAgent must be "claude" or "codex"' });
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
config.defaultAgent = defaultAgent;
|
|
516
|
+
saveConfig(CONFIG_PATH, config);
|
|
517
|
+
res.json({ defaultAgent: config.defaultAgent });
|
|
518
|
+
});
|
|
503
519
|
// DELETE /worktrees — remove a worktree, prune, and delete its branch
|
|
504
520
|
app.delete('/worktrees', requireAuth, async (req, res) => {
|
|
505
521
|
const { worktreePath, repoPath } = req.body;
|
|
@@ -574,11 +590,12 @@ async function main() {
|
|
|
574
590
|
});
|
|
575
591
|
// POST /sessions
|
|
576
592
|
app.post('/sessions', requireAuth, async (req, res) => {
|
|
577
|
-
const { repoPath, repoName, worktreePath, branchName, claudeArgs } = req.body;
|
|
593
|
+
const { repoPath, repoName, worktreePath, branchName, claudeArgs, agent } = req.body;
|
|
578
594
|
if (!repoPath) {
|
|
579
595
|
res.status(400).json({ error: 'repoPath is required' });
|
|
580
596
|
return;
|
|
581
597
|
}
|
|
598
|
+
const resolvedAgent = agent || config.defaultAgent || 'claude';
|
|
582
599
|
const name = repoName || repoPath.split('/').filter(Boolean).pop() || 'session';
|
|
583
600
|
const baseArgs = [...(config.claudeArgs || []), ...(claudeArgs || [])];
|
|
584
601
|
// Compute root by matching repoPath against configured rootDirs
|
|
@@ -591,7 +608,7 @@ async function main() {
|
|
|
591
608
|
let resolvedBranch = '';
|
|
592
609
|
if (worktreePath) {
|
|
593
610
|
// Resume existing worktree
|
|
594
|
-
args = [
|
|
611
|
+
args = [...AGENT_CONTINUE_ARGS[resolvedAgent], ...baseArgs];
|
|
595
612
|
cwd = worktreePath;
|
|
596
613
|
sessionRepoPath = worktreePath;
|
|
597
614
|
worktreeName = worktreePath.split('/').pop() || '';
|
|
@@ -648,12 +665,12 @@ async function main() {
|
|
|
648
665
|
}
|
|
649
666
|
const repoSession = sessions.create({
|
|
650
667
|
type: 'repo',
|
|
668
|
+
agent: resolvedAgent,
|
|
651
669
|
repoName: name,
|
|
652
670
|
repoPath,
|
|
653
671
|
cwd: repoPath,
|
|
654
672
|
root,
|
|
655
673
|
displayName: name,
|
|
656
|
-
command: config.claudeCommand,
|
|
657
674
|
args: baseArgs,
|
|
658
675
|
});
|
|
659
676
|
res.status(201).json(repoSession);
|
|
@@ -664,10 +681,11 @@ async function main() {
|
|
|
664
681
|
cwd = existingWt.path;
|
|
665
682
|
sessionRepoPath = existingWt.path;
|
|
666
683
|
worktreeName = existingWt.path.split('/').pop() || '';
|
|
667
|
-
args = [
|
|
684
|
+
args = [...AGENT_CONTINUE_ARGS[resolvedAgent], ...baseArgs];
|
|
668
685
|
const displayNameVal = branchName || worktreeName;
|
|
669
686
|
const session = sessions.create({
|
|
670
687
|
type: 'worktree',
|
|
688
|
+
agent: resolvedAgent,
|
|
671
689
|
repoName: name,
|
|
672
690
|
repoPath: sessionRepoPath,
|
|
673
691
|
cwd,
|
|
@@ -675,7 +693,6 @@ async function main() {
|
|
|
675
693
|
worktreeName,
|
|
676
694
|
branchName: branchName || worktreeName,
|
|
677
695
|
displayName: displayNameVal,
|
|
678
|
-
command: config.claudeCommand,
|
|
679
696
|
args,
|
|
680
697
|
configPath: CONFIG_PATH,
|
|
681
698
|
});
|
|
@@ -710,6 +727,7 @@ async function main() {
|
|
|
710
727
|
const displayName = branchName || worktreeName;
|
|
711
728
|
const session = sessions.create({
|
|
712
729
|
type: 'worktree',
|
|
730
|
+
agent: resolvedAgent,
|
|
713
731
|
repoName: name,
|
|
714
732
|
repoPath: sessionRepoPath,
|
|
715
733
|
cwd,
|
|
@@ -717,7 +735,6 @@ async function main() {
|
|
|
717
735
|
worktreeName,
|
|
718
736
|
branchName: branchName || worktreeName,
|
|
719
737
|
displayName,
|
|
720
|
-
command: config.claudeCommand,
|
|
721
738
|
args,
|
|
722
739
|
configPath: CONFIG_PATH,
|
|
723
740
|
});
|
|
@@ -733,11 +750,12 @@ async function main() {
|
|
|
733
750
|
});
|
|
734
751
|
// POST /sessions/repo — start a session in the repo root (no worktree)
|
|
735
752
|
app.post('/sessions/repo', requireAuth, (req, res) => {
|
|
736
|
-
const { repoPath, repoName, continue: continueSession, claudeArgs } = req.body;
|
|
753
|
+
const { repoPath, repoName, continue: continueSession, claudeArgs, agent } = req.body;
|
|
737
754
|
if (!repoPath) {
|
|
738
755
|
res.status(400).json({ error: 'repoPath is required' });
|
|
739
756
|
return;
|
|
740
757
|
}
|
|
758
|
+
const resolvedAgent = agent || config.defaultAgent || 'claude';
|
|
741
759
|
// One repo session at a time
|
|
742
760
|
const existing = sessions.findRepoSession(repoPath);
|
|
743
761
|
if (existing) {
|
|
@@ -746,17 +764,17 @@ async function main() {
|
|
|
746
764
|
}
|
|
747
765
|
const name = repoName || repoPath.split('/').filter(Boolean).pop() || 'session';
|
|
748
766
|
const baseArgs = [...(config.claudeArgs || []), ...(claudeArgs || [])];
|
|
749
|
-
const args = continueSession ? [
|
|
767
|
+
const args = continueSession ? [...AGENT_CONTINUE_ARGS[resolvedAgent], ...baseArgs] : [...baseArgs];
|
|
750
768
|
const roots = config.rootDirs || [];
|
|
751
769
|
const root = roots.find(function (r) { return repoPath.startsWith(r); }) || '';
|
|
752
770
|
const session = sessions.create({
|
|
753
771
|
type: 'repo',
|
|
772
|
+
agent: resolvedAgent,
|
|
754
773
|
repoName: name,
|
|
755
774
|
repoPath,
|
|
756
775
|
cwd: repoPath,
|
|
757
776
|
root,
|
|
758
777
|
displayName: name,
|
|
759
|
-
command: config.claudeCommand,
|
|
760
778
|
args,
|
|
761
779
|
});
|
|
762
780
|
res.status(201).json(session);
|
package/dist/server/sessions.js
CHANGED
|
@@ -4,6 +4,18 @@ import fs from 'node:fs';
|
|
|
4
4
|
import os from 'node:os';
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
import { readMeta, writeMeta } from './config.js';
|
|
7
|
+
const AGENT_COMMANDS = {
|
|
8
|
+
claude: 'claude',
|
|
9
|
+
codex: 'codex',
|
|
10
|
+
};
|
|
11
|
+
const AGENT_YOLO_ARGS = {
|
|
12
|
+
claude: ['--dangerously-skip-permissions'],
|
|
13
|
+
codex: ['--full-auto'],
|
|
14
|
+
};
|
|
15
|
+
const AGENT_CONTINUE_ARGS = {
|
|
16
|
+
claude: ['--continue'],
|
|
17
|
+
codex: ['resume', '--last'],
|
|
18
|
+
};
|
|
7
19
|
// In-memory registry: id -> Session
|
|
8
20
|
const sessions = new Map();
|
|
9
21
|
const IDLE_TIMEOUT_MS = 5000;
|
|
@@ -11,13 +23,14 @@ let idleChangeCallback = null;
|
|
|
11
23
|
function onIdleChange(cb) {
|
|
12
24
|
idleChangeCallback = cb;
|
|
13
25
|
}
|
|
14
|
-
function create({ type, repoName, repoPath, cwd, root, worktreeName, branchName, displayName, command, args = [], cols = 80, rows = 24, configPath }) {
|
|
26
|
+
function create({ type, agent = 'claude', repoName, repoPath, cwd, root, worktreeName, branchName, displayName, command, args = [], cols = 80, rows = 24, configPath }) {
|
|
15
27
|
const id = crypto.randomBytes(8).toString('hex');
|
|
16
28
|
const createdAt = new Date().toISOString();
|
|
29
|
+
const resolvedCommand = command || AGENT_COMMANDS[agent];
|
|
17
30
|
// Strip CLAUDECODE env var to allow spawning claude inside a claude-managed server
|
|
18
31
|
const env = Object.assign({}, process.env);
|
|
19
32
|
delete env.CLAUDECODE;
|
|
20
|
-
const ptyProcess = pty.spawn(
|
|
33
|
+
const ptyProcess = pty.spawn(resolvedCommand, args, {
|
|
21
34
|
name: 'xterm-256color',
|
|
22
35
|
cols,
|
|
23
36
|
rows,
|
|
@@ -31,6 +44,7 @@ function create({ type, repoName, repoPath, cwd, root, worktreeName, branchName,
|
|
|
31
44
|
const session = {
|
|
32
45
|
id,
|
|
33
46
|
type: type || 'worktree',
|
|
47
|
+
agent,
|
|
34
48
|
root: root || '',
|
|
35
49
|
repoName: repoName || '',
|
|
36
50
|
repoPath,
|
|
@@ -70,6 +84,7 @@ function create({ type, repoName, repoPath, cwd, root, worktreeName, branchName,
|
|
|
70
84
|
}
|
|
71
85
|
}, IDLE_TIMEOUT_MS);
|
|
72
86
|
}
|
|
87
|
+
const continueArgs = AGENT_CONTINUE_ARGS[agent];
|
|
73
88
|
function attachHandlers(proc, canRetry) {
|
|
74
89
|
const spawnTime = Date.now();
|
|
75
90
|
proc.onData((data) => {
|
|
@@ -89,12 +104,12 @@ function create({ type, repoName, repoPath, cwd, root, worktreeName, branchName,
|
|
|
89
104
|
}
|
|
90
105
|
});
|
|
91
106
|
proc.onExit(({ exitCode }) => {
|
|
92
|
-
// If
|
|
107
|
+
// If continue args failed quickly, retry without them
|
|
93
108
|
if (canRetry && (Date.now() - spawnTime) < 3000 && exitCode !== 0) {
|
|
94
|
-
const retryArgs = args.filter(a => a
|
|
109
|
+
const retryArgs = args.filter(a => !continueArgs.includes(a));
|
|
95
110
|
scrollback.length = 0;
|
|
96
111
|
scrollbackBytes = 0;
|
|
97
|
-
const retryPty = pty.spawn(
|
|
112
|
+
const retryPty = pty.spawn(resolvedCommand, retryArgs, {
|
|
98
113
|
name: 'xterm-256color',
|
|
99
114
|
cols,
|
|
100
115
|
rows,
|
|
@@ -117,17 +132,18 @@ function create({ type, repoName, repoPath, cwd, root, worktreeName, branchName,
|
|
|
117
132
|
fs.rm(tmpDir, { recursive: true, force: true }, () => { });
|
|
118
133
|
});
|
|
119
134
|
}
|
|
120
|
-
attachHandlers(ptyProcess, args.includes(
|
|
121
|
-
return { id, type: session.type, root: session.root, repoName: session.repoName, repoPath, worktreeName: session.worktreeName, branchName: session.branchName, displayName: session.displayName, pid: ptyProcess.pid, createdAt, lastActivity: createdAt, idle: false };
|
|
135
|
+
attachHandlers(ptyProcess, continueArgs.some(a => args.includes(a)));
|
|
136
|
+
return { id, type: session.type, agent: session.agent, root: session.root, repoName: session.repoName, repoPath, worktreeName: session.worktreeName, branchName: session.branchName, displayName: session.displayName, pid: ptyProcess.pid, createdAt, lastActivity: createdAt, idle: false };
|
|
122
137
|
}
|
|
123
138
|
function get(id) {
|
|
124
139
|
return sessions.get(id);
|
|
125
140
|
}
|
|
126
141
|
function list() {
|
|
127
142
|
return Array.from(sessions.values())
|
|
128
|
-
.map(({ id, type, root, repoName, repoPath, worktreeName, branchName, displayName, createdAt, lastActivity, idle }) => ({
|
|
143
|
+
.map(({ id, type, agent, root, repoName, repoPath, worktreeName, branchName, displayName, createdAt, lastActivity, idle }) => ({
|
|
129
144
|
id,
|
|
130
145
|
type,
|
|
146
|
+
agent,
|
|
131
147
|
root,
|
|
132
148
|
repoName,
|
|
133
149
|
repoPath,
|
|
@@ -172,4 +188,4 @@ function write(id, data) {
|
|
|
172
188
|
function findRepoSession(repoPath) {
|
|
173
189
|
return list().find((s) => s.type === 'repo' && s.repoPath === repoPath);
|
|
174
190
|
}
|
|
175
|
-
export { create, get, list, kill, resize, updateDisplayName, write, onIdleChange, findRepoSession };
|
|
191
|
+
export { create, get, list, kill, resize, updateDisplayName, write, onIdleChange, findRepoSession, AGENT_COMMANDS, AGENT_YOLO_ARGS, AGENT_CONTINUE_ARGS };
|
package/dist/test/config.test.js
CHANGED
|
@@ -40,6 +40,7 @@ test('loadConfig merges with defaults for missing fields', () => {
|
|
|
40
40
|
assert.deepEqual(config.repos, DEFAULTS.repos);
|
|
41
41
|
assert.equal(config.claudeCommand, DEFAULTS.claudeCommand);
|
|
42
42
|
assert.deepEqual(config.claudeArgs, DEFAULTS.claudeArgs);
|
|
43
|
+
assert.equal(config.defaultAgent, DEFAULTS.defaultAgent);
|
|
43
44
|
});
|
|
44
45
|
test('loadConfig throws if config file not found', () => {
|
|
45
46
|
const configPath = path.join(tmpDir, 'nonexistent.json');
|
|
@@ -59,6 +60,7 @@ test('DEFAULTS has expected keys and values', () => {
|
|
|
59
60
|
assert.deepEqual(DEFAULTS.repos, []);
|
|
60
61
|
assert.equal(DEFAULTS.claudeCommand, 'claude');
|
|
61
62
|
assert.deepEqual(DEFAULTS.claudeArgs, []);
|
|
63
|
+
assert.equal(DEFAULTS.defaultAgent, 'claude');
|
|
62
64
|
});
|
|
63
65
|
test('ensureMetaDir creates worktree-meta directory', () => {
|
|
64
66
|
const configPath = path.join(tmpDir, 'config.json');
|
|
@@ -264,4 +264,39 @@ describe('sessions', () => {
|
|
|
264
264
|
createdIds.push(result.id);
|
|
265
265
|
assert.strictEqual(result.branchName, '');
|
|
266
266
|
});
|
|
267
|
+
it('agent defaults to claude when not specified', () => {
|
|
268
|
+
const result = sessions.create({
|
|
269
|
+
repoName: 'test-repo',
|
|
270
|
+
repoPath: '/tmp',
|
|
271
|
+
command: '/bin/echo',
|
|
272
|
+
args: ['hello'],
|
|
273
|
+
});
|
|
274
|
+
createdIds.push(result.id);
|
|
275
|
+
assert.strictEqual(result.agent, 'claude');
|
|
276
|
+
});
|
|
277
|
+
it('agent is set when specified', () => {
|
|
278
|
+
const result = sessions.create({
|
|
279
|
+
repoName: 'test-repo',
|
|
280
|
+
repoPath: '/tmp',
|
|
281
|
+
agent: 'codex',
|
|
282
|
+
command: '/bin/echo',
|
|
283
|
+
args: ['hello'],
|
|
284
|
+
});
|
|
285
|
+
createdIds.push(result.id);
|
|
286
|
+
assert.strictEqual(result.agent, 'codex');
|
|
287
|
+
});
|
|
288
|
+
it('list includes agent field', () => {
|
|
289
|
+
const result = sessions.create({
|
|
290
|
+
repoName: 'test-repo',
|
|
291
|
+
repoPath: '/tmp',
|
|
292
|
+
agent: 'codex',
|
|
293
|
+
command: '/bin/echo',
|
|
294
|
+
args: ['hello'],
|
|
295
|
+
});
|
|
296
|
+
createdIds.push(result.id);
|
|
297
|
+
const list = sessions.list();
|
|
298
|
+
const session = list.find(s => s.id === result.id);
|
|
299
|
+
assert.ok(session);
|
|
300
|
+
assert.strictEqual(session.agent, 'codex');
|
|
301
|
+
});
|
|
267
302
|
});
|