shadok-ai 0.15.34 → 0.15.35
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 +9 -6
- package/package.json +1 -1
- package/public/index.html +39 -6
package/README.md
CHANGED
|
@@ -76,9 +76,11 @@ Enter to skip; you can add it later from the web UI).
|
|
|
76
76
|
- **Channels** — one `claude` process each, running in parallel. Renaming,
|
|
77
77
|
grouping, and closing all sync live between the browser and Telegram: it's
|
|
78
78
|
one list, server-owned, not two copies.
|
|
79
|
-
- **Groups column** — on a desktop the groups get a
|
|
80
|
-
of the agents
|
|
81
|
-
|
|
79
|
+
- **Groups column** — once you create a group, on a desktop the groups get a
|
|
80
|
+
column of their own, left of the agents (with no group there is no column, just
|
|
81
|
+
the single agents list): pick a group and the agents column shows only its
|
|
82
|
+
agents (*Ungrouped* holds the rest, the home agent included unless you file
|
|
83
|
+
it). Each
|
|
82
84
|
group has an icon — drawn at random, double-click it to pick another: choose
|
|
83
85
|
from the grid, type any emoji, or **type a word** (`rocket`, `bug`, `money`…)
|
|
84
86
|
to search for a matching one — and a **+** that creates the new agent straight
|
|
@@ -86,9 +88,10 @@ Enter to skip; you can add it later from the web UI).
|
|
|
86
88
|
A single click on a group (its icon or its row) selects it; this matters once
|
|
87
89
|
**«** folds the column to its icons, where the icon is the whole row.
|
|
88
90
|
Dragging an agent onto a group still files it there, and dragging groups
|
|
89
|
-
reorders them. Double-click a name to rename it. A
|
|
90
|
-
|
|
91
|
-
|
|
91
|
+
reorders them. Double-click a name to rename it. A group you are not looking at
|
|
92
|
+
carries the same signal its agents do — the row lights up (and breathes) when
|
|
93
|
+
one is working, waiting for you, or has an unread answer, the way a channel
|
|
94
|
+
does. On a phone nothing changes: the agents sheet still lists every group.
|
|
92
95
|
- **Worktree isolation** — spawned agents get their own git worktree and branch
|
|
93
96
|
by default, so parallel agents never collide. Work is never auto-discarded:
|
|
94
97
|
an empty worktree is reclaimed on close, anything with changes or commits
|
package/package.json
CHANGED
package/public/index.html
CHANGED
|
@@ -590,15 +590,19 @@
|
|
|
590
590
|
animation: breathe 1.8s ease-in-out infinite;
|
|
591
591
|
}
|
|
592
592
|
@media (prefers-reduced-motion: reduce) { .tab.working, .tab.has-bg { animation: none; } }
|
|
593
|
-
#newTab, #newGroup {
|
|
593
|
+
#newTab, #newGroup, #newGroupBare {
|
|
594
594
|
margin-top: 8px;
|
|
595
595
|
border: 1px dashed var(--line);
|
|
596
596
|
font-size: 12px;
|
|
597
597
|
color: var(--text-dim);
|
|
598
598
|
padding: 8px;
|
|
599
599
|
}
|
|
600
|
-
#newTab:hover, #newGroup:hover { color: var(--amber); border-color: var(--amber); }
|
|
600
|
+
#newTab:hover, #newGroup:hover, #newGroupBare:hover { color: var(--amber); border-color: var(--amber); }
|
|
601
601
|
#newGroup { margin-top: 4px; }
|
|
602
|
+
/* The fallback "new group" entry: only on desktop, only while the rail (which
|
|
603
|
+
has its own) is hidden for want of a group. */
|
|
604
|
+
#newGroupBare { display: none; margin-top: 4px; }
|
|
605
|
+
@media (min-width: 641px) { body:not(.has-groups) #newGroupBare { display: block; } }
|
|
602
606
|
/* The column's only coloured element: tabs are borderless rows and the + are
|
|
603
607
|
ghost buttons, so a solid card reads as an action rather than as a session.
|
|
604
608
|
Pinned to the bottom (margin-top:auto + sticky) so it stays reachable while
|
|
@@ -712,7 +716,10 @@
|
|
|
712
716
|
#groupRail { display: none; }
|
|
713
717
|
.icon-picker[hidden] { display: none; }
|
|
714
718
|
@media (min-width: 641px) {
|
|
715
|
-
|
|
719
|
+
/* The column only earns its space once a group exists: with none, the
|
|
720
|
+
cockpit is the single agents list it always was (body.has-groups is set
|
|
721
|
+
from groups.length in applyView). */
|
|
722
|
+
body.has-groups #groupRail {
|
|
716
723
|
width: 190px; flex: none;
|
|
717
724
|
display: flex; flex-direction: column; gap: 2px;
|
|
718
725
|
background: var(--bg-inset);
|
|
@@ -752,6 +759,15 @@
|
|
|
752
759
|
.rail-item.unread .rail-dot { display: block; background: var(--phosphor); }
|
|
753
760
|
.rail-item.working .rail-dot { display: block; background: var(--text-dim); animation: breathe 1.8s ease-in-out infinite; }
|
|
754
761
|
@media (prefers-reduced-motion: reduce) { .rail-dot { animation: none !important; } }
|
|
762
|
+
/* A group carries the SAME effect its channels do — a working or finished
|
|
763
|
+
agent makes the whole group row read like that agent, not just a dot.
|
|
764
|
+
Mirrors .tab.working / .needs-answer / .unread. Shown for a group you are
|
|
765
|
+
NOT viewing (the active one shows its state on each agent in the column).
|
|
766
|
+
Placed after :hover so the state colour wins over the hover background. */
|
|
767
|
+
.rail-item.working { background: var(--amber-soft); animation: breathe 1.6s ease-in-out infinite; }
|
|
768
|
+
.rail-item.needs-answer { background: color-mix(in srgb, var(--amber) 28%, transparent); color: var(--text); }
|
|
769
|
+
.rail-item.unread { background: rgba(127, 201, 127, 0.14); border-left-color: var(--ok); color: var(--text); }
|
|
770
|
+
@media (prefers-reduced-motion: reduce) { .rail-item.working { animation: none !important; } }
|
|
755
771
|
.rail-add, .rail-del {
|
|
756
772
|
flex: none; display: none; border: none; background: none;
|
|
757
773
|
padding: 0 3px; font-size: 13px; line-height: 1; color: var(--text-dim);
|
|
@@ -780,7 +796,11 @@
|
|
|
780
796
|
body.rail-mini .rail-dot { position: absolute; top: 4px; right: 4px; }
|
|
781
797
|
|
|
782
798
|
/* The agents column, narrowed to the selected group. */
|
|
783
|
-
|
|
799
|
+
/* With a column the list header is the selected group's name; with no
|
|
800
|
+
column it is just "Agents" again (the "Ungrouped" view label would read
|
|
801
|
+
oddly when there is nothing to be ungrouped from). */
|
|
802
|
+
body.has-groups #tabbar .side-label .sl-all { display: none; }
|
|
803
|
+
body:not(.has-groups) #tabbar .side-label .sl-view { display: none; }
|
|
784
804
|
#tabbar .group-head { display: none; }
|
|
785
805
|
#tabbar .group { margin-top: 0; }
|
|
786
806
|
#tabbar .group-body { padding-left: 0; }
|
|
@@ -2568,6 +2588,11 @@
|
|
|
2568
2588
|
<div id="groups"></div>
|
|
2569
2589
|
<p id="viewEmpty" class="check-hint" hidden>No agent in this group yet — create one, or drag one onto the group.</p>
|
|
2570
2590
|
<button id="newTab" title="New agent">+ new agent</button>
|
|
2591
|
+
<!-- The rail carries "+ new group" at its foot, but the rail is gone until a
|
|
2592
|
+
group exists — so this is the way to create the FIRST one. Desktop-only
|
|
2593
|
+
and only while there are no groups (CSS); it hands off to the rail's
|
|
2594
|
+
button once the column appears. -->
|
|
2595
|
+
<button id="newGroupBare" type="button" title="New agent group">+ new group</button>
|
|
2571
2596
|
<div id="tweakSlot">
|
|
2572
2597
|
<button id="tweakCta" type="button"
|
|
2573
2598
|
title="Change shadok-ai itself — the agent works on a branch and opens a pull request">
|
|
@@ -4188,6 +4213,8 @@
|
|
|
4188
4213
|
|
|
4189
4214
|
function applyView() {
|
|
4190
4215
|
const v = currentView();
|
|
4216
|
+
// No group → no column (invariant: the rail earns its space, see the CSS).
|
|
4217
|
+
document.body.classList.toggle("has-groups", groups.length > 0);
|
|
4191
4218
|
tabbar.dataset.view = v;
|
|
4192
4219
|
for (const g of groups) g.el.classList.toggle("in-view", String(g.id) === v);
|
|
4193
4220
|
const g = groups.find((x) => String(x.id) === v);
|
|
@@ -9786,12 +9813,18 @@
|
|
|
9786
9813
|
markTweakTab(t);
|
|
9787
9814
|
launchTab(t, { cwd: data.cwd, worktree: true, profile: "Shadok-Tweak" });
|
|
9788
9815
|
});
|
|
9789
|
-
|
|
9816
|
+
function addGroup() {
|
|
9790
9817
|
const g = createGroup();
|
|
9791
9818
|
persistGroups();
|
|
9819
|
+
// applyView first, so has-groups is set and the column is shown SYNCHRONOUSLY
|
|
9820
|
+
// — otherwise railShown() below is still false on the first group (created
|
|
9821
|
+
// from the bare button, while the rail was hidden) and it would not select.
|
|
9822
|
+
applyView();
|
|
9792
9823
|
// A new group is where you are going next: select it (it starts empty).
|
|
9793
9824
|
if (railShown()) setView(g.id, { follow: false });
|
|
9794
|
-
}
|
|
9825
|
+
}
|
|
9826
|
+
newGroupBtn.addEventListener("click", addGroup);
|
|
9827
|
+
$("newGroupBare").addEventListener("click", addGroup);
|
|
9795
9828
|
|
|
9796
9829
|
// ── Quota gauges (5h / 7d) ──────────────────────────────
|
|
9797
9830
|
function fmtReset(sec) {
|