coxpit 5.0.2 → 5.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/board.ts +40 -21
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "coxpit",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.3",
|
|
4
4
|
"description": "Self-hosted cockpit for running a fleet of AI coding agents across your own machines — parallel worktree runs, live board, compare & merge, web terminal, design capture.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/src/board.ts
CHANGED
|
@@ -185,9 +185,24 @@ export const BOARD_HTML = /* html */ `<!doctype html>
|
|
|
185
185
|
.sheet-h .sp{flex:1}.sheet-h .x{color:var(--muted);cursor:pointer;background:none;border:none;padding:2px}
|
|
186
186
|
.sheet #taskForm{display:flex;flex-direction:column;gap:13px;min-height:0}
|
|
187
187
|
.sheet-body{display:flex;flex-direction:column;gap:8px;overflow-y:auto;min-height:0;max-height:60vh;padding:1px}
|
|
188
|
-
.sheet-f{display:flex;align-items:center;gap:
|
|
189
|
-
.sheet-f #modeSeg{flex:
|
|
190
|
-
.sheet-f #
|
|
188
|
+
.sheet-f{display:flex;flex-wrap:wrap;align-items:center;gap:10px;padding-top:12px;border-top:1px solid var(--line)}
|
|
189
|
+
.sheet-f #modeSeg{flex:0 0 auto}
|
|
190
|
+
.sheet-f #taskCountStep{flex:0 0 auto;margin-left:auto}
|
|
191
|
+
.sheet-f #runFleetBtn{flex:1 1 100%;justify-content:center}
|
|
192
|
+
/* agent-mode switch — compact toggle (dry ⇄ real), never a native checkbox/white box */
|
|
193
|
+
.realtog{display:inline-flex;align-items:center;gap:8px;background:#0e1118;border:1px solid var(--line);
|
|
194
|
+
border-radius:999px;padding:5px 13px 5px 6px;cursor:pointer;font-family:var(--sans);font-size:12px;
|
|
195
|
+
font-weight:600;color:var(--muted);white-space:nowrap;transition:color .15s,border-color .15s}
|
|
196
|
+
.realtog:hover{border-color:var(--brand)}
|
|
197
|
+
.realtog .realtog-knob{width:30px;height:17px;border-radius:999px;background:var(--surface2);
|
|
198
|
+
position:relative;flex:none;transition:background .18s}
|
|
199
|
+
.realtog .realtog-knob::after{content:"";position:absolute;top:2px;left:2px;width:13px;height:13px;
|
|
200
|
+
border-radius:50%;background:var(--faint);transition:transform .18s,background .18s}
|
|
201
|
+
.realtog .realtog-hint{font-family:var(--mono);font-size:10px;font-weight:400;color:var(--faint)}
|
|
202
|
+
.realtog[aria-checked="true"]{color:var(--brand);border-color:rgba(78,201,176,.4)}
|
|
203
|
+
.realtog[aria-checked="true"] .realtog-knob{background:var(--brand-dim)}
|
|
204
|
+
.realtog[aria-checked="true"] .realtog-knob::after{transform:translateX(13px);background:var(--brand)}
|
|
205
|
+
.realtog:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
|
|
191
206
|
/* progressive Options reveal (rarely-used Task fields) */
|
|
192
207
|
.opt{border:1px solid var(--line);border-radius:var(--r-ctl);background:#0e1118;overflow:hidden}
|
|
193
208
|
.opt-h{width:100%;display:flex;align-items:center;gap:8px;background:transparent;border:none;cursor:pointer;
|
|
@@ -253,7 +268,7 @@ export const BOARD_HTML = /* html */ `<!doctype html>
|
|
|
253
268
|
.seg{display:flex;gap:3px;padding:3px;border:1px solid var(--line);border-radius:var(--r-ctl);background:#0e1118}
|
|
254
269
|
/* slim single-row option — matches the type/provider seg height; the risky hint rides inline, subtle */
|
|
255
270
|
.seg-opt{flex:1;display:inline-flex;flex-direction:row;align-items:center;justify-content:center;gap:5px;
|
|
256
|
-
padding:6px 8px;border:none;min-width:0;
|
|
271
|
+
padding:6px 8px;border:none;min-width:0;white-space:nowrap;line-height:1.2;
|
|
257
272
|
background:transparent;color:var(--muted);font-size:12px;font-weight:600;cursor:pointer;
|
|
258
273
|
border-radius:calc(var(--r-ctl) - 3px);transition:background .15s,color .15s}
|
|
259
274
|
.seg-opt:hover{color:var(--ink)}
|
|
@@ -884,10 +899,11 @@ ${ICON_SPRITE}
|
|
|
884
899
|
</div>
|
|
885
900
|
</div>
|
|
886
901
|
<div class="sheet-f" id="sheetFooter">
|
|
887
|
-
<
|
|
888
|
-
<
|
|
889
|
-
<
|
|
890
|
-
|
|
902
|
+
<button type="button" id="modeSeg" class="realtog" role="switch" aria-checked="false" title="Dry run rehearses the full pipeline with zero credits. Turn on to run the real agent CLI.">
|
|
903
|
+
<span class="realtog-knob"></span>
|
|
904
|
+
<span class="realtog-lbl" id="modeRealLbl">Dry run</span>
|
|
905
|
+
<span class="realtog-hint" id="modeRealHint">rehearsal</span>
|
|
906
|
+
</button>
|
|
891
907
|
<input type="checkbox" id="taskReal" hidden />
|
|
892
908
|
<div class="stepper" id="taskCountStep" title="agents — 1 for a job, N to explore variants">
|
|
893
909
|
<button type="button" class="stp" id="cntDown" aria-label="fewer agents"><svg class="ic"><use href="#i-minus"/></svg></button>
|
|
@@ -1764,19 +1780,19 @@ function renderRail(){
|
|
|
1764
1780
|
const cnt = railCounts();
|
|
1765
1781
|
let html = '';
|
|
1766
1782
|
if (repos.length){
|
|
1767
|
-
html += '<
|
|
1768
|
-
+ ic('layers')+'<span class="nm">All repositories</span></
|
|
1783
|
+
html += '<div class="repo'+(selectedRepo==null?' on':'')+'" role="button" tabindex="0" data-repo="all">'
|
|
1784
|
+
+ ic('layers')+'<span class="nm">All repositories</span></div>';
|
|
1769
1785
|
for (const r of repos){
|
|
1770
1786
|
const c = cnt.get(r.id) || { active:0, attn:false };
|
|
1771
1787
|
const on = selectedRepo===r.id;
|
|
1772
|
-
html += '<
|
|
1788
|
+
html += '<div class="repo'+(on?' on':'')+'" role="button" tabindex="0" data-repo="'+r.id+'" title="'+escA(r.path||r.name)+'">'
|
|
1773
1789
|
+ ic('folder')+'<span class="nm">'+esc(r.name)+'</span>'
|
|
1774
1790
|
+ (c.attn ? '<span class="attn" title="a run needs a hand"></span>' : '')
|
|
1775
1791
|
+ (c.active>0 ? '<span class="cnt">'+c.active+'</span>' : '')
|
|
1776
1792
|
+ '<span class="rowmenu">'
|
|
1777
1793
|
+ '<button type="button" class="rmbtn" data-rbranch="'+r.id+'" title="base branch">'+ic('branch')+'</button>'
|
|
1778
1794
|
+ '<button type="button" class="rmbtn" data-rremove="'+r.id+'" title="remove">'+ic('x')+'</button>'
|
|
1779
|
-
+ '</span></
|
|
1795
|
+
+ '</span></div>';
|
|
1780
1796
|
}
|
|
1781
1797
|
} else {
|
|
1782
1798
|
// empty state — 첫 repo 추가 CTA
|
|
@@ -1804,6 +1820,12 @@ $('repoList').addEventListener('click', (e)=>{
|
|
|
1804
1820
|
const row = e.target.closest('.repo[data-repo]'); if(!row) return;
|
|
1805
1821
|
setScope(row.dataset.repo==='all' ? null : Number(row.dataset.repo));
|
|
1806
1822
|
});
|
|
1823
|
+
$('repoList').addEventListener('keydown', (e)=>{
|
|
1824
|
+
if (e.key!=='Enter' && e.key!==' ') return;
|
|
1825
|
+
const row = e.target.closest('.repo[data-repo]'); if(!row) return;
|
|
1826
|
+
e.preventDefault();
|
|
1827
|
+
setScope(row.dataset.repo==='all' ? null : Number(row.dataset.repo));
|
|
1828
|
+
});
|
|
1807
1829
|
$('captures').addEventListener('click', async (e)=>{
|
|
1808
1830
|
const b = e.target.closest('button[data-delcap]'); if(!b) return;
|
|
1809
1831
|
await fetch('/api/design/'+b.dataset.delcap,{method:'DELETE'});
|
|
@@ -3034,7 +3056,7 @@ function setV(tab){
|
|
|
3034
3056
|
$('panelBench').hidden = tab!=='bench';
|
|
3035
3057
|
$('panelBench').style.display = tab==='bench' ? 'flex' : 'none';
|
|
3036
3058
|
// footer adapts: Task=Dry/Real·count·Run fleet · Goal=Dry/Real·Plan & run · Workbench=Open workbench only
|
|
3037
|
-
$('modeSeg').style.display = tab==='bench' ? 'none' : 'flex'; // workbench 는 에이전트 없음
|
|
3059
|
+
$('modeSeg').style.display = tab==='bench' ? 'none' : 'inline-flex'; // workbench 는 에이전트 없음
|
|
3038
3060
|
$('taskCountStep').style.display = tab==='task' ? 'flex' : 'none'; // count 는 Task 만(플래너·워크벤치는 1)
|
|
3039
3061
|
$('runFleetBtn').innerHTML = ic(L_ICON[tab]) + ' ' + L_LABEL[tab];
|
|
3040
3062
|
}
|
|
@@ -3178,18 +3200,15 @@ $('cntDown').addEventListener('click', ()=>stepCount(-1));
|
|
|
3178
3200
|
$('cntUp').addEventListener('click', ()=>stepCount(1));
|
|
3179
3201
|
$('taskCount').addEventListener('change', ()=>stepCount(0)); // clamp manual typing
|
|
3180
3202
|
|
|
3181
|
-
/* ── agent mode
|
|
3182
|
-
const segOpts = Array.from(document.querySelectorAll('#modeSeg .seg-opt'));
|
|
3203
|
+
/* ── agent mode switch (compact toggle mirroring hidden #taskReal) ── */
|
|
3183
3204
|
function setMode(real, persist){
|
|
3184
3205
|
$('taskReal').checked = real;
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
b.setAttribute('aria-pressed', on ? 'true' : 'false');
|
|
3189
|
-
}
|
|
3206
|
+
$('modeSeg').setAttribute('aria-checked', real ? 'true' : 'false');
|
|
3207
|
+
$('modeRealLbl').textContent = real ? 'Real agent' : 'Dry run';
|
|
3208
|
+
$('modeRealHint').textContent = real ? 'spends credits' : 'rehearsal';
|
|
3190
3209
|
if (persist) try { localStorage.setItem('coxpit.real', real ? '1' : '0'); } catch {}
|
|
3191
3210
|
}
|
|
3192
|
-
|
|
3211
|
+
$('modeSeg').addEventListener('click', ()=>setMode(!$('taskReal').checked, true));
|
|
3193
3212
|
let savedMode = null;
|
|
3194
3213
|
try { savedMode = localStorage.getItem('coxpit.real'); } catch {}
|
|
3195
3214
|
setMode(savedMode === '1', false);
|