@korso/shepherd-ui 0.3.1 → 0.5.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.
- package/LICENSE +661 -0
- package/dist/ShepherdRoot.js +13 -12
- package/dist/client.d.ts +6 -0
- package/dist/client.js +14 -0
- package/dist/components/Dashboard.d.ts +7 -1
- package/dist/components/Dashboard.js +2 -2
- package/dist/config/ConfigPanel.d.ts +14 -0
- package/dist/config/ConfigPanel.js +16 -0
- package/dist/config/ConnectAgent.d.ts +1 -2
- package/dist/config/ConnectAgent.js +6 -12
- package/dist/config/GeneralSettings.d.ts +8 -0
- package/dist/config/GeneralSettings.js +27 -0
- package/dist/config/Invites.d.ts +7 -0
- package/dist/config/Invites.js +84 -0
- package/dist/config/Members.d.ts +1 -3
- package/dist/config/Members.js +4 -23
- package/dist/config/WorkspaceSwitcher.d.ts +14 -0
- package/dist/config/WorkspaceSwitcher.js +108 -0
- package/dist/config/index.d.ts +8 -2
- package/dist/config/index.js +6 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/lib/Dashboard-C48qY8R2.js +1412 -0
- package/dist/lib/index.d.ts +63 -22
- package/dist/lib/index.js +552 -302
- package/dist/lib/selfhost.js +1 -1
- package/dist/lib/styles.css +128 -18
- package/dist/preview.js +40 -4
- package/dist/selfhost/assets/index-CK7qrsNo.css +1 -0
- package/dist/selfhost/assets/index-adPvx18g.js +40 -0
- package/dist/selfhost/index.html +2 -2
- package/dist/test/mockClient.js +3 -0
- package/package.json +2 -2
- package/dist/config/Workspaces.d.ts +0 -15
- package/dist/config/Workspaces.js +0 -116
- package/dist/lib/Dashboard-Bgi50wCo.js +0 -1396
- package/dist/selfhost/assets/index-D0C3m6st.js +0 -40
- package/dist/selfhost/assets/index-rNR1Acph.css +0 -1
|
@@ -1,1396 +0,0 @@
|
|
|
1
|
-
var De = Object.defineProperty;
|
|
2
|
-
var Ie = (t, n, i) => n in t ? De(t, n, { enumerable: !0, configurable: !0, writable: !0, value: i }) : t[n] = i;
|
|
3
|
-
var de = (t, n, i) => Ie(t, typeof n != "symbol" ? n + "" : n, i);
|
|
4
|
-
import { jsx as o, jsxs as m, Fragment as H } from "react/jsx-runtime";
|
|
5
|
-
import { createContext as xe, useContext as Me, useState as w, useRef as P, useCallback as j, useEffect as ne, Fragment as Le, useLayoutEffect as Pe, useId as Ne } from "react";
|
|
6
|
-
import { z as e } from "zod";
|
|
7
|
-
const C = e.string(), K = e.number(), Oe = e.object({
|
|
8
|
-
agentName: e.string(),
|
|
9
|
-
human: e.string(),
|
|
10
|
-
branch: e.string(),
|
|
11
|
-
kind: e.enum(["committed", "uncommitted"]),
|
|
12
|
-
commitSha: e.string().nullable(),
|
|
13
|
-
message: e.string().nullable(),
|
|
14
|
-
paths: e.array(e.string()).min(1),
|
|
15
|
-
authorIsLive: e.boolean(),
|
|
16
|
-
authorLastActiveAt: C,
|
|
17
|
-
updatedAt: C
|
|
18
|
-
}), Ge = e.object({
|
|
19
|
-
kind: e.enum(["committed", "uncommitted"]),
|
|
20
|
-
// A git object id (lowercase hex, 4–64 chars) for `committed` entries, or null
|
|
21
|
-
// for `uncommitted`. This value is forwarded by the hub to OTHER clients, which
|
|
22
|
-
// feed it straight into local `git` argument vectors (isAncestor/hasCommit/
|
|
23
|
-
// changedLineRanges). Validating the shape at the wire boundary stops an
|
|
24
|
-
// attacker-controlled, flag-like value (e.g. "--output=...") from being parsed
|
|
25
|
-
// by git as an option on a teammate's machine (argument injection). gitContext
|
|
26
|
-
// re-validates defensively as well.
|
|
27
|
-
sha: e.string().regex(/^[0-9a-f]{4,64}$/).nullable(),
|
|
28
|
-
message: e.string().nullable(),
|
|
29
|
-
paths: e.array(e.string()).min(1).max(500)
|
|
30
|
-
}), se = e.object({
|
|
31
|
-
branch: e.string(),
|
|
32
|
-
baseBranch: e.string(),
|
|
33
|
-
head: e.string(),
|
|
34
|
-
truncated: e.boolean().default(!1),
|
|
35
|
-
// The only producer (gitContext.unlandedCommits) emits at most MAX_COMMITS
|
|
36
|
-
// (100) committed entries + 1 uncommitted, so this ceiling is generous. If
|
|
37
|
-
// MAX_COMMITS is ever raised above ~599, raise this in lockstep or the hub
|
|
38
|
-
// will start 400-rejecting otherwise-valid reports.
|
|
39
|
-
entries: e.array(Ge).max(600)
|
|
40
|
-
}), X = e.object({
|
|
41
|
-
workItemId: e.string().uuid(),
|
|
42
|
-
agentName: e.string(),
|
|
43
|
-
human: e.string().min(1),
|
|
44
|
-
intent: e.string().min(1).max(2048),
|
|
45
|
-
pathGlobs: e.array(e.string().min(1).max(512)).min(1).max(64),
|
|
46
|
-
// ISO timestamp string; see IsoTimestamp note above
|
|
47
|
-
expiresAt: C
|
|
48
|
-
}), z = e.object({
|
|
49
|
-
// bigint PK serialised as number; see DbId note above
|
|
50
|
-
id: K,
|
|
51
|
-
fromAgentName: e.string(),
|
|
52
|
-
fromHuman: e.string().min(1),
|
|
53
|
-
body: e.string().min(1).max(8192),
|
|
54
|
-
targetAgentName: e.string().nullable(),
|
|
55
|
-
// ISO timestamp string; see IsoTimestamp note above
|
|
56
|
-
createdAt: C
|
|
57
|
-
}), we = e.object({
|
|
58
|
-
conflicts: e.array(X),
|
|
59
|
-
activeClaims: e.array(X),
|
|
60
|
-
// The caller's OWN active claims. `activeClaims` deliberately excludes the
|
|
61
|
-
// caller's session, so without this an agent has no way to confirm its own
|
|
62
|
-
// claim is live. Optional with a default so an older client talking to a
|
|
63
|
-
// newer hub (or vice-versa) never fails validation on its absence.
|
|
64
|
-
yourClaims: e.array(X).default([]),
|
|
65
|
-
announcements: e.array(z),
|
|
66
|
-
// Per-agent change records for the workspace. Defaulted for version-skew safety.
|
|
67
|
-
changeRecords: e.array(Oe).default([])
|
|
68
|
-
}), Fe = e.object({
|
|
69
|
-
name: e.string(),
|
|
70
|
-
human: e.string(),
|
|
71
|
-
program: e.string(),
|
|
72
|
-
// model is nullable in the DB (may be unknown when an agent first joins).
|
|
73
|
-
model: e.string().nullable(),
|
|
74
|
-
// repo/branch/lastHeartbeatAt come from the agent's most-recent session and
|
|
75
|
-
// are null when the agent has no session yet.
|
|
76
|
-
repo: e.string().nullable(),
|
|
77
|
-
branch: e.string().nullable(),
|
|
78
|
-
lastHeartbeatAt: C.nullable(),
|
|
79
|
-
presence: e.enum(["live", "offline"])
|
|
80
|
-
}), Ue = e.enum(["active", "done", "dropped"]), He = e.object({
|
|
81
|
-
agentName: e.string(),
|
|
82
|
-
program: e.string(),
|
|
83
|
-
model: e.string().nullable(),
|
|
84
|
-
repo: e.string(),
|
|
85
|
-
intent: e.string(),
|
|
86
|
-
pathGlobs: e.array(e.string()),
|
|
87
|
-
status: Ue,
|
|
88
|
-
createdAt: C,
|
|
89
|
-
endedAt: C.nullable()
|
|
90
|
-
}), We = e.object({
|
|
91
|
-
fromAgentName: e.string(),
|
|
92
|
-
fromHuman: e.string(),
|
|
93
|
-
body: e.string(),
|
|
94
|
-
targetAgentName: e.string().nullable(),
|
|
95
|
-
repo: e.string(),
|
|
96
|
-
// True when the message was sent by the human operator from the dashboard
|
|
97
|
-
// (no agent session). The dashboard renders these as "me" (right-aligned).
|
|
98
|
-
// Defaulted for version-skew safety with older hubs.
|
|
99
|
-
fromAdmin: e.boolean().default(!1),
|
|
100
|
-
// True when an agent addressed the message TO the operator (the mirror of
|
|
101
|
-
// fromAdmin). The dashboard renders these as "<agent> → admin". Not delivered
|
|
102
|
-
// to other agents. Defaulted for version-skew safety with older hubs.
|
|
103
|
-
toAdmin: e.boolean().default(!1),
|
|
104
|
-
createdAt: C
|
|
105
|
-
}), ue = e.object({
|
|
106
|
-
agents: e.array(Fe),
|
|
107
|
-
tasks: e.array(He),
|
|
108
|
-
announcements: e.array(We),
|
|
109
|
-
// The server's clock, so the client computes "expires in / last seen" against
|
|
110
|
-
// the hub rather than the (possibly skewed) browser clock.
|
|
111
|
-
serverTime: C
|
|
112
|
-
});
|
|
113
|
-
e.object({
|
|
114
|
-
body: e.string().min(1).max(8192),
|
|
115
|
-
// Direct-message a single agent (by the exact name shown in the landscape).
|
|
116
|
-
// Absent/null => broadcast. The hub resolves the target's repo server-side.
|
|
117
|
-
targetAgentName: e.string().min(1).nullable().optional(),
|
|
118
|
-
// For a broadcast, the repo to scope the message to (matches the dashboard's
|
|
119
|
-
// selected repo). Absent/null => fan out to every repo in the workspace.
|
|
120
|
-
// Ignored for a DM (the target's own repo is used).
|
|
121
|
-
repo: e.string().min(1).nullable().optional()
|
|
122
|
-
});
|
|
123
|
-
const me = e.object({
|
|
124
|
-
ok: e.literal(!0),
|
|
125
|
-
// One id per inserted row: a single id for a DM or repo-scoped broadcast, or
|
|
126
|
-
// several when an all-repos broadcast fans out across repos.
|
|
127
|
-
announcementIds: e.array(K)
|
|
128
|
-
});
|
|
129
|
-
e.object({
|
|
130
|
-
workspace: e.string().min(1),
|
|
131
|
-
repo: e.string().min(1),
|
|
132
|
-
branch: e.string().min(1),
|
|
133
|
-
human: e.string().min(1),
|
|
134
|
-
program: e.string().min(1),
|
|
135
|
-
model: e.string().min(1).optional()
|
|
136
|
-
});
|
|
137
|
-
e.object({
|
|
138
|
-
agentName: e.string(),
|
|
139
|
-
sessionId: e.string().uuid()
|
|
140
|
-
});
|
|
141
|
-
const qe = e.object({
|
|
142
|
-
sessionId: e.string().uuid(),
|
|
143
|
-
intent: e.string().min(1).max(2048),
|
|
144
|
-
pathGlobs: e.array(e.string().min(1).max(512)).min(1).max(64),
|
|
145
|
-
ttlSeconds: e.number().int().positive().optional(),
|
|
146
|
-
changeReport: se.optional()
|
|
147
|
-
});
|
|
148
|
-
e.object({
|
|
149
|
-
workItemId: e.string().uuid(),
|
|
150
|
-
landscape: we
|
|
151
|
-
});
|
|
152
|
-
const Be = e.object({
|
|
153
|
-
sessionId: e.string().uuid(),
|
|
154
|
-
workItemId: e.string().uuid()
|
|
155
|
-
});
|
|
156
|
-
e.object({
|
|
157
|
-
ok: e.literal(!0),
|
|
158
|
-
// Pending announcements for the caller, delivered as a side effect of done so
|
|
159
|
-
// a message lands the moment a teammate finishes a unit of work (not only on
|
|
160
|
-
// their next work/sync). Defaulted for version-skew safety with older hubs.
|
|
161
|
-
announcements: e.array(z).default([])
|
|
162
|
-
});
|
|
163
|
-
const Ke = e.object({
|
|
164
|
-
sessionId: e.string().uuid(),
|
|
165
|
-
body: e.string().min(1).max(8192),
|
|
166
|
-
// absent or null => broadcast to all agents in the workspace
|
|
167
|
-
targetAgentName: e.string().nullable().optional(),
|
|
168
|
-
// true => address the human operator (the dashboard) instead of agents. The
|
|
169
|
-
// mirror of the operator's admin → agent DM: it shows in the workspace feed as
|
|
170
|
-
// "<agent> → admin" and is NOT delivered to other agents. Mutually exclusive
|
|
171
|
-
// with targetAgentName (the hub rejects setting both). Defaulted/optional for
|
|
172
|
-
// version skew with older clients.
|
|
173
|
-
toAdmin: e.boolean().optional()
|
|
174
|
-
});
|
|
175
|
-
e.object({
|
|
176
|
-
ok: e.literal(!0),
|
|
177
|
-
// bigint PK serialised as number; see DbId note above
|
|
178
|
-
announcementId: K,
|
|
179
|
-
// Pending announcements for the caller, delivered as a side effect of announce
|
|
180
|
-
// (a turn where the agent is already reading hub output) so inbound messages
|
|
181
|
-
// surface promptly. Excludes the just-sent one. Defaulted for version skew.
|
|
182
|
-
announcements: e.array(z).default([])
|
|
183
|
-
});
|
|
184
|
-
e.object({
|
|
185
|
-
sessionId: e.string().uuid(),
|
|
186
|
-
changeReport: se.optional()
|
|
187
|
-
});
|
|
188
|
-
e.object({
|
|
189
|
-
landscape: we
|
|
190
|
-
});
|
|
191
|
-
qe.omit({ sessionId: !0, changeReport: !0 });
|
|
192
|
-
Ke.omit({ sessionId: !0 });
|
|
193
|
-
Be.omit({ sessionId: !0 });
|
|
194
|
-
e.object({});
|
|
195
|
-
e.object({});
|
|
196
|
-
e.object({
|
|
197
|
-
sessionId: e.string().uuid(),
|
|
198
|
-
// Optional change report so the BACKGROUND heartbeat keeps an agent's durable
|
|
199
|
-
// change records fresh (commits surface within ~one heartbeat interval, not
|
|
200
|
-
// only when it next calls work/sync). Processed presence-style: it refreshes
|
|
201
|
-
// change records but, like the rest of heartbeat, does NOT renew claim TTLs.
|
|
202
|
-
changeReport: se.optional(),
|
|
203
|
-
// Opt-in: when set, the heartbeat returns any pending announcements for the
|
|
204
|
-
// caller in the response. Delivery is now TWO-PHASE and crash-safe: this fetch
|
|
205
|
-
// phase does NOT mark them delivered — the client persists them to its
|
|
206
|
-
// model-visible sink (the local inbox file drained by a hook) FIRST, then acks
|
|
207
|
-
// via `ackAnnouncementIds` so the hub records the delivery only after the local
|
|
208
|
-
// write is confirmed. The MCP client only sets this when it actually has such a
|
|
209
|
-
// sink. Absent for older clients, so default behaviour (no delivery) is
|
|
210
|
-
// unchanged.
|
|
211
|
-
deliverAnnouncements: e.boolean().optional(),
|
|
212
|
-
// Phase-two ack of a previous `deliverAnnouncements` fetch: the ids the client
|
|
213
|
-
// has now durably written to its model-visible sink. The hub marks exactly
|
|
214
|
-
// these delivered to the caller's session. Decoupling the mark from the fetch
|
|
215
|
-
// guarantees a message is never recorded delivered before the client holds it
|
|
216
|
-
// (a lost response or a failed local append simply leaves it pending for the
|
|
217
|
-
// next beat). Absent on a plain presence/fetch beat.
|
|
218
|
-
ackAnnouncementIds: e.array(K).optional()
|
|
219
|
-
});
|
|
220
|
-
e.object({
|
|
221
|
-
ok: e.literal(!0),
|
|
222
|
-
// Pending announcements for the caller, delivered only when the request set
|
|
223
|
-
// `deliverAnnouncements`. Defaulted to [] for version-skew safety with older
|
|
224
|
-
// hubs (which return just { ok: true }).
|
|
225
|
-
announcements: e.array(z).default([])
|
|
226
|
-
});
|
|
227
|
-
e.object({
|
|
228
|
-
sessionId: e.string().uuid()
|
|
229
|
-
});
|
|
230
|
-
e.object({
|
|
231
|
-
ok: e.literal(!0)
|
|
232
|
-
});
|
|
233
|
-
const Ae = e.enum(["admin", "member"]), ae = e.object({
|
|
234
|
-
id: e.string(),
|
|
235
|
-
slug: e.string(),
|
|
236
|
-
name: e.string(),
|
|
237
|
-
role: Ae
|
|
238
|
-
});
|
|
239
|
-
e.object({
|
|
240
|
-
name: e.string().min(1)
|
|
241
|
-
});
|
|
242
|
-
const ze = ae, Ye = e.object({
|
|
243
|
-
workspaces: e.array(ae)
|
|
244
|
-
});
|
|
245
|
-
e.object({
|
|
246
|
-
name: e.string().min(1).optional()
|
|
247
|
-
});
|
|
248
|
-
const Ve = e.object({
|
|
249
|
-
// The raw shp_ token, shown once at creation and never returned again.
|
|
250
|
-
token: e.string(),
|
|
251
|
-
id: e.string()
|
|
252
|
-
}), Xe = e.object({
|
|
253
|
-
id: e.string(),
|
|
254
|
-
name: e.string().nullable(),
|
|
255
|
-
// ISO timestamp string (see IsoTimestamp note above) or null when unused / not revoked.
|
|
256
|
-
lastUsedAt: C.nullable(),
|
|
257
|
-
createdAt: C,
|
|
258
|
-
revokedAt: C.nullable()
|
|
259
|
-
}), Ze = e.object({
|
|
260
|
-
tokens: e.array(Xe)
|
|
261
|
-
});
|
|
262
|
-
e.object({
|
|
263
|
-
expiresInDays: e.number().int().positive().optional(),
|
|
264
|
-
// Omitted = unlimited, redeemable until explicitly revoked. Pass a positive
|
|
265
|
-
// integer to cap it instead.
|
|
266
|
-
maxUses: e.number().int().positive().optional()
|
|
267
|
-
});
|
|
268
|
-
const Je = e.object({
|
|
269
|
-
code: e.string(),
|
|
270
|
-
// ISO timestamp string, or null when the invite never expires.
|
|
271
|
-
expiresAt: C.nullable(),
|
|
272
|
-
// null = unlimited (redeemable until revoked).
|
|
273
|
-
maxUses: e.number().int().positive().nullable(),
|
|
274
|
-
useCount: e.number().int().nonnegative()
|
|
275
|
-
});
|
|
276
|
-
e.object({
|
|
277
|
-
email: e.string().email()
|
|
278
|
-
});
|
|
279
|
-
const Qe = e.object({
|
|
280
|
-
email: e.string(),
|
|
281
|
-
sentAt: C
|
|
282
|
-
}), et = e.object({
|
|
283
|
-
// The workspace the caller just joined.
|
|
284
|
-
workspace: ae
|
|
285
|
-
}), tt = e.object({
|
|
286
|
-
accountId: e.string(),
|
|
287
|
-
displayName: e.string().nullable(),
|
|
288
|
-
githubLogin: e.string().nullable(),
|
|
289
|
-
avatarUrl: e.string().nullable(),
|
|
290
|
-
role: Ae
|
|
291
|
-
}), nt = e.object({
|
|
292
|
-
members: e.array(tt)
|
|
293
|
-
}), st = e.enum(["bug", "suggestion", "other"]);
|
|
294
|
-
e.object({
|
|
295
|
-
type: st,
|
|
296
|
-
body: e.string().trim().min(1).max(4e3)
|
|
297
|
-
});
|
|
298
|
-
const at = e.object({
|
|
299
|
-
ok: e.literal(!0),
|
|
300
|
-
// uuid PK (the feedback table, like workspaces, uses gen_random_uuid()).
|
|
301
|
-
id: e.string()
|
|
302
|
-
}), rt = 5e3;
|
|
303
|
-
class U extends Error {
|
|
304
|
-
/**
|
|
305
|
-
* @param message - Human-readable failure description.
|
|
306
|
-
* @param status - Upstream HTTP status, omitted for network/abort failures.
|
|
307
|
-
*/
|
|
308
|
-
constructor(i, r) {
|
|
309
|
-
super(i);
|
|
310
|
-
/** Upstream HTTP status for a non-2xx response; absent for transport errors. */
|
|
311
|
-
de(this, "status");
|
|
312
|
-
this.name = "ShepherdClientError", r !== void 0 && (this.status = r);
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
function ot(t) {
|
|
316
|
-
return t instanceof Error ? t.message : "Something went wrong.";
|
|
317
|
-
}
|
|
318
|
-
async function it(t) {
|
|
319
|
-
try {
|
|
320
|
-
const n = await t.json();
|
|
321
|
-
if (n !== null && typeof n == "object" && "error" in n && typeof n.error == "string")
|
|
322
|
-
return n.error;
|
|
323
|
-
} catch {
|
|
324
|
-
}
|
|
325
|
-
return "";
|
|
326
|
-
}
|
|
327
|
-
function Ht(t) {
|
|
328
|
-
const n = t.baseUrl.replace(/\/$/, ""), i = t.timeoutMs ?? rt, r = encodeURIComponent;
|
|
329
|
-
async function a(s, c, l = {}) {
|
|
330
|
-
var b, y;
|
|
331
|
-
const h = new AbortController(), u = setTimeout(() => h.abort(), i);
|
|
332
|
-
let d;
|
|
333
|
-
try {
|
|
334
|
-
const v = {
|
|
335
|
-
"Content-Type": "application/json"
|
|
336
|
-
}, T = await ((b = t.getAuthHeader) == null ? void 0 : b.call(t)), A = {
|
|
337
|
-
method: s,
|
|
338
|
-
headers: { ...v, ...typeof T == "string" ? { Authorization: T } : T ?? {} },
|
|
339
|
-
signal: h.signal
|
|
340
|
-
};
|
|
341
|
-
l.body !== void 0 && (A.body = JSON.stringify(l.body)), d = await fetch(`${n}${c}`, A);
|
|
342
|
-
} catch (v) {
|
|
343
|
-
throw new U(
|
|
344
|
-
v instanceof Error ? v.message : String(v)
|
|
345
|
-
);
|
|
346
|
-
} finally {
|
|
347
|
-
clearTimeout(u);
|
|
348
|
-
}
|
|
349
|
-
if (d.status === 401)
|
|
350
|
-
throw (y = t.onUnauthorized) == null || y.call(t), new U("Unauthorized", 401);
|
|
351
|
-
if (!d.ok) {
|
|
352
|
-
const v = await it(d);
|
|
353
|
-
throw new U(
|
|
354
|
-
v !== "" ? `HTTP ${d.status}: ${v}` : `HTTP ${d.status}`,
|
|
355
|
-
d.status
|
|
356
|
-
);
|
|
357
|
-
}
|
|
358
|
-
if (!l.schema) {
|
|
359
|
-
try {
|
|
360
|
-
await d.json();
|
|
361
|
-
} catch {
|
|
362
|
-
}
|
|
363
|
-
return;
|
|
364
|
-
}
|
|
365
|
-
const f = l.schema.safeParse(await d.json());
|
|
366
|
-
if (!f.success)
|
|
367
|
-
throw new U("Invalid response schema");
|
|
368
|
-
return f.data;
|
|
369
|
-
}
|
|
370
|
-
return {
|
|
371
|
-
baseUrl: n,
|
|
372
|
-
// --- multi-workspace management surface ---------------------------------
|
|
373
|
-
listWorkspaces() {
|
|
374
|
-
return a("GET", "/workspaces", {
|
|
375
|
-
schema: Ye
|
|
376
|
-
});
|
|
377
|
-
},
|
|
378
|
-
createWorkspace(s) {
|
|
379
|
-
return a("POST", "/workspaces", {
|
|
380
|
-
body: s,
|
|
381
|
-
schema: ze
|
|
382
|
-
});
|
|
383
|
-
},
|
|
384
|
-
mintToken(s, c) {
|
|
385
|
-
return a("POST", `/workspaces/${r(s)}/tokens`, {
|
|
386
|
-
body: c,
|
|
387
|
-
schema: Ve
|
|
388
|
-
});
|
|
389
|
-
},
|
|
390
|
-
listTokens(s) {
|
|
391
|
-
return a("GET", `/workspaces/${r(s)}/tokens`, {
|
|
392
|
-
schema: Ze
|
|
393
|
-
});
|
|
394
|
-
},
|
|
395
|
-
revokeToken(s, c) {
|
|
396
|
-
return a(
|
|
397
|
-
"DELETE",
|
|
398
|
-
`/workspaces/${r(s)}/tokens/${r(c)}`
|
|
399
|
-
);
|
|
400
|
-
},
|
|
401
|
-
createInvite(s, c) {
|
|
402
|
-
return a("POST", `/workspaces/${r(s)}/invites`, {
|
|
403
|
-
body: c,
|
|
404
|
-
schema: Je
|
|
405
|
-
});
|
|
406
|
-
},
|
|
407
|
-
inviteByEmail(s, c) {
|
|
408
|
-
return a("POST", `/workspaces/${r(s)}/invites/email`, {
|
|
409
|
-
body: { email: c },
|
|
410
|
-
schema: Qe
|
|
411
|
-
});
|
|
412
|
-
},
|
|
413
|
-
revokeInvite(s, c) {
|
|
414
|
-
return a(
|
|
415
|
-
"POST",
|
|
416
|
-
`/workspaces/${r(s)}/invites/${r(c)}/revoke`
|
|
417
|
-
);
|
|
418
|
-
},
|
|
419
|
-
redeemInvite(s) {
|
|
420
|
-
return a("POST", `/invites/${r(s)}/redeem`, {
|
|
421
|
-
schema: et
|
|
422
|
-
});
|
|
423
|
-
},
|
|
424
|
-
listMembers(s) {
|
|
425
|
-
return a("GET", `/workspaces/${r(s)}/members`, {
|
|
426
|
-
schema: nt
|
|
427
|
-
});
|
|
428
|
-
},
|
|
429
|
-
removeMember(s, c) {
|
|
430
|
-
return a(
|
|
431
|
-
"DELETE",
|
|
432
|
-
`/workspaces/${r(s)}/members/${r(c)}`
|
|
433
|
-
);
|
|
434
|
-
},
|
|
435
|
-
leave(s) {
|
|
436
|
-
return a("POST", `/workspaces/${r(s)}/leave`);
|
|
437
|
-
},
|
|
438
|
-
landscape(s) {
|
|
439
|
-
return a("GET", `/workspaces/${r(s)}/landscape`, {
|
|
440
|
-
schema: ue
|
|
441
|
-
});
|
|
442
|
-
},
|
|
443
|
-
announceTo(s, c) {
|
|
444
|
-
return a("POST", `/workspaces/${r(s)}/announce`, {
|
|
445
|
-
body: c,
|
|
446
|
-
schema: me
|
|
447
|
-
});
|
|
448
|
-
},
|
|
449
|
-
submitFeedback(s, c) {
|
|
450
|
-
const l = c !== void 0 ? `/workspaces/${r(c)}/feedback` : "/feedback";
|
|
451
|
-
return a("POST", l, { body: s, schema: at });
|
|
452
|
-
},
|
|
453
|
-
// --- self-host singular aliases (implicit single workspace) -------------
|
|
454
|
-
getLandscape() {
|
|
455
|
-
return a("GET", "/workspace/landscape", {
|
|
456
|
-
schema: ue
|
|
457
|
-
});
|
|
458
|
-
},
|
|
459
|
-
announce(s) {
|
|
460
|
-
return a("POST", "/workspace/announce", {
|
|
461
|
-
body: s,
|
|
462
|
-
schema: me
|
|
463
|
-
});
|
|
464
|
-
}
|
|
465
|
-
};
|
|
466
|
-
}
|
|
467
|
-
const Se = xe(null);
|
|
468
|
-
function Wt({
|
|
469
|
-
client: t,
|
|
470
|
-
children: n
|
|
471
|
-
}) {
|
|
472
|
-
return /* @__PURE__ */ o(Se.Provider, { value: t, children: n });
|
|
473
|
-
}
|
|
474
|
-
function re() {
|
|
475
|
-
const t = Me(Se);
|
|
476
|
-
if (t === null)
|
|
477
|
-
throw new Error(
|
|
478
|
-
"useShepherdClient must be used within <ShepherdClientProvider>"
|
|
479
|
-
);
|
|
480
|
-
return t;
|
|
481
|
-
}
|
|
482
|
-
const ct = 5e3, lt = 1e3;
|
|
483
|
-
function dt(t) {
|
|
484
|
-
const n = re(), i = t == null ? void 0 : t.workspaceId, r = (t == null ? void 0 : t.pollMs) ?? ct, a = (t == null ? void 0 : t.enabled) ?? !0, [s, c] = w(
|
|
485
|
-
null
|
|
486
|
-
), [l, h] = w("live"), [u, d] = w(null), [, f] = w(0), b = P(n);
|
|
487
|
-
b.current = n;
|
|
488
|
-
const y = P(0), v = j(
|
|
489
|
-
async ($) => {
|
|
490
|
-
try {
|
|
491
|
-
const A = i ? await b.current.landscape(i) : await b.current.getLandscape();
|
|
492
|
-
if ($ !== y.current) return;
|
|
493
|
-
c(A), d(Date.now()), h("live");
|
|
494
|
-
} catch (A) {
|
|
495
|
-
if ($ !== y.current) return;
|
|
496
|
-
A instanceof U && A.status === 401 ? h("unauthorized") : h("reconnecting");
|
|
497
|
-
}
|
|
498
|
-
},
|
|
499
|
-
[i]
|
|
500
|
-
);
|
|
501
|
-
ne(() => {
|
|
502
|
-
if (!a) return;
|
|
503
|
-
const $ = ++y.current;
|
|
504
|
-
v($);
|
|
505
|
-
const A = setInterval(() => {
|
|
506
|
-
document.visibilityState !== "hidden" && v($);
|
|
507
|
-
}, r), k = setInterval(() => {
|
|
508
|
-
f((E) => E + 1);
|
|
509
|
-
}, lt), R = () => {
|
|
510
|
-
document.visibilityState === "visible" && v($);
|
|
511
|
-
};
|
|
512
|
-
return document.addEventListener("visibilitychange", R), () => {
|
|
513
|
-
y.current++, clearInterval(A), clearInterval(k), document.removeEventListener("visibilitychange", R);
|
|
514
|
-
};
|
|
515
|
-
}, [v, r, a]);
|
|
516
|
-
const T = j(() => v(y.current), [v]);
|
|
517
|
-
return { snapshot: s, status: l, lastUpdatedMs: u, refresh: T };
|
|
518
|
-
}
|
|
519
|
-
function q(t, n) {
|
|
520
|
-
const i = Math.floor((n - Date.parse(t)) / 1e3);
|
|
521
|
-
if (i < 5) return "just now";
|
|
522
|
-
if (i < 60) return `${i}s ago`;
|
|
523
|
-
const r = Math.floor(i / 60);
|
|
524
|
-
if (r < 60) return `${r}m ago`;
|
|
525
|
-
const a = Math.floor(r / 60);
|
|
526
|
-
return a < 24 ? `${a}h ago` : `${Math.floor(a / 24)}d ago`;
|
|
527
|
-
}
|
|
528
|
-
function B(t) {
|
|
529
|
-
let n = 0;
|
|
530
|
-
for (let i = 0; i < t.length; i++) n = (n * 31 + t.charCodeAt(i)) % 360;
|
|
531
|
-
return `hsl(${n}, 38%, 42%)`;
|
|
532
|
-
}
|
|
533
|
-
function oe(t) {
|
|
534
|
-
if (!t) return "?";
|
|
535
|
-
const n = t.match(/[A-Z]/g);
|
|
536
|
-
return n && n.length >= 2 ? n[0] + n[1] : t.slice(0, 2).toUpperCase();
|
|
537
|
-
}
|
|
538
|
-
const Te = "A-Za-z0-9_-";
|
|
539
|
-
function ut(t, n) {
|
|
540
|
-
const r = t.slice(0, n).match(new RegExp(`(?:^|\\s)@([${Te}]*)$`));
|
|
541
|
-
if (!r) return null;
|
|
542
|
-
const a = r[1];
|
|
543
|
-
return { start: n - a.length - 1, end: n, query: a };
|
|
544
|
-
}
|
|
545
|
-
function mt(t, n) {
|
|
546
|
-
const i = new RegExp(`(?:^|\\s)@([${Te}]+)`, "g");
|
|
547
|
-
let r;
|
|
548
|
-
for (; (r = i.exec(t)) !== null; ) {
|
|
549
|
-
const a = r[1].toLowerCase(), s = n.find((c) => c.toLowerCase() === a);
|
|
550
|
-
if (s) return s;
|
|
551
|
-
}
|
|
552
|
-
return null;
|
|
553
|
-
}
|
|
554
|
-
function Ce(t) {
|
|
555
|
-
return [...new Set(t.map((n) => n.repo))].sort();
|
|
556
|
-
}
|
|
557
|
-
function M(t, n) {
|
|
558
|
-
return n === null || n === "__all__" || t.repo === n;
|
|
559
|
-
}
|
|
560
|
-
function ht(t, n) {
|
|
561
|
-
return [
|
|
562
|
-
...new Set(
|
|
563
|
-
t.filter((i) => i.presence === "live" && M(i, n)).map((i) => i.name)
|
|
564
|
-
)
|
|
565
|
-
].sort();
|
|
566
|
-
}
|
|
567
|
-
function he(t) {
|
|
568
|
-
const n = t.find((i) => i.status === "active");
|
|
569
|
-
return n ? n.repo : t.length ? t[0].repo : null;
|
|
570
|
-
}
|
|
571
|
-
function pt(t) {
|
|
572
|
-
return t === "dropped" ? "dropped" : "done";
|
|
573
|
-
}
|
|
574
|
-
function pe(t, n) {
|
|
575
|
-
if (!n) return "";
|
|
576
|
-
const i = Math.floor((Date.parse(n) - Date.parse(t)) / 1e3), r = Math.floor(i / 60);
|
|
577
|
-
return r < 60 ? `active ${r}m` : `active ${Math.floor(r / 60)}h`;
|
|
578
|
-
}
|
|
579
|
-
function gt(t, n) {
|
|
580
|
-
const i = new Date(Date.parse(t)), r = new Date(n), a = (c) => new Date(c.getFullYear(), c.getMonth(), c.getDate()).getTime(), s = Math.round((a(r) - a(i)) / 864e5);
|
|
581
|
-
return s <= 0 ? "Today" : s === 1 ? "Yesterday" : i.toLocaleDateString(void 0, { month: "short", day: "numeric" });
|
|
582
|
-
}
|
|
583
|
-
function ge(t) {
|
|
584
|
-
let n = t.toLowerCase().replace(/\\/g, "/");
|
|
585
|
-
n.endsWith("/") && (n = n.replace(/\/+$/, "") + "/**");
|
|
586
|
-
const i = [];
|
|
587
|
-
for (const r of n.split("/"))
|
|
588
|
-
if (!(r === "" || r === ".")) {
|
|
589
|
-
if (r === "..") {
|
|
590
|
-
i.length && i.pop();
|
|
591
|
-
continue;
|
|
592
|
-
}
|
|
593
|
-
i.push(r);
|
|
594
|
-
}
|
|
595
|
-
return i;
|
|
596
|
-
}
|
|
597
|
-
const fe = /[*?{}[\]]/;
|
|
598
|
-
function ft(t, n) {
|
|
599
|
-
return t === "*" ? !0 : (fe.test(t) || !fe.test(n)) && t === n;
|
|
600
|
-
}
|
|
601
|
-
function bt(t, n) {
|
|
602
|
-
const i = /* @__PURE__ */ new Map();
|
|
603
|
-
function r(a, s) {
|
|
604
|
-
if (n.length - s === 0) {
|
|
605
|
-
for (let f = a; f < t.length; f++) if (t[f] !== "**") return !1;
|
|
606
|
-
return !0;
|
|
607
|
-
}
|
|
608
|
-
if (t.length - a === 0) return !1;
|
|
609
|
-
const c = a * (n.length + 1) + s, l = i.get(c);
|
|
610
|
-
if (l !== void 0) return l;
|
|
611
|
-
const h = t[a], u = n[s];
|
|
612
|
-
let d;
|
|
613
|
-
return h === "**" ? d = r(a + 1, s) || r(a, s + 1) : u === "**" ? d = !1 : d = ft(h, u) && r(a + 1, s + 1), i.set(c, d), d;
|
|
614
|
-
}
|
|
615
|
-
return r(0, 0);
|
|
616
|
-
}
|
|
617
|
-
function be(t, n) {
|
|
618
|
-
if (n.length === 0) return !0;
|
|
619
|
-
const i = t.map(ge);
|
|
620
|
-
return n.every((r) => {
|
|
621
|
-
const a = ge(r);
|
|
622
|
-
return i.some((s) => bt(s, a));
|
|
623
|
-
});
|
|
624
|
-
}
|
|
625
|
-
function vt(t) {
|
|
626
|
-
const n = /* @__PURE__ */ new Map();
|
|
627
|
-
for (const a of t)
|
|
628
|
-
n.has(a.agentName) || n.set(a.agentName, []), n.get(a.agentName).push(a);
|
|
629
|
-
const i = (a, s) => s.createdAt.localeCompare(a.createdAt), r = [];
|
|
630
|
-
for (const [a, s] of n) {
|
|
631
|
-
const c = [...s].sort(i), l = c.map(
|
|
632
|
-
(u) => c.some(
|
|
633
|
-
(d) => d !== u && be(d.pathGlobs, u.pathGlobs) && !be(u.pathGlobs, d.pathGlobs)
|
|
634
|
-
)
|
|
635
|
-
), h = c[0];
|
|
636
|
-
r.push({
|
|
637
|
-
agentName: a,
|
|
638
|
-
model: h.model,
|
|
639
|
-
program: h.program,
|
|
640
|
-
repo: h.repo,
|
|
641
|
-
primaries: c.filter((u, d) => !l[d]),
|
|
642
|
-
narrower: c.filter((u, d) => l[d])
|
|
643
|
-
});
|
|
644
|
-
}
|
|
645
|
-
return r.sort((a, s) => {
|
|
646
|
-
const c = a.primaries.concat(a.narrower)[0].createdAt;
|
|
647
|
-
return s.primaries.concat(s.narrower)[0].createdAt.localeCompare(c);
|
|
648
|
-
}), r;
|
|
649
|
-
}
|
|
650
|
-
const ve = { active: 0, done: 0 };
|
|
651
|
-
function yt({
|
|
652
|
-
repos: t,
|
|
653
|
-
counts: n,
|
|
654
|
-
selected: i,
|
|
655
|
-
onSelect: r
|
|
656
|
-
}) {
|
|
657
|
-
const [a, s] = w(!1), c = P(null);
|
|
658
|
-
if (ne(() => {
|
|
659
|
-
var b;
|
|
660
|
-
if (!a) return;
|
|
661
|
-
const d = (b = c.current) == null ? void 0 : b.querySelector(".repo-menu");
|
|
662
|
-
if (!d) return;
|
|
663
|
-
const f = d.querySelector('[aria-selected="true"]') ?? d.querySelector("button");
|
|
664
|
-
f == null || f.focus();
|
|
665
|
-
}, [a]), t.length < 2) return null;
|
|
666
|
-
const l = i === null || i === "__all__", h = l ? "All repos" : i, u = (d, f) => {
|
|
667
|
-
const b = d === null ? n.__all__ ?? ve : n[d] ?? ve, y = d === null ? l : i === d, v = "repo-mi" + (y ? " on" : "") + (d === null ? " all" : "");
|
|
668
|
-
return /* @__PURE__ */ m(
|
|
669
|
-
"button",
|
|
670
|
-
{
|
|
671
|
-
type: "button",
|
|
672
|
-
className: v,
|
|
673
|
-
role: "option",
|
|
674
|
-
"aria-selected": y,
|
|
675
|
-
onClick: (T) => {
|
|
676
|
-
T.stopPropagation(), s(!1), r(d);
|
|
677
|
-
},
|
|
678
|
-
children: [
|
|
679
|
-
/* @__PURE__ */ o("span", { children: f }),
|
|
680
|
-
/* @__PURE__ */ o("span", { className: "ct", children: `${b.active} active · ${b.done} done` })
|
|
681
|
-
]
|
|
682
|
-
},
|
|
683
|
-
d ?? "__all__"
|
|
684
|
-
);
|
|
685
|
-
};
|
|
686
|
-
return /* @__PURE__ */ m(
|
|
687
|
-
"span",
|
|
688
|
-
{
|
|
689
|
-
ref: c,
|
|
690
|
-
className: "repo",
|
|
691
|
-
onKeyDown: (d) => {
|
|
692
|
-
d.key === "Escape" && s(!1);
|
|
693
|
-
},
|
|
694
|
-
children: [
|
|
695
|
-
/* @__PURE__ */ m(
|
|
696
|
-
"button",
|
|
697
|
-
{
|
|
698
|
-
type: "button",
|
|
699
|
-
className: "repo-trig",
|
|
700
|
-
"aria-haspopup": "listbox",
|
|
701
|
-
"aria-expanded": a,
|
|
702
|
-
"aria-label": `Filter by repo (current: ${h})`,
|
|
703
|
-
onClick: (d) => {
|
|
704
|
-
d.stopPropagation(), s((f) => !f);
|
|
705
|
-
},
|
|
706
|
-
children: [
|
|
707
|
-
/* @__PURE__ */ o("span", { className: "slash", children: "/" }),
|
|
708
|
-
" " + h + " ",
|
|
709
|
-
/* @__PURE__ */ o("span", { children: "▼" })
|
|
710
|
-
]
|
|
711
|
-
}
|
|
712
|
-
),
|
|
713
|
-
a && /* @__PURE__ */ m("div", { className: "repo-menu", role: "listbox", children: [
|
|
714
|
-
t.map((d) => u(d, d)),
|
|
715
|
-
u(null, "All repos")
|
|
716
|
-
] })
|
|
717
|
-
]
|
|
718
|
-
}
|
|
719
|
-
);
|
|
720
|
-
}
|
|
721
|
-
function kt({ agents: t, tasks: n, selectedRepo: i }) {
|
|
722
|
-
const r = t.filter(
|
|
723
|
-
(l) => l.presence === "live" && M({ repo: l.repo ?? "" }, i)
|
|
724
|
-
), a = /* @__PURE__ */ new Set();
|
|
725
|
-
for (const l of n) l.status === "active" && a.add(l.agentName);
|
|
726
|
-
const s = (l) => a.has(l.name), c = [...r].sort((l, h) => {
|
|
727
|
-
const u = s(l), d = s(h);
|
|
728
|
-
return u !== d ? u ? -1 : 1 : l.name.localeCompare(h.name);
|
|
729
|
-
});
|
|
730
|
-
return /* @__PURE__ */ o("div", { className: "crew", id: "crew", children: c.map((l) => /* @__PURE__ */ m(
|
|
731
|
-
"div",
|
|
732
|
-
{
|
|
733
|
-
className: "person" + (s(l) ? "" : " person--idle"),
|
|
734
|
-
children: [
|
|
735
|
-
/* @__PURE__ */ o("div", { className: "avatar", style: { background: B(l.name) }, children: oe(l.name) }),
|
|
736
|
-
/* @__PURE__ */ o("span", { className: "person__name", children: l.name })
|
|
737
|
-
]
|
|
738
|
-
},
|
|
739
|
-
l.name
|
|
740
|
-
)) });
|
|
741
|
-
}
|
|
742
|
-
function $e({ globs: t }) {
|
|
743
|
-
return t.length <= 1 ? /* @__PURE__ */ m("div", { className: "terr", children: [
|
|
744
|
-
/* @__PURE__ */ o("span", { className: "terr__lbl", children: "territory" }),
|
|
745
|
-
t.map((n) => /* @__PURE__ */ o("span", { className: "glob", children: n }, n))
|
|
746
|
-
] }) : /* @__PURE__ */ m("details", { className: "terrx", children: [
|
|
747
|
-
/* @__PURE__ */ m("summary", { children: [
|
|
748
|
-
/* @__PURE__ */ o("span", { className: "terr__lbl", children: "territory" }),
|
|
749
|
-
/* @__PURE__ */ m("span", { className: "glob glob--more", children: [
|
|
750
|
-
/* @__PURE__ */ o("span", { className: "tw", children: "▶" }),
|
|
751
|
-
` ${t.length} paths`
|
|
752
|
-
] })
|
|
753
|
-
] }),
|
|
754
|
-
/* @__PURE__ */ o("div", { className: "terr terr--full", children: t.map((n) => /* @__PURE__ */ o("span", { className: "glob", children: n }, n)) })
|
|
755
|
-
] });
|
|
756
|
-
}
|
|
757
|
-
const ee = (t) => `${t.agentName}|${t.repo}|${t.createdAt}`, _t = (t) => t === null || t === "__all__";
|
|
758
|
-
function te({
|
|
759
|
-
task: t,
|
|
760
|
-
nowMs: n
|
|
761
|
-
}) {
|
|
762
|
-
return /* @__PURE__ */ m(H, { children: [
|
|
763
|
-
/* @__PURE__ */ o("div", { className: "task__intent", children: t.intent }),
|
|
764
|
-
/* @__PURE__ */ o($e, { globs: t.pathGlobs }),
|
|
765
|
-
/* @__PURE__ */ o("div", { className: "task__meta", children: `started ${q(t.createdAt, n)}` })
|
|
766
|
-
] });
|
|
767
|
-
}
|
|
768
|
-
function Nt({
|
|
769
|
-
task: t,
|
|
770
|
-
nowMs: n,
|
|
771
|
-
allRepos: i
|
|
772
|
-
}) {
|
|
773
|
-
const r = t.model || t.program;
|
|
774
|
-
return /* @__PURE__ */ m("div", { className: "task", children: [
|
|
775
|
-
/* @__PURE__ */ m("div", { className: "task__r1", children: [
|
|
776
|
-
/* @__PURE__ */ o("span", { className: "task__who", children: t.agentName }),
|
|
777
|
-
i && /* @__PURE__ */ o("span", { className: "task__repo", children: t.repo }),
|
|
778
|
-
r && /* @__PURE__ */ o("span", { className: "task__tag", children: r }),
|
|
779
|
-
/* @__PURE__ */ o("span", { className: "livedot", title: "active" })
|
|
780
|
-
] }),
|
|
781
|
-
/* @__PURE__ */ o(te, { task: t, nowMs: n })
|
|
782
|
-
] });
|
|
783
|
-
}
|
|
784
|
-
function wt({
|
|
785
|
-
group: t,
|
|
786
|
-
nowMs: n,
|
|
787
|
-
allRepos: i
|
|
788
|
-
}) {
|
|
789
|
-
const r = t.model || t.program, a = t.primaries.length + t.narrower.length, s = t.narrower.length;
|
|
790
|
-
return /* @__PURE__ */ m("div", { className: "grp", children: [
|
|
791
|
-
/* @__PURE__ */ m("div", { className: "grp__head", children: [
|
|
792
|
-
/* @__PURE__ */ o("span", { className: "grp__who", children: t.agentName }),
|
|
793
|
-
i && /* @__PURE__ */ o("span", { className: "task__repo", children: t.repo }),
|
|
794
|
-
r && /* @__PURE__ */ o("span", { className: "grp__tag", children: r }),
|
|
795
|
-
/* @__PURE__ */ o("span", { className: "grp__count", children: `· ${a} active` }),
|
|
796
|
-
/* @__PURE__ */ o("span", { className: "grp__dot", title: "live" })
|
|
797
|
-
] }),
|
|
798
|
-
/* @__PURE__ */ o("div", { className: "claims", children: t.primaries.map((c) => /* @__PURE__ */ o("div", { className: "claim", children: /* @__PURE__ */ o(te, { task: c, nowMs: n }) }, ee(c))) }),
|
|
799
|
-
s > 0 && /* @__PURE__ */ m("details", { className: "fold", children: [
|
|
800
|
-
/* @__PURE__ */ m("summary", { children: [
|
|
801
|
-
/* @__PURE__ */ o("span", { className: "tw", children: "▶" }),
|
|
802
|
-
` +${s} narrower claim${s > 1 ? "s" : ""}`
|
|
803
|
-
] }),
|
|
804
|
-
/* @__PURE__ */ o("div", { className: "fold__body", children: t.narrower.map((c) => /* @__PURE__ */ m("div", { className: "claim", children: [
|
|
805
|
-
/* @__PURE__ */ o(te, { task: c, nowMs: n }),
|
|
806
|
-
/* @__PURE__ */ o("div", { className: "covered", children: "⊂ covered by a claim above" })
|
|
807
|
-
] }, ee(c))) })
|
|
808
|
-
] })
|
|
809
|
-
] });
|
|
810
|
-
}
|
|
811
|
-
function At({
|
|
812
|
-
tasks: t,
|
|
813
|
-
nowMs: n,
|
|
814
|
-
selectedRepo: i
|
|
815
|
-
}) {
|
|
816
|
-
const r = _t(i), a = t.filter(
|
|
817
|
-
(s) => s.status === "active" && M(s, i)
|
|
818
|
-
);
|
|
819
|
-
if (a.length === 0) {
|
|
820
|
-
const s = r ? "Nothing active right now." : `Nothing active in ${i}.`;
|
|
821
|
-
return /* @__PURE__ */ o("div", { id: "active-list", children: /* @__PURE__ */ o("div", { className: "empty", children: s }) });
|
|
822
|
-
}
|
|
823
|
-
return /* @__PURE__ */ o("div", { id: "active-list", children: vt(a).map((s) => {
|
|
824
|
-
const c = s.primaries.length === 1 && s.narrower.length === 0, l = ee(s.primaries.concat(s.narrower)[0]);
|
|
825
|
-
return c ? /* @__PURE__ */ o(
|
|
826
|
-
Nt,
|
|
827
|
-
{
|
|
828
|
-
task: s.primaries[0],
|
|
829
|
-
nowMs: n,
|
|
830
|
-
allRepos: r
|
|
831
|
-
},
|
|
832
|
-
l
|
|
833
|
-
) : /* @__PURE__ */ o(wt, { group: s, nowMs: n, allRepos: r }, l);
|
|
834
|
-
}) });
|
|
835
|
-
}
|
|
836
|
-
const St = (t) => `${t.agentName}|${t.repo}|${t.createdAt}`, Tt = (t) => t === null || t === "__all__";
|
|
837
|
-
function Ct({
|
|
838
|
-
tasks: t,
|
|
839
|
-
nowMs: n,
|
|
840
|
-
selectedRepo: i,
|
|
841
|
-
doneShown: r,
|
|
842
|
-
onLoadMore: a
|
|
843
|
-
}) {
|
|
844
|
-
const s = Tt(i), c = t.filter(
|
|
845
|
-
(u) => u.status !== "active" && M(u, i)
|
|
846
|
-
);
|
|
847
|
-
if (c.length === 0) {
|
|
848
|
-
const u = s ? "No finished tasks yet." : `No finished tasks in ${i} yet.`;
|
|
849
|
-
return /* @__PURE__ */ o("div", { id: "done-list", children: /* @__PURE__ */ o("div", { className: "empty", children: u }) });
|
|
850
|
-
}
|
|
851
|
-
const l = c.slice(0, r);
|
|
852
|
-
let h = null;
|
|
853
|
-
return /* @__PURE__ */ m("div", { id: "done-list", children: [
|
|
854
|
-
l.map((u) => {
|
|
855
|
-
const d = gt(u.endedAt ?? u.createdAt, n), f = d !== h ? d : null;
|
|
856
|
-
h = d;
|
|
857
|
-
const b = u.status === "dropped", y = b ? `went offline ${q(u.endedAt ?? u.createdAt, n)} — no done signal` : `finished ${q(u.endedAt ?? u.createdAt, n)}${pe(u.createdAt, u.endedAt) ? " · " + pe(u.createdAt, u.endedAt) : ""}`;
|
|
858
|
-
return /* @__PURE__ */ m(Le, { children: [
|
|
859
|
-
f !== null && /* @__PURE__ */ o("div", { className: "day", children: f }),
|
|
860
|
-
/* @__PURE__ */ m("div", { className: "task", children: [
|
|
861
|
-
/* @__PURE__ */ m("div", { className: "task__r1", children: [
|
|
862
|
-
/* @__PURE__ */ o("span", { className: "task__who", children: u.agentName }),
|
|
863
|
-
s && /* @__PURE__ */ o("span", { className: "task__repo", children: u.repo }),
|
|
864
|
-
/* @__PURE__ */ o(
|
|
865
|
-
"span",
|
|
866
|
-
{
|
|
867
|
-
className: "task__stat" + (b ? " task__stat--drop" : ""),
|
|
868
|
-
children: pt(u.status)
|
|
869
|
-
}
|
|
870
|
-
)
|
|
871
|
-
] }),
|
|
872
|
-
/* @__PURE__ */ o("div", { className: "task__intent", children: u.intent }),
|
|
873
|
-
/* @__PURE__ */ o($e, { globs: u.pathGlobs }),
|
|
874
|
-
/* @__PURE__ */ o("div", { className: "task__meta", children: y })
|
|
875
|
-
] })
|
|
876
|
-
] }, St(u));
|
|
877
|
-
}),
|
|
878
|
-
c.length > r && /* @__PURE__ */ o(
|
|
879
|
-
"div",
|
|
880
|
-
{
|
|
881
|
-
className: "more",
|
|
882
|
-
role: "button",
|
|
883
|
-
tabIndex: 0,
|
|
884
|
-
onClick: a,
|
|
885
|
-
onKeyDown: (u) => {
|
|
886
|
-
(u.key === "Enter" || u.key === " ") && (u.preventDefault(), a());
|
|
887
|
-
},
|
|
888
|
-
children: `Load older · ${r} of ${c.length}`
|
|
889
|
-
}
|
|
890
|
-
)
|
|
891
|
-
] });
|
|
892
|
-
}
|
|
893
|
-
const $t = 80;
|
|
894
|
-
function Rt({ announcements: t, selectedRepo: n, nowMs: i }) {
|
|
895
|
-
const r = P(null), a = P(!0), s = r.current;
|
|
896
|
-
s && (a.current = s.scrollHeight - s.scrollTop - s.clientHeight < $t);
|
|
897
|
-
const c = [...t].filter((l) => M(l, n)).reverse();
|
|
898
|
-
return Pe(() => {
|
|
899
|
-
a.current && r.current && (r.current.scrollTop = r.current.scrollHeight);
|
|
900
|
-
}, [c.length]), /* @__PURE__ */ o("div", { id: "chat", className: "chat", ref: r, children: c.length === 0 ? /* @__PURE__ */ o("div", { className: "empty", children: "No announcements yet — agents will post here as they coordinate." }) : c.map((l, h) => {
|
|
901
|
-
const d = "msg" + (l.targetAgentName !== null || l.toAdmin ? " msg--targeted" : "") + (l.fromAdmin ? " msg--me" : "");
|
|
902
|
-
return (
|
|
903
|
-
// The feed has no stable id; index is acceptable because the list is
|
|
904
|
-
// append-only oldest->newest and rows are never reordered in place.
|
|
905
|
-
/* @__PURE__ */ m("div", { className: d, children: [
|
|
906
|
-
/* @__PURE__ */ o(
|
|
907
|
-
"div",
|
|
908
|
-
{
|
|
909
|
-
className: "msg__avatar",
|
|
910
|
-
style: { background: B(l.fromAgentName) },
|
|
911
|
-
children: oe(l.fromAgentName)
|
|
912
|
-
}
|
|
913
|
-
),
|
|
914
|
-
/* @__PURE__ */ m("div", { className: "msg__body", children: [
|
|
915
|
-
/* @__PURE__ */ m("div", { className: "msg__head", children: [
|
|
916
|
-
/* @__PURE__ */ o(
|
|
917
|
-
"span",
|
|
918
|
-
{
|
|
919
|
-
className: "msg__who",
|
|
920
|
-
style: { color: B(l.fromAgentName) },
|
|
921
|
-
children: l.fromAgentName
|
|
922
|
-
}
|
|
923
|
-
),
|
|
924
|
-
l.fromHuman ? /* @__PURE__ */ o("span", { className: "msg__human", children: l.fromHuman }) : null,
|
|
925
|
-
l.targetAgentName !== null ? /* @__PURE__ */ o("span", { className: "msg__to", children: `→ @${l.targetAgentName}` }) : l.toAdmin ? /* @__PURE__ */ o("span", { className: "msg__to", children: "→ admin" }) : null,
|
|
926
|
-
/* @__PURE__ */ o("span", { className: "msg__time", children: q(l.createdAt, i) })
|
|
927
|
-
] }),
|
|
928
|
-
/* @__PURE__ */ o("div", { className: "msg__text", children: l.body })
|
|
929
|
-
] })
|
|
930
|
-
] }, h)
|
|
931
|
-
);
|
|
932
|
-
}) });
|
|
933
|
-
}
|
|
934
|
-
const Et = 8;
|
|
935
|
-
function jt({ agents: t, selectedRepo: n, workspaceId: i, onSent: r }) {
|
|
936
|
-
const a = re(), s = P(null), [c, l] = w(""), [h, u] = w([]), [d, f] = w(0), [b, y] = w(null), [v, T] = w(!1), [$, A] = w(!1), k = ht(
|
|
937
|
-
t.map((p) => ({ name: p.name, presence: p.presence, repo: p.repo ?? "" })),
|
|
938
|
-
n
|
|
939
|
-
), R = h.length > 0, E = j(() => {
|
|
940
|
-
u([]), y(null);
|
|
941
|
-
}, []), W = j(
|
|
942
|
-
(p, N) => {
|
|
943
|
-
const S = ut(p, N);
|
|
944
|
-
if (!S) {
|
|
945
|
-
E();
|
|
946
|
-
return;
|
|
947
|
-
}
|
|
948
|
-
const L = S.query.toLowerCase(), D = k.filter((O) => O.toLowerCase().startsWith(L)).slice(0, Et);
|
|
949
|
-
u(D), y({ start: S.start, end: S.end }), f(0);
|
|
950
|
-
},
|
|
951
|
-
[k, E]
|
|
952
|
-
), _ = j(
|
|
953
|
-
(p) => {
|
|
954
|
-
if (!b) return;
|
|
955
|
-
const N = "@" + p + " ", S = c.slice(0, b.start) + N + c.slice(b.end), L = b.start + N.length;
|
|
956
|
-
l(S), E(), requestAnimationFrame(() => {
|
|
957
|
-
const D = s.current;
|
|
958
|
-
D && (D.focus(), D.setSelectionRange(L, L));
|
|
959
|
-
});
|
|
960
|
-
},
|
|
961
|
-
[b, c, E]
|
|
962
|
-
), F = j(
|
|
963
|
-
(p) => {
|
|
964
|
-
var S;
|
|
965
|
-
l(p);
|
|
966
|
-
const N = ((S = s.current) == null ? void 0 : S.selectionStart) ?? p.length;
|
|
967
|
-
W(p, N);
|
|
968
|
-
},
|
|
969
|
-
[W]
|
|
970
|
-
), Y = j(
|
|
971
|
-
(p) => {
|
|
972
|
-
R && (p.key === "ArrowDown" ? (p.preventDefault(), f((N) => (N + 1) % h.length)) : p.key === "ArrowUp" ? (p.preventDefault(), f((N) => (N - 1 + h.length) % h.length)) : p.key === "Enter" || p.key === "Tab" ? (p.preventDefault(), _(h[d])) : p.key === "Escape" && (p.preventDefault(), E()));
|
|
973
|
-
},
|
|
974
|
-
[R, h, d, _, E]
|
|
975
|
-
), V = j(
|
|
976
|
-
async (p) => {
|
|
977
|
-
p.preventDefault();
|
|
978
|
-
const N = c.trim();
|
|
979
|
-
if (!N) return;
|
|
980
|
-
const S = mt(N, k), L = n === null || n === "__all__" ? null : n;
|
|
981
|
-
T(!0), A(!1);
|
|
982
|
-
try {
|
|
983
|
-
const D = { body: N, targetAgentName: S, repo: L };
|
|
984
|
-
await (i !== void 0 ? a.announceTo(i, D) : a.announce(D)), l(""), E(), await r();
|
|
985
|
-
} catch {
|
|
986
|
-
A(!0);
|
|
987
|
-
} finally {
|
|
988
|
-
T(!1);
|
|
989
|
-
}
|
|
990
|
-
},
|
|
991
|
-
[c, k, n, i, a, E, r]
|
|
992
|
-
);
|
|
993
|
-
return /* @__PURE__ */ m("div", { className: "composer", children: [
|
|
994
|
-
/* @__PURE__ */ o(
|
|
995
|
-
"div",
|
|
996
|
-
{
|
|
997
|
-
id: "mention-pop",
|
|
998
|
-
className: "mention-pop",
|
|
999
|
-
role: "listbox",
|
|
1000
|
-
"aria-label": "Agents to mention",
|
|
1001
|
-
hidden: !R,
|
|
1002
|
-
children: h.map((p, N) => /* @__PURE__ */ m(
|
|
1003
|
-
"button",
|
|
1004
|
-
{
|
|
1005
|
-
id: `mention-opt-${N}`,
|
|
1006
|
-
type: "button",
|
|
1007
|
-
role: "option",
|
|
1008
|
-
"aria-selected": N === d,
|
|
1009
|
-
className: "mention-mi" + (N === d ? " on" : ""),
|
|
1010
|
-
onMouseDown: (S) => {
|
|
1011
|
-
S.preventDefault(), _(p);
|
|
1012
|
-
},
|
|
1013
|
-
children: [
|
|
1014
|
-
/* @__PURE__ */ o("div", { className: "ma", style: { background: B(p) }, children: oe(p) }),
|
|
1015
|
-
/* @__PURE__ */ o("span", { children: p })
|
|
1016
|
-
]
|
|
1017
|
-
},
|
|
1018
|
-
p
|
|
1019
|
-
))
|
|
1020
|
-
}
|
|
1021
|
-
),
|
|
1022
|
-
/* @__PURE__ */ m(
|
|
1023
|
-
"form",
|
|
1024
|
-
{
|
|
1025
|
-
id: "chat-form",
|
|
1026
|
-
className: "chat-form",
|
|
1027
|
-
onSubmit: (p) => {
|
|
1028
|
-
V(p);
|
|
1029
|
-
},
|
|
1030
|
-
children: [
|
|
1031
|
-
/* @__PURE__ */ o(
|
|
1032
|
-
"input",
|
|
1033
|
-
{
|
|
1034
|
-
id: "chat-input",
|
|
1035
|
-
className: "chat-input",
|
|
1036
|
-
type: "text",
|
|
1037
|
-
autoComplete: "off",
|
|
1038
|
-
"aria-label": "Message the team",
|
|
1039
|
-
placeholder: "Message the team… use @name to direct it",
|
|
1040
|
-
role: "combobox",
|
|
1041
|
-
"aria-expanded": R,
|
|
1042
|
-
"aria-controls": "mention-pop",
|
|
1043
|
-
"aria-autocomplete": "list",
|
|
1044
|
-
"aria-activedescendant": R ? `mention-opt-${d}` : void 0,
|
|
1045
|
-
ref: s,
|
|
1046
|
-
value: c,
|
|
1047
|
-
onChange: (p) => F(p.target.value),
|
|
1048
|
-
onKeyDown: Y
|
|
1049
|
-
}
|
|
1050
|
-
),
|
|
1051
|
-
/* @__PURE__ */ o("button", { id: "chat-send", className: "chat-send", type: "submit", disabled: v, children: "Send" })
|
|
1052
|
-
]
|
|
1053
|
-
}
|
|
1054
|
-
),
|
|
1055
|
-
$ ? /* @__PURE__ */ o("div", { className: "chat__note", role: "status", children: "send failed — retry" }) : null
|
|
1056
|
-
] });
|
|
1057
|
-
}
|
|
1058
|
-
function ye({
|
|
1059
|
-
title: t = "No workspace yet",
|
|
1060
|
-
children: n,
|
|
1061
|
-
onGetStarted: i,
|
|
1062
|
-
ctaLabel: r = "Go to Config"
|
|
1063
|
-
}) {
|
|
1064
|
-
const a = Ne();
|
|
1065
|
-
return /* @__PURE__ */ m("section", { className: "shepherd-empty-state", "aria-labelledby": a, children: [
|
|
1066
|
-
/* @__PURE__ */ o("h2", { id: a, children: t }),
|
|
1067
|
-
/* @__PURE__ */ o("p", { children: n ?? "Create a workspace or join one with an invite code to get started." }),
|
|
1068
|
-
i && /* @__PURE__ */ o("button", { type: "button", onClick: i, children: r })
|
|
1069
|
-
] });
|
|
1070
|
-
}
|
|
1071
|
-
const Dt = [
|
|
1072
|
-
{ id: "bug", label: "Bug" },
|
|
1073
|
-
{ id: "suggestion", label: "Suggestion" },
|
|
1074
|
-
{ id: "other", label: "Other" }
|
|
1075
|
-
], It = 1500;
|
|
1076
|
-
function xt({ workspaceId: t }) {
|
|
1077
|
-
const n = re(), i = Ne(), [r, a] = w(!1), [s, c] = w("bug"), [l, h] = w(""), [u, d] = w(!1), [f, b] = w(null), [y, v] = w(!1);
|
|
1078
|
-
function T() {
|
|
1079
|
-
a((k) => !k);
|
|
1080
|
-
}
|
|
1081
|
-
function $() {
|
|
1082
|
-
c("bug"), h(""), b(null), v(!1);
|
|
1083
|
-
}
|
|
1084
|
-
async function A() {
|
|
1085
|
-
d(!0), b(null);
|
|
1086
|
-
try {
|
|
1087
|
-
await n.submitFeedback({ type: s, body: l.trim() }, t), v(!0), h(""), setTimeout(() => {
|
|
1088
|
-
a(!1), $();
|
|
1089
|
-
}, It);
|
|
1090
|
-
} catch (k) {
|
|
1091
|
-
b(ot(k));
|
|
1092
|
-
} finally {
|
|
1093
|
-
d(!1);
|
|
1094
|
-
}
|
|
1095
|
-
}
|
|
1096
|
-
return /* @__PURE__ */ m("div", { className: "shepherd-feedback", children: [
|
|
1097
|
-
/* @__PURE__ */ o(
|
|
1098
|
-
"button",
|
|
1099
|
-
{
|
|
1100
|
-
type: "button",
|
|
1101
|
-
className: "shepherd-feedback__trigger",
|
|
1102
|
-
onClick: T,
|
|
1103
|
-
"aria-expanded": r,
|
|
1104
|
-
children: "Feedback"
|
|
1105
|
-
}
|
|
1106
|
-
),
|
|
1107
|
-
r && /* @__PURE__ */ m(
|
|
1108
|
-
"section",
|
|
1109
|
-
{
|
|
1110
|
-
className: "shepherd-feedback__panel",
|
|
1111
|
-
"aria-labelledby": i,
|
|
1112
|
-
children: [
|
|
1113
|
-
/* @__PURE__ */ o("h3", { id: i, children: "Give feedback" }),
|
|
1114
|
-
y ? /* @__PURE__ */ o("p", { role: "status", children: "Thanks! Your feedback was sent." }) : /* @__PURE__ */ m(H, { children: [
|
|
1115
|
-
/* @__PURE__ */ o("div", { className: "shepherd-feedback__types", children: Dt.map((k) => /* @__PURE__ */ o(
|
|
1116
|
-
"button",
|
|
1117
|
-
{
|
|
1118
|
-
type: "button",
|
|
1119
|
-
"aria-pressed": s === k.id,
|
|
1120
|
-
onClick: () => c(k.id),
|
|
1121
|
-
children: k.label
|
|
1122
|
-
},
|
|
1123
|
-
k.id
|
|
1124
|
-
)) }),
|
|
1125
|
-
/* @__PURE__ */ o(
|
|
1126
|
-
"textarea",
|
|
1127
|
-
{
|
|
1128
|
-
"aria-label": "Feedback",
|
|
1129
|
-
placeholder: "What's on your mind?",
|
|
1130
|
-
value: l,
|
|
1131
|
-
onChange: (k) => h(k.target.value)
|
|
1132
|
-
}
|
|
1133
|
-
),
|
|
1134
|
-
f && /* @__PURE__ */ o("p", { role: "alert", children: f }),
|
|
1135
|
-
/* @__PURE__ */ o(
|
|
1136
|
-
"button",
|
|
1137
|
-
{
|
|
1138
|
-
type: "button",
|
|
1139
|
-
onClick: () => void A(),
|
|
1140
|
-
disabled: l.trim() === "" || u,
|
|
1141
|
-
children: "Submit"
|
|
1142
|
-
}
|
|
1143
|
-
)
|
|
1144
|
-
] })
|
|
1145
|
-
]
|
|
1146
|
-
}
|
|
1147
|
-
)
|
|
1148
|
-
] });
|
|
1149
|
-
}
|
|
1150
|
-
const ke = "shepherd.tab", Z = "shepherd.repo", J = 10, Mt = {
|
|
1151
|
-
live: { text: "live", kind: "ok" },
|
|
1152
|
-
reconnecting: { text: "reconnecting…", kind: "warn" },
|
|
1153
|
-
// app.js cleared the token and re-prompted on 401; in the auth-agnostic port
|
|
1154
|
-
// the injected client's onUnauthorized owns any token handling, so the board
|
|
1155
|
-
// only surfaces the rejected state.
|
|
1156
|
-
unauthorized: { text: "token rejected", kind: "error" }
|
|
1157
|
-
};
|
|
1158
|
-
function _e(t) {
|
|
1159
|
-
try {
|
|
1160
|
-
return localStorage.getItem(t);
|
|
1161
|
-
} catch {
|
|
1162
|
-
return null;
|
|
1163
|
-
}
|
|
1164
|
-
}
|
|
1165
|
-
function Q(t, n) {
|
|
1166
|
-
try {
|
|
1167
|
-
localStorage.setItem(t, n);
|
|
1168
|
-
} catch {
|
|
1169
|
-
}
|
|
1170
|
-
}
|
|
1171
|
-
function Lt(t, n, i) {
|
|
1172
|
-
const r = Ce(n.tasks);
|
|
1173
|
-
let a = t;
|
|
1174
|
-
if (a === null && r.length >= 2 && (a = he(n.tasks)), a !== null && a !== "__all__" && !r.includes(a) && (a = "__all__"), i && a !== null && a !== "__all__") {
|
|
1175
|
-
const s = n.tasks.some(
|
|
1176
|
-
(l) => l.status === "active" && l.repo === a
|
|
1177
|
-
), c = n.tasks.some((l) => l.status === "active");
|
|
1178
|
-
!s && c && (a = he(n.tasks));
|
|
1179
|
-
}
|
|
1180
|
-
return a;
|
|
1181
|
-
}
|
|
1182
|
-
function Pt(t) {
|
|
1183
|
-
const n = {}, i = (r, a) => {
|
|
1184
|
-
const s = n[r] ?? (n[r] = { active: 0, done: 0 });
|
|
1185
|
-
s[a]++;
|
|
1186
|
-
};
|
|
1187
|
-
for (const r of t.tasks) {
|
|
1188
|
-
const a = r.status === "active" ? "active" : "done";
|
|
1189
|
-
i(r.repo, a), i("__all__", a);
|
|
1190
|
-
}
|
|
1191
|
-
return n;
|
|
1192
|
-
}
|
|
1193
|
-
function qt({
|
|
1194
|
-
workspaceId: t,
|
|
1195
|
-
config: n,
|
|
1196
|
-
hasWorkspace: i
|
|
1197
|
-
} = {}) {
|
|
1198
|
-
const r = n != null, a = i === !1, { snapshot: s, status: c, lastUpdatedMs: l, refresh: h } = dt({
|
|
1199
|
-
workspaceId: t,
|
|
1200
|
-
// A no-workspace board has nothing to poll; keep it off the hub.
|
|
1201
|
-
enabled: !a
|
|
1202
|
-
}), [u, d] = w(() => {
|
|
1203
|
-
if (r && a) return "config";
|
|
1204
|
-
const g = _e(ke);
|
|
1205
|
-
return g === "chat" ? "chat" : g === "config" && r ? "config" : "tasks";
|
|
1206
|
-
}), f = r ? [
|
|
1207
|
-
{ id: "tasks", label: "Tasks" },
|
|
1208
|
-
{ id: "chat", label: "Chat" },
|
|
1209
|
-
{ id: "config", label: "Config" }
|
|
1210
|
-
] : [
|
|
1211
|
-
{ id: "tasks", label: "Tasks" },
|
|
1212
|
-
{ id: "chat", label: "Chat" }
|
|
1213
|
-
], b = P([]), y = j(
|
|
1214
|
-
(g, x) => {
|
|
1215
|
-
var le;
|
|
1216
|
-
const G = f.length - 1;
|
|
1217
|
-
let I = null;
|
|
1218
|
-
switch (g.key) {
|
|
1219
|
-
case "ArrowRight":
|
|
1220
|
-
I = x === G ? 0 : x + 1;
|
|
1221
|
-
break;
|
|
1222
|
-
case "ArrowLeft":
|
|
1223
|
-
I = x === 0 ? G : x - 1;
|
|
1224
|
-
break;
|
|
1225
|
-
case "Home":
|
|
1226
|
-
I = 0;
|
|
1227
|
-
break;
|
|
1228
|
-
case "End":
|
|
1229
|
-
I = G;
|
|
1230
|
-
break;
|
|
1231
|
-
default:
|
|
1232
|
-
return;
|
|
1233
|
-
}
|
|
1234
|
-
g.preventDefault();
|
|
1235
|
-
const ce = f[I];
|
|
1236
|
-
ce && (R(ce.id), (le = b.current[I]) == null || le.focus());
|
|
1237
|
-
},
|
|
1238
|
-
// `tabs` is rebuilt each render but its identity only matters by length,
|
|
1239
|
-
// which is stable for a given `hasConfig`; `onTab` is stable.
|
|
1240
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1241
|
-
[r]
|
|
1242
|
-
), [v, T] = w(
|
|
1243
|
-
() => _e(Z)
|
|
1244
|
-
), [$, A] = w(J), k = P(!0), R = j((g) => {
|
|
1245
|
-
d(g), Q(ke, g);
|
|
1246
|
-
}, []), E = j((g) => {
|
|
1247
|
-
const x = g === null ? "__all__" : g;
|
|
1248
|
-
T(x), Q(Z, x), A(J);
|
|
1249
|
-
}, []), W = j(() => {
|
|
1250
|
-
A((g) => g + J);
|
|
1251
|
-
}, []), _ = s ? Lt(v, s, k.current) : v;
|
|
1252
|
-
ne(() => {
|
|
1253
|
-
s && (k.current = !1, _ !== v && (T(_), _ !== null && _ !== "__all__" && Q(Z, _)));
|
|
1254
|
-
}, [s, _, v]);
|
|
1255
|
-
const F = s ? Date.parse(s.serverTime) : Date.now(), Y = s ? Ce(s.tasks) : [], V = s ? Pt(s) : {}, p = s ? s.agents.filter(
|
|
1256
|
-
(g) => g.presence === "live" && M({ repo: g.repo ?? "" }, _)
|
|
1257
|
-
).length : 0, N = s ? s.tasks.filter((g) => g.status === "active" && M(g, _)).length : 0, S = Mt[c], L = l === null ? "" : `updated ${Math.floor((Date.now() - l) / 1e3)}s ago`, D = (s == null ? void 0 : s.agents) ?? [], O = (s == null ? void 0 : s.tasks) ?? [], Re = (s == null ? void 0 : s.announcements) ?? [], Ee = O.filter(
|
|
1258
|
-
(g) => g.status === "active" && M(g, _)
|
|
1259
|
-
).length, je = O.filter(
|
|
1260
|
-
(g) => g.status !== "active" && M(g, _)
|
|
1261
|
-
).length, ie = !a && u !== "config";
|
|
1262
|
-
return /* @__PURE__ */ m("div", { id: "board", children: [
|
|
1263
|
-
/* @__PURE__ */ m("header", { children: [
|
|
1264
|
-
/* @__PURE__ */ o("h1", { className: "brand", style: { margin: 0, font: "inherit" }, children: "Shepherd" }),
|
|
1265
|
-
ie && /* @__PURE__ */ m(H, { children: [
|
|
1266
|
-
/* @__PURE__ */ o(
|
|
1267
|
-
yt,
|
|
1268
|
-
{
|
|
1269
|
-
repos: Y,
|
|
1270
|
-
counts: V,
|
|
1271
|
-
selected: _,
|
|
1272
|
-
onSelect: E
|
|
1273
|
-
}
|
|
1274
|
-
),
|
|
1275
|
-
/* @__PURE__ */ m("span", { className: "vitals", children: [
|
|
1276
|
-
/* @__PURE__ */ o("b", { id: "vitals-online", children: p }),
|
|
1277
|
-
" online · ",
|
|
1278
|
-
/* @__PURE__ */ o("b", { id: "vitals-active", children: N }),
|
|
1279
|
-
" active"
|
|
1280
|
-
] })
|
|
1281
|
-
] }),
|
|
1282
|
-
/* @__PURE__ */ o("span", { className: "grow" }),
|
|
1283
|
-
ie && /* @__PURE__ */ m(H, { children: [
|
|
1284
|
-
/* @__PURE__ */ o(
|
|
1285
|
-
"span",
|
|
1286
|
-
{
|
|
1287
|
-
id: "status",
|
|
1288
|
-
className: "status" + (S.kind ? ` status--${S.kind}` : ""),
|
|
1289
|
-
children: S.text
|
|
1290
|
-
}
|
|
1291
|
-
),
|
|
1292
|
-
/* @__PURE__ */ o("span", { id: "freshness", className: "freshness", children: L })
|
|
1293
|
-
] }),
|
|
1294
|
-
/* @__PURE__ */ o("nav", { className: "tabs", role: "tablist", "aria-label": "Shepherd views", children: f.map(({ id: g, label: x }, G) => /* @__PURE__ */ o(
|
|
1295
|
-
"button",
|
|
1296
|
-
{
|
|
1297
|
-
ref: (I) => {
|
|
1298
|
-
b.current[G] = I;
|
|
1299
|
-
},
|
|
1300
|
-
className: "tab" + (u === g ? " tab--active" : ""),
|
|
1301
|
-
"data-tab": g,
|
|
1302
|
-
type: "button",
|
|
1303
|
-
role: "tab",
|
|
1304
|
-
id: `tab-${g}`,
|
|
1305
|
-
"aria-controls": `panel-${g}`,
|
|
1306
|
-
"aria-selected": u === g,
|
|
1307
|
-
tabIndex: u === g ? 0 : -1,
|
|
1308
|
-
onClick: () => R(g),
|
|
1309
|
-
onKeyDown: (I) => y(I, G),
|
|
1310
|
-
children: x
|
|
1311
|
-
},
|
|
1312
|
-
g
|
|
1313
|
-
)) })
|
|
1314
|
-
] }),
|
|
1315
|
-
/* @__PURE__ */ o(
|
|
1316
|
-
"section",
|
|
1317
|
-
{
|
|
1318
|
-
id: "panel-tasks",
|
|
1319
|
-
role: "tabpanel",
|
|
1320
|
-
"aria-labelledby": "tab-tasks",
|
|
1321
|
-
hidden: u !== "tasks",
|
|
1322
|
-
children: a ? /* @__PURE__ */ o(ye, { onGetStarted: () => R("config") }) : /* @__PURE__ */ m(H, { children: [
|
|
1323
|
-
/* @__PURE__ */ o(kt, { agents: D, tasks: O, selectedRepo: _ }),
|
|
1324
|
-
/* @__PURE__ */ m("div", { className: "board", children: [
|
|
1325
|
-
/* @__PURE__ */ m("div", { className: "col", children: [
|
|
1326
|
-
/* @__PURE__ */ m("div", { className: "colhead", children: [
|
|
1327
|
-
/* @__PURE__ */ o("h2", { children: "Active" }),
|
|
1328
|
-
/* @__PURE__ */ o("span", { className: "n", id: "active-count", children: Ee })
|
|
1329
|
-
] }),
|
|
1330
|
-
/* @__PURE__ */ o(At, { tasks: O, nowMs: F, selectedRepo: _ })
|
|
1331
|
-
] }),
|
|
1332
|
-
/* @__PURE__ */ o("div", { className: "board__rule" }),
|
|
1333
|
-
/* @__PURE__ */ m("div", { className: "col", children: [
|
|
1334
|
-
/* @__PURE__ */ m("div", { className: "colhead", children: [
|
|
1335
|
-
/* @__PURE__ */ o("h2", { children: "Done" }),
|
|
1336
|
-
/* @__PURE__ */ o("span", { className: "n", id: "done-count", children: je })
|
|
1337
|
-
] }),
|
|
1338
|
-
/* @__PURE__ */ o(
|
|
1339
|
-
Ct,
|
|
1340
|
-
{
|
|
1341
|
-
tasks: O,
|
|
1342
|
-
nowMs: F,
|
|
1343
|
-
selectedRepo: _,
|
|
1344
|
-
doneShown: $,
|
|
1345
|
-
onLoadMore: W
|
|
1346
|
-
}
|
|
1347
|
-
)
|
|
1348
|
-
] })
|
|
1349
|
-
] })
|
|
1350
|
-
] })
|
|
1351
|
-
}
|
|
1352
|
-
),
|
|
1353
|
-
/* @__PURE__ */ o(
|
|
1354
|
-
"section",
|
|
1355
|
-
{
|
|
1356
|
-
id: "panel-chat",
|
|
1357
|
-
role: "tabpanel",
|
|
1358
|
-
"aria-labelledby": "tab-chat",
|
|
1359
|
-
hidden: u !== "chat",
|
|
1360
|
-
children: a ? /* @__PURE__ */ o(ye, { onGetStarted: () => R("config") }) : /* @__PURE__ */ m("div", { className: "chat-wrap", children: [
|
|
1361
|
-
/* @__PURE__ */ o(Rt, { announcements: Re, selectedRepo: _, nowMs: F }),
|
|
1362
|
-
/* @__PURE__ */ o(
|
|
1363
|
-
jt,
|
|
1364
|
-
{
|
|
1365
|
-
agents: D,
|
|
1366
|
-
selectedRepo: _,
|
|
1367
|
-
workspaceId: t,
|
|
1368
|
-
onSent: h
|
|
1369
|
-
}
|
|
1370
|
-
)
|
|
1371
|
-
] })
|
|
1372
|
-
}
|
|
1373
|
-
),
|
|
1374
|
-
r && /* @__PURE__ */ o(
|
|
1375
|
-
"section",
|
|
1376
|
-
{
|
|
1377
|
-
id: "panel-config",
|
|
1378
|
-
role: "tabpanel",
|
|
1379
|
-
"aria-labelledby": "tab-config",
|
|
1380
|
-
hidden: u !== "config",
|
|
1381
|
-
children: n
|
|
1382
|
-
}
|
|
1383
|
-
),
|
|
1384
|
-
/* @__PURE__ */ o(xt, { workspaceId: t })
|
|
1385
|
-
] });
|
|
1386
|
-
}
|
|
1387
|
-
export {
|
|
1388
|
-
qt as D,
|
|
1389
|
-
ye as E,
|
|
1390
|
-
U as S,
|
|
1391
|
-
Wt as a,
|
|
1392
|
-
Ht as c,
|
|
1393
|
-
ot as d,
|
|
1394
|
-
q as f,
|
|
1395
|
-
re as u
|
|
1396
|
-
};
|