claude-code-kanban 7.7.0 → 7.9.0

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.
@@ -1,88 +0,0 @@
1
- // Transient session groups: `dispatch start --group` puts the started session in a group,
2
- // and only an explicit `--group` does. A group lives while any member's claude
3
- // runs, and for a grace period after; once none runs, only pinned members stay in it.
4
- // The map is on disk so a pinned group outlives a server restart.
5
-
6
- const GROUP_RE = /^[a-z0-9]+(-[a-z0-9]+)*$/;
7
- const MAX_GROUP = 64;
8
- // Covers a claude that has started but not yet registered, a resume, and registry lag.
9
- const GRACE_MS = 60 * 1000;
10
-
11
- function isGroupName(s) {
12
- return typeof s === 'string' && s.length <= MAX_GROUP && GROUP_RE.test(s);
13
- }
14
-
15
- function suggestGroupName(s) {
16
- return String(s ?? '')
17
- .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
18
- .toLowerCase()
19
- .replace(/[^a-z0-9]+/g, '-')
20
- .replace(/^-+|-+$/g, '')
21
- .slice(0, MAX_GROUP)
22
- .replace(/-+$/, '');
23
- }
24
-
25
- /**
26
- * @param {object} o
27
- * @param {() => object|null} o.load returns `{sessions: {[id]: group}}` or null
28
- * @param {(data: object) => void} o.save
29
- * @param {(id: string) => boolean} o.isAlive
30
- * @param {() => Set<string>} o.pinnedIds
31
- */
32
- function createGroupStore({ load, save, isAlive, pinnedIds, now = Date.now }) {
33
- const members = new Map();
34
- const liveAt = new Map();
35
- const saved = load();
36
- if (saved?.sessions && typeof saved.sessions === 'object') {
37
- for (const [id, g] of Object.entries(saved.sessions)) if (isGroupName(g)) members.set(id, g);
38
- }
39
- for (const g of members.values()) liveAt.set(g, now());
40
-
41
- const persist = () => save({ version: 1, sessions: Object.fromEntries(members) });
42
-
43
- function join(group, ids) {
44
- let changed = false;
45
- for (const id of ids) {
46
- if (!id || members.get(id) === group) continue;
47
- members.set(id, group);
48
- changed = true;
49
- }
50
- liveAt.set(group, now());
51
- if (changed) persist();
52
- }
53
-
54
- function refresh() {
55
- const t = now();
56
- const byGroup = new Map();
57
- for (const [id, g] of members) {
58
- if (!byGroup.has(g)) byGroup.set(g, []);
59
- byGroup.get(g).push(id);
60
- }
61
- let pinned = null;
62
- let changed = false;
63
- for (const [g, ids] of byGroup) {
64
- if (ids.some(isAlive)) {
65
- liveAt.set(g, t);
66
- continue;
67
- }
68
- if (t - (liveAt.get(g) ?? 0) <= GRACE_MS) continue;
69
- pinned ??= pinnedIds();
70
- for (const id of ids) {
71
- if (pinned.has(id)) continue;
72
- members.delete(id);
73
- changed = true;
74
- }
75
- if (!ids.some((id) => pinned.has(id))) liveAt.delete(g);
76
- }
77
- if (changed) persist();
78
- }
79
-
80
- function snapshot() {
81
- refresh();
82
- return members;
83
- }
84
-
85
- return { join, snapshot };
86
- }
87
-
88
- module.exports = { createGroupStore, isGroupName, suggestGroupName, GRACE_MS };