@michengai/dsh-automation 0.1.30 → 0.1.32
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/CHANGELOG.md +12 -0
- package/CHANGELOG.zh-CN.md +12 -0
- package/README.md +1 -0
- package/README.zh-CN.md +1 -0
- package/lib/client.js +645 -608
- package/lib/client.js.map +4 -4
- package/lib/index.js +1 -29
- package/lib/types/client/ScheduleRail.d.ts +5 -2
- package/lib/types/client/runtime.d.ts +13 -3
- package/lib/types/client/schedule-overview.d.ts +4 -7
- package/lib/types/client/schedule-rail-model.d.ts +2 -3
- package/lib/types/executor.d.ts +0 -1
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -154,6 +154,19 @@ function buildCreateInput(form, workspaces, models, now = /* @__PURE__ */ new Da
|
|
|
154
154
|
reasoningEffort: form.reasoningEffort === "none" ? null : form.reasoningEffort
|
|
155
155
|
};
|
|
156
156
|
}
|
|
157
|
+
function formatRelativeTime(iso, now, t) {
|
|
158
|
+
const value = Date.parse(iso);
|
|
159
|
+
if (!Number.isFinite(value)) return iso;
|
|
160
|
+
const deltaMinutes = Math.round((value - now.getTime()) / 6e4);
|
|
161
|
+
const abs = Math.abs(deltaMinutes);
|
|
162
|
+
if (abs < 1) return t("time.now");
|
|
163
|
+
const future = deltaMinutes > 0;
|
|
164
|
+
if (abs < 60) return t(future ? "time.inMinute" : "time.minuteAgo", { count: abs });
|
|
165
|
+
const hours = Math.round(abs / 60);
|
|
166
|
+
if (hours < 24) return t(future ? "time.inHour" : "time.hourAgo", { count: hours });
|
|
167
|
+
const days = Math.round(hours / 24);
|
|
168
|
+
return t(future ? "time.inDay" : "time.dayAgo", { count: days });
|
|
169
|
+
}
|
|
157
170
|
function formatSchedule(schedule, t) {
|
|
158
171
|
switch (schedule.kind) {
|
|
159
172
|
case "once":
|
|
@@ -324,102 +337,425 @@ function toLocalInput(iso) {
|
|
|
324
337
|
return new Date(value.getTime() - offset).toISOString().slice(0, 16);
|
|
325
338
|
}
|
|
326
339
|
|
|
327
|
-
// src/
|
|
328
|
-
var
|
|
329
|
-
|
|
330
|
-
|
|
340
|
+
// src/run-title.ts
|
|
341
|
+
var RUN_STAMP_OPTIONS = {
|
|
342
|
+
year: "numeric",
|
|
343
|
+
month: "2-digit",
|
|
344
|
+
day: "2-digit",
|
|
345
|
+
hour: "2-digit",
|
|
346
|
+
minute: "2-digit",
|
|
347
|
+
hourCycle: "h23"
|
|
348
|
+
};
|
|
349
|
+
var zonedRunStampFormatters = /* @__PURE__ */ new Map();
|
|
350
|
+
function runStampFormatter(timeZone) {
|
|
351
|
+
const cached = zonedRunStampFormatters.get(timeZone);
|
|
352
|
+
if (cached !== void 0) return cached;
|
|
353
|
+
const formatter = new Intl.DateTimeFormat("en-CA", { ...RUN_STAMP_OPTIONS, timeZone });
|
|
354
|
+
zonedRunStampFormatters.set(timeZone, formatter);
|
|
355
|
+
return formatter;
|
|
331
356
|
}
|
|
332
|
-
function
|
|
333
|
-
|
|
357
|
+
function formatRunStamp(iso, timeZone) {
|
|
358
|
+
const value = new Date(iso);
|
|
359
|
+
if (Number.isNaN(value.getTime())) return iso;
|
|
360
|
+
if (timeZone === void 0) {
|
|
361
|
+
const date = `${value.getFullYear()}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`;
|
|
362
|
+
const time = `${String(value.getHours()).padStart(2, "0")}:${String(value.getMinutes()).padStart(2, "0")}`;
|
|
363
|
+
return `${date} ${time}`;
|
|
364
|
+
}
|
|
365
|
+
try {
|
|
366
|
+
const parts = runStampFormatter(timeZone).formatToParts(value);
|
|
367
|
+
const part = (type) => parts.find((item) => item.type === type)?.value;
|
|
368
|
+
const [year, month, day, hour, minute] = ["year", "month", "day", "hour", "minute"].map((type) => part(type));
|
|
369
|
+
if ([year, month, day, hour, minute].some((item) => item === void 0)) return iso;
|
|
370
|
+
return `${year}-${month}-${day} ${hour}:${minute}`;
|
|
371
|
+
} catch {
|
|
372
|
+
return iso;
|
|
373
|
+
}
|
|
334
374
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
375
|
+
|
|
376
|
+
// src/client/schedule-rail-model.ts
|
|
377
|
+
var AUTOMATION_SESSION_PREFIX = "dsh-automation-session-";
|
|
378
|
+
var NATIVE_SIDEBAR_TAB_KEY = "dsh-automation.sidebar-tab";
|
|
379
|
+
function groupScheduledSessions(automations, runs) {
|
|
380
|
+
const nameById = /* @__PURE__ */ new Map();
|
|
381
|
+
const timeZoneById = /* @__PURE__ */ new Map();
|
|
382
|
+
for (const item of automations) {
|
|
383
|
+
nameById.set(item.id, item.name);
|
|
384
|
+
if (item.timeZone !== void 0) timeZoneById.set(item.id, item.timeZone);
|
|
385
|
+
}
|
|
386
|
+
for (const run of runs) {
|
|
387
|
+
const stored = (run.automationName || "").trim();
|
|
388
|
+
if (stored !== "" && stored !== run.automationId && !nameById.has(run.automationId)) {
|
|
389
|
+
nameById.set(run.automationId, stored);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
const ids = [];
|
|
393
|
+
const seen = /* @__PURE__ */ new Set();
|
|
394
|
+
for (const item of automations) {
|
|
395
|
+
if (seen.has(item.id)) continue;
|
|
396
|
+
ids.push(item.id);
|
|
397
|
+
seen.add(item.id);
|
|
398
|
+
}
|
|
399
|
+
for (const run of runs) {
|
|
400
|
+
if (run.sessionId === void 0 || run.sessionId === "" || seen.has(run.automationId)) continue;
|
|
401
|
+
ids.push(run.automationId);
|
|
402
|
+
seen.add(run.automationId);
|
|
403
|
+
}
|
|
404
|
+
return ids.map((id) => {
|
|
405
|
+
const name2 = nameById.get(id) ?? id;
|
|
406
|
+
return {
|
|
407
|
+
id,
|
|
408
|
+
name: name2,
|
|
409
|
+
sessions: runs.filter((run) => run.automationId === id && run.sessionId !== void 0 && run.sessionId !== "").slice().sort((left, right) => Date.parse(right.startedAt ?? right.scheduledFor) - Date.parse(left.startedAt ?? left.scheduledFor)).map((run) => ({
|
|
410
|
+
id: run.sessionId,
|
|
411
|
+
running: run.status === "running" || run.status === "queued",
|
|
412
|
+
label: formatRunStamp(run.startedAt ?? run.scheduledFor, timeZoneById.get(id)) + " - " + name2
|
|
413
|
+
}))
|
|
414
|
+
};
|
|
415
|
+
}).filter((group) => group.sessions.length > 0);
|
|
340
416
|
}
|
|
341
|
-
function
|
|
342
|
-
return
|
|
417
|
+
function automationToggleMutation(status) {
|
|
418
|
+
return status === "active" ? "pause" : "resume";
|
|
343
419
|
}
|
|
344
|
-
function
|
|
345
|
-
return
|
|
420
|
+
function deriveTaskOverviewRows(automations) {
|
|
421
|
+
return automations.map((item) => ({
|
|
422
|
+
id: item.id,
|
|
423
|
+
name: item.name,
|
|
424
|
+
status: item.status,
|
|
425
|
+
...item.nextRunAt === void 0 ? {} : { nextRunAt: item.nextRunAt }
|
|
426
|
+
}));
|
|
346
427
|
}
|
|
347
|
-
function
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
] });
|
|
428
|
+
function keepScheduledSessionLink(sessionId, archived, _presentIds) {
|
|
429
|
+
if (sessionId === void 0 || sessionId === "") return false;
|
|
430
|
+
if (archived.has(sessionId)) return false;
|
|
431
|
+
return true;
|
|
352
432
|
}
|
|
353
|
-
function
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
] });
|
|
433
|
+
function scheduledSessionNeedsSnapshotRefresh(sessionId, runs) {
|
|
434
|
+
if (sessionId === void 0 || sessionId === null || sessionId === "") return false;
|
|
435
|
+
if (!sessionId.startsWith(AUTOMATION_SESSION_PREFIX)) return false;
|
|
436
|
+
return !(runs ?? []).some((run) => run.sessionId === sessionId);
|
|
358
437
|
}
|
|
359
|
-
function
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
438
|
+
function collectScheduledSessionIds(runs) {
|
|
439
|
+
const ids = /* @__PURE__ */ new Set();
|
|
440
|
+
for (const run of runs ?? []) {
|
|
441
|
+
const id = run.sessionId;
|
|
442
|
+
if (typeof id === "string" && id !== "") ids.add(id);
|
|
443
|
+
}
|
|
444
|
+
return ids;
|
|
365
445
|
}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
] });
|
|
446
|
+
var AUTOMATION_TITLE_RE = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}/;
|
|
447
|
+
function isAutomationSidebarSession(id, item, scheduledIds = /* @__PURE__ */ new Set()) {
|
|
448
|
+
if (id.startsWith(AUTOMATION_SESSION_PREFIX) || scheduledIds.has(id)) return true;
|
|
449
|
+
const title = String(item?.title ?? item?.displayTitle ?? "");
|
|
450
|
+
return AUTOMATION_TITLE_RE.test(title);
|
|
372
451
|
}
|
|
373
|
-
function
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
452
|
+
function isNativeTaskSession(item, scheduledIds = /* @__PURE__ */ new Set()) {
|
|
453
|
+
if (item === void 0 || item.blank === true) return false;
|
|
454
|
+
if (item.origin === "im" || item.origin === "subagent") return false;
|
|
455
|
+
const id = item.id ?? "";
|
|
456
|
+
if (id.startsWith("im:")) return false;
|
|
457
|
+
if (isAutomationSidebarSession(id, item, scheduledIds)) return false;
|
|
458
|
+
return true;
|
|
378
459
|
}
|
|
379
|
-
function
|
|
380
|
-
|
|
460
|
+
function groupNativeTaskSessions(sessions, workspaces, ungroupedLabel, scheduledIds = /* @__PURE__ */ new Set()) {
|
|
461
|
+
const byId = sessions.byId ?? {};
|
|
462
|
+
const archived = new Set(workspaces?.archivedSessionIds ?? []);
|
|
463
|
+
const assigned = /* @__PURE__ */ new Set();
|
|
464
|
+
const groups = [];
|
|
465
|
+
for (const workspace of workspaces?.items ?? []) {
|
|
466
|
+
const items = (workspace.sessionIds ?? []).map((id) => byId[id]).filter((item) => item !== void 0 && item.id !== void 0 && isNativeTaskSession(item, scheduledIds) && !archived.has(item.id));
|
|
467
|
+
for (const item of items) {
|
|
468
|
+
if (item.id !== void 0) assigned.add(item.id);
|
|
469
|
+
}
|
|
470
|
+
if (items.length > 0) {
|
|
471
|
+
groups.push({
|
|
472
|
+
id: workspace.workspaceId ?? workspace.id ?? workspace.path ?? workspace.title ?? "workspace",
|
|
473
|
+
label: workspace.title || workspace.path || ungroupedLabel,
|
|
474
|
+
sessions: items
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
const ungrouped = (sessions.ids ?? []).map((id) => byId[id]).filter((item) => item !== void 0 && item.id !== void 0 && !assigned.has(item.id) && isNativeTaskSession(item, scheduledIds) && !archived.has(item.id));
|
|
479
|
+
if (ungrouped.length > 0) groups.push({ id: "", label: ungroupedLabel, sessions: ungrouped });
|
|
480
|
+
return groups;
|
|
381
481
|
}
|
|
382
|
-
function
|
|
383
|
-
|
|
482
|
+
function readNativeSidebarTab(raw) {
|
|
483
|
+
if (raw === "channels" || raw === "schedule" || raw === "tasks") return raw;
|
|
484
|
+
return "tasks";
|
|
384
485
|
}
|
|
385
|
-
function
|
|
386
|
-
|
|
486
|
+
function shouldFollowSessionTab(previousCurrent, current) {
|
|
487
|
+
const prev = previousCurrent ?? "";
|
|
488
|
+
const next = current ?? "";
|
|
489
|
+
return next !== "" && prev !== next;
|
|
387
490
|
}
|
|
388
|
-
function
|
|
389
|
-
|
|
491
|
+
function ownedSidebarTabIds(input) {
|
|
492
|
+
const ids = ["tasks"];
|
|
493
|
+
for (const id of input.extraTabIds) {
|
|
494
|
+
if (id === "" || id === "tasks" || id === "schedule" || ids.includes(id)) continue;
|
|
495
|
+
ids.push(id);
|
|
496
|
+
}
|
|
497
|
+
if (input.channelsReady && !ids.includes("channels")) ids.push("channels");
|
|
498
|
+
ids.push("schedule");
|
|
499
|
+
return ids;
|
|
390
500
|
}
|
|
391
|
-
function
|
|
392
|
-
|
|
501
|
+
function resolveVisibleSidebarTab(input) {
|
|
502
|
+
if (input.extraTabIds.includes(input.tab)) return input.tab;
|
|
503
|
+
if (input.tab === "channels" && !input.channelsReady) return "tasks";
|
|
504
|
+
return input.tab;
|
|
393
505
|
}
|
|
394
|
-
function
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
506
|
+
function tabForSessionId(sessionId, scheduledIds) {
|
|
507
|
+
if (sessionId === void 0 || sessionId === null || sessionId === "") return void 0;
|
|
508
|
+
if (scheduledIds !== void 0 ? scheduledIds.has(sessionId) : sessionId.startsWith(AUTOMATION_SESSION_PREFIX)) return "schedule";
|
|
509
|
+
if (sessionId.startsWith("im:")) return "channels";
|
|
510
|
+
return void 0;
|
|
399
511
|
}
|
|
400
|
-
function
|
|
401
|
-
return
|
|
512
|
+
function occupantLooksLikeCodexUi(value) {
|
|
513
|
+
return /dsh-codex-ui|michengai-codex-ui|michengai\.codexUi|codex-ui/i.test(String(value ?? ""));
|
|
402
514
|
}
|
|
403
|
-
function
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
515
|
+
function slotOccupantName(item) {
|
|
516
|
+
const record = item;
|
|
517
|
+
return String(
|
|
518
|
+
record?.options?.locale ?? record?.options?.id ?? record?.options?.name ?? record?.options?.registrant ?? record?.component?.displayName ?? record?.component?.name ?? record?.id ?? record?.name ?? ""
|
|
519
|
+
);
|
|
408
520
|
}
|
|
409
|
-
function
|
|
410
|
-
return
|
|
521
|
+
function hasCodexUiSidebar(entries) {
|
|
522
|
+
return (entries ?? []).some((item) => occupantLooksLikeCodexUi(slotOccupantName(item)));
|
|
411
523
|
}
|
|
412
|
-
|
|
413
|
-
|
|
524
|
+
var taskFilterCache = /* @__PURE__ */ new WeakMap();
|
|
525
|
+
var workspaceFilterCache = /* @__PURE__ */ new WeakMap();
|
|
526
|
+
function scheduledCacheKey(scheduledIds) {
|
|
527
|
+
if (scheduledIds.size === 0) return "";
|
|
528
|
+
return [...scheduledIds].sort().join("\0");
|
|
414
529
|
}
|
|
415
|
-
function
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
530
|
+
function filterTaskSessionState(state, scheduledIds = /* @__PURE__ */ new Set()) {
|
|
531
|
+
const src = state ?? { ids: [], byId: {}, current: null };
|
|
532
|
+
const key = scheduledCacheKey(scheduledIds);
|
|
533
|
+
if (typeof src === "object" && src !== null) {
|
|
534
|
+
const hit = taskFilterCache.get(src);
|
|
535
|
+
if (hit !== void 0 && hit.key === key) return hit.result;
|
|
536
|
+
}
|
|
537
|
+
const ids = (src.ids ?? []).filter((id) => {
|
|
538
|
+
const value = String(id);
|
|
539
|
+
return !value.startsWith("im:") && !isAutomationSidebarSession(value, src.byId?.[value], scheduledIds);
|
|
540
|
+
});
|
|
541
|
+
const unchanged = ids.length === (src.ids ?? []).length;
|
|
542
|
+
const result = unchanged ? src : { ...src, ids, byId: Object.fromEntries(ids.map((id) => [id, src.byId?.[id]]).filter((entry) => entry[1] !== void 0)) };
|
|
543
|
+
if (typeof src === "object" && src !== null) taskFilterCache.set(src, { key, result });
|
|
544
|
+
return result;
|
|
420
545
|
}
|
|
421
|
-
function
|
|
422
|
-
|
|
546
|
+
function openScheduledSession(id, openRuntime, openHost) {
|
|
547
|
+
if (id === "") return false;
|
|
548
|
+
const attempts = id.startsWith(AUTOMATION_SESSION_PREFIX) || id.startsWith("im:") ? [openRuntime, openHost] : [openHost, openRuntime];
|
|
549
|
+
for (const attempt of attempts) {
|
|
550
|
+
if (typeof attempt !== "function") continue;
|
|
551
|
+
try {
|
|
552
|
+
attempt(id);
|
|
553
|
+
return true;
|
|
554
|
+
} catch {
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
return false;
|
|
558
|
+
}
|
|
559
|
+
async function ensureOpenScheduledSession(input) {
|
|
560
|
+
const id = input.id.trim();
|
|
561
|
+
if (id === "") return false;
|
|
562
|
+
await input.adopt?.(id).catch(() => void 0);
|
|
563
|
+
const listed = () => input.listed?.(id) === true;
|
|
564
|
+
if (!listed() && input.refresh !== void 0) {
|
|
565
|
+
await input.refresh().catch(() => void 0);
|
|
566
|
+
}
|
|
567
|
+
if (openScheduledSession(id, input.openRuntime, input.openHost)) return true;
|
|
568
|
+
if (input.refresh !== void 0) {
|
|
569
|
+
await input.refresh().catch(() => void 0);
|
|
570
|
+
}
|
|
571
|
+
return openScheduledSession(id, input.openRuntime, input.openHost);
|
|
572
|
+
}
|
|
573
|
+
function isHiddenSidebarSessionId(id, scheduledIds = /* @__PURE__ */ new Set()) {
|
|
574
|
+
return id.startsWith("im:") || isAutomationSidebarSession(id, void 0, scheduledIds);
|
|
575
|
+
}
|
|
576
|
+
function filterWorkspaceListState(state, scheduledIds = /* @__PURE__ */ new Set()) {
|
|
577
|
+
const src = state ?? { items: [], archivedSessionIds: [] };
|
|
578
|
+
const key = scheduledCacheKey(scheduledIds);
|
|
579
|
+
if (typeof src === "object" && src !== null) {
|
|
580
|
+
const hit = workspaceFilterCache.get(src);
|
|
581
|
+
if (hit !== void 0 && hit.key === key) return hit.result;
|
|
582
|
+
}
|
|
583
|
+
let changed = false;
|
|
584
|
+
const items = (src.items ?? []).map((workspace) => {
|
|
585
|
+
const sessionIds = (workspace.sessionIds ?? []).filter((sid) => !isHiddenSidebarSessionId(String(sid), scheduledIds));
|
|
586
|
+
if (sessionIds.length !== (workspace.sessionIds ?? []).length) {
|
|
587
|
+
changed = true;
|
|
588
|
+
return { ...workspace, sessionIds };
|
|
589
|
+
}
|
|
590
|
+
return workspace;
|
|
591
|
+
});
|
|
592
|
+
const result = changed ? { ...src, items } : src;
|
|
593
|
+
if (typeof src === "object" && src !== null) workspaceFilterCache.set(src, { key, result });
|
|
594
|
+
return result;
|
|
595
|
+
}
|
|
596
|
+
function wrapperFlags(component) {
|
|
597
|
+
if (component === void 0 || component === null || typeof component !== "function" && typeof component !== "object") return {};
|
|
598
|
+
return component;
|
|
599
|
+
}
|
|
600
|
+
function isOwnAutomationWrapper(component) {
|
|
601
|
+
return wrapperFlags(component).__dshAutomationWrapped === true;
|
|
602
|
+
}
|
|
603
|
+
function resolveOfficialTreeComponent(component) {
|
|
604
|
+
const seen = /* @__PURE__ */ new Set();
|
|
605
|
+
let current = component;
|
|
606
|
+
while (current !== void 0 && current !== null && !seen.has(current)) {
|
|
607
|
+
seen.add(current);
|
|
608
|
+
const flags = wrapperFlags(current);
|
|
609
|
+
const next = flags.__dshAutomationOriginal ?? flags.__imConnectOriginal;
|
|
610
|
+
if (next !== void 0 && next !== current) {
|
|
611
|
+
current = next;
|
|
612
|
+
continue;
|
|
613
|
+
}
|
|
614
|
+
if (flags.__dshAutomationWrapped === true || flags.__imConnectWrapped === true) return void 0;
|
|
615
|
+
return current;
|
|
616
|
+
}
|
|
617
|
+
return void 0;
|
|
618
|
+
}
|
|
619
|
+
function isAutomationWorkspaceWrapper(item) {
|
|
620
|
+
const record = item;
|
|
621
|
+
const id = String(record?.options?.id ?? "");
|
|
622
|
+
const name2 = String(record?.component?.displayName ?? record?.component?.name ?? "");
|
|
623
|
+
return id === "dsh-automation-native-switcher" || id === "dsh-automation-wrap-bump" || name2 === "AutomationNativeWorkspaceShell" || name2 === "AutomationWrapBump" || isOwnAutomationWrapper(record?.component);
|
|
624
|
+
}
|
|
625
|
+
function pickWrappableWorkspacesEntry(entries) {
|
|
626
|
+
for (const item of entries) {
|
|
627
|
+
const record = item;
|
|
628
|
+
if (record?.component === void 0) continue;
|
|
629
|
+
if (isAutomationWorkspaceWrapper(item)) continue;
|
|
630
|
+
return item;
|
|
631
|
+
}
|
|
632
|
+
return void 0;
|
|
633
|
+
}
|
|
634
|
+
function applyWorkspaceBrowserQuery(groups, query, sort, groupMode = "workspace") {
|
|
635
|
+
const needle = query.trim().toLocaleLowerCase();
|
|
636
|
+
const filtered = groups.map((group) => {
|
|
637
|
+
if (needle === "") return group;
|
|
638
|
+
if (group.name.toLocaleLowerCase().includes(needle)) return group;
|
|
639
|
+
const sessions = group.sessions.filter((session) => `${session.title ?? ""} ${session.label ?? ""}`.toLocaleLowerCase().includes(needle));
|
|
640
|
+
return { ...group, sessions };
|
|
641
|
+
}).filter((group) => group.sessions.length > 0 || needle !== "" && group.name.toLocaleLowerCase().includes(needle));
|
|
642
|
+
if (groupMode === "list") {
|
|
643
|
+
const sessions = filtered.flatMap((group) => [...group.sessions]);
|
|
644
|
+
if (sort === "time") sessions.sort((left, right) => sessionTime(right) - sessionTime(left));
|
|
645
|
+
return sessions.length === 0 ? [] : [{ ...filtered[0], name: "", sessions }];
|
|
646
|
+
}
|
|
647
|
+
if (sort === "manual") return filtered;
|
|
648
|
+
return [...filtered].sort((left, right) => latestSessionTime(right) - latestSessionTime(left));
|
|
649
|
+
}
|
|
650
|
+
function sessionTime(session) {
|
|
651
|
+
const ts = Date.parse(session.updatedAt ?? "");
|
|
652
|
+
return Number.isFinite(ts) ? ts : 0;
|
|
653
|
+
}
|
|
654
|
+
function latestSessionTime(group) {
|
|
655
|
+
let latest = 0;
|
|
656
|
+
for (const session of group.sessions) {
|
|
657
|
+
const ts = sessionTime(session);
|
|
658
|
+
if (ts > latest) latest = ts;
|
|
659
|
+
}
|
|
660
|
+
return latest;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// src/client/icons.tsx
|
|
664
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
665
|
+
function IconFrame({ children, ...props }) {
|
|
666
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", width: "18", height: "18", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", ...props, children });
|
|
667
|
+
}
|
|
668
|
+
function PlusIcon(props) {
|
|
669
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconFrame, { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 5v14M5 12h14" }) });
|
|
670
|
+
}
|
|
671
|
+
function RefreshIcon(props) {
|
|
672
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(IconFrame, { ...props, children: [
|
|
673
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M19 7v5h-5" }),
|
|
674
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M18.1 15.5A7.5 7.5 0 1 1 19 12" })
|
|
675
|
+
] });
|
|
676
|
+
}
|
|
677
|
+
function PlayIcon(props) {
|
|
678
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 16 16", width: 16, height: 16, fill: "none", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M4.6 3.4 11.7 8l-7.1 4.6V3.4Z", fill: "currentColor", stroke: "currentColor", strokeWidth: "1.6", strokeLinejoin: "round" }) });
|
|
679
|
+
}
|
|
680
|
+
function TrashIcon(props) {
|
|
681
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FillIcon, { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M14.478 4.841 14.214 10.115c-.104 2.072-.147 2.896-.827 3.846a3.53 3.53 0 0 1-1.044.993c-.519.333-1.101.478-1.784.546-.671.067-1.509.066-2.559.066s-1.887.001-2.558-.066c-.683-.068-1.266-.213-1.784-.546a3.53 3.53 0 0 1-1.044-.993c-.681-.95-.724-1.774-.828-3.846L1.522 4.841l1.368-.068.263 5.273c.109 2.176.171 2.556.573 3.117a2.16 2.16 0 0 0 .673.64c.263.169.603.277 1.179.334.587.059 1.345.06 2.422.06s1.834-.001 2.422-.06c.575-.057.916-.165 1.179-.335.262-.168.49-.386.672-.64.402-.56.464-.94.573-3.116l.263-5.273 1.369.068ZM5.43 6.228h1.37v5.163H5.43V6.228Zm3.77 0h1.37v5.163H9.2V6.228ZM8.536.434c.644 0 1.116-.007 1.56.137.14.045.276.101.406.168.416.212.745.552 1.2 1.007l.796.795h2.876v1.37H.626V2.541h2.876l.796-.795c.456-.455.784-.795 1.2-1.007.13-.067.266-.123.405-.168C6.348.427 6.82.434 7.464.434h1.072Zm-1.072 1.37c-.732 0-.948.008-1.138.07a2.2 2.2 0 0 0-.206.085c-.156.08-.296.204-.678.583h5.117c-.382-.379-.522-.503-.679-.583a2.2 2.2 0 0 0-.205-.085c-.191-.062-.406-.07-1.138-.07H7.464Z" }) });
|
|
682
|
+
}
|
|
683
|
+
function ShieldIcon(props) {
|
|
684
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(IconFrame, { ...props, children: [
|
|
685
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 3.8 19 6v5.1c0 4.3-2.6 7.4-7 9.1-4.4-1.7-7-4.8-7-9.1V6l7-2.2Z" }),
|
|
686
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m9.4 12 1.7 1.7 3.7-4" })
|
|
687
|
+
] });
|
|
688
|
+
}
|
|
689
|
+
function CalendarIcon(props) {
|
|
690
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(IconFrame, { ...props, children: [
|
|
691
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "4", y: "5.5", width: "16", height: "14", rx: "2" }),
|
|
692
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M8 3.8v3.4M16 3.8v3.4M4 9.5h16" })
|
|
693
|
+
] });
|
|
694
|
+
}
|
|
695
|
+
function MoreIcon(props) {
|
|
696
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(IconFrame, { ...props, children: [
|
|
697
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "6", cy: "12", r: "1.2", fill: "currentColor" }),
|
|
698
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "1.2", fill: "currentColor" }),
|
|
699
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "18", cy: "12", r: "1.2", fill: "currentColor" })
|
|
700
|
+
] });
|
|
701
|
+
}
|
|
702
|
+
function InfoIcon(props) {
|
|
703
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(IconFrame, { ...props, children: [
|
|
704
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "8.25" }),
|
|
705
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 10.4V16" }),
|
|
706
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 7.6h.01" })
|
|
707
|
+
] });
|
|
708
|
+
}
|
|
709
|
+
function ClockIcon(props) {
|
|
710
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(IconFrame, { ...props, children: [
|
|
711
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "8.25" }),
|
|
712
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 7.6v4.6l3 1.8" })
|
|
713
|
+
] });
|
|
714
|
+
}
|
|
715
|
+
function ChatIcon(props) {
|
|
716
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconFrame, { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M5.5 6.5h13v9.2H9.2L5.5 18.8V6.5Z" }) });
|
|
717
|
+
}
|
|
718
|
+
function GithubIcon(props) {
|
|
719
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 16 16", width: 16, height: 16, "aria-hidden": "true", focusable: "false", ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M8 0a8 8 0 0 0-2.53 15.59c.4.074.547-.173.547-.385 0-.19-.007-.693-.01-1.36-2.226.484-2.695-1.073-2.695-1.073-.364-.924-.89-1.17-.89-1.17-.726-.496.055-.486.055-.486.803.056 1.225.824 1.225.824.714 1.223 1.872.87 2.328.665.072-.517.28-.87.508-1.07-1.777-.202-3.645-.888-3.645-3.956 0-.874.31-1.588.823-2.148-.083-.202-.357-1.017.078-2.12 0 0 .672-.215 2.2.82A7.65 7.65 0 0 1 8 4.8c.68.003 1.365.092 2.004.27 1.527-1.035 2.197-.82 2.197-.82.437 1.103.162 1.918.08 2.12.513.56.822 1.274.822 2.148 0 3.076-1.872 3.752-3.654 3.95.288.248.544.735.544 1.482 0 1.07-.01 1.932-.01 2.195 0 .214.144.463.55.384A8.001 8.001 0 0 0 8 0Z" }) });
|
|
720
|
+
}
|
|
721
|
+
function FolderIcon(props) {
|
|
722
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconFrame, { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M4 7.2h6.1l1.7 1.8H20V18H4V7.2Z" }) });
|
|
723
|
+
}
|
|
724
|
+
function SparkleIcon(props) {
|
|
725
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconFrame, { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 3.6 13.3 8.7 18.4 10 13.3 11.3 12 16.4 10.7 11.3 5.6 10 10.7 8.7 12 3.6Z" }) });
|
|
726
|
+
}
|
|
727
|
+
function FillIcon({ children, width = 16, height = 16 }) {
|
|
728
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 16 16", width, height, fill: "none", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", children });
|
|
729
|
+
}
|
|
730
|
+
function CloseOutlineIcon(props) {
|
|
731
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(FillIcon, { ...props, children: [
|
|
732
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M14.1168 13.197L13.197 14.1167L1.8833 2.80303L2.80309 1.88324L14.1168 13.197Z" }),
|
|
733
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M13.197 1.88326L14.1168 2.80305L2.80309 14.1168L1.8833 13.197L13.197 1.88326Z" })
|
|
734
|
+
] });
|
|
735
|
+
}
|
|
736
|
+
function CheckOutlineIcon(props) {
|
|
737
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FillIcon, { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M15.0498 3.92579L8.49512 12.3818C8.25774 12.6881 8.04517 12.9645 7.84668 13.1689C7.63957 13.3823 7.38732 13.5841 7.04492 13.6719C6.86373 13.7183 6.6757 13.7346 6.48926 13.7197C6.13666 13.6915 5.8528 13.5355 5.6123 13.3604C5.38201 13.1926 5.12573 12.9567 4.83984 12.6953L1.03125 9.21289L1.96875 8.1875L5.77734 11.6699C6.08684 11.9529 6.27773 12.1249 6.43066 12.2363C6.50183 12.2882 6.54699 12.3135 6.57324 12.3252C6.58525 12.3305 6.59269 12.3322 6.5957 12.333C6.59802 12.3336 6.59961 12.334 6.59961 12.334C6.63317 12.3367 6.66758 12.3335 6.7002 12.3252C6.7002 12.3252 6.70211 12.3251 6.7041 12.3242C6.70698 12.3229 6.71348 12.319 6.72461 12.3115C6.74849 12.2956 6.78843 12.2642 6.84961 12.2012C6.98138 12.0654 7.13957 11.8628 7.39648 11.5313L13.9502 3.07422L15.0498 3.92579Z" }) });
|
|
738
|
+
}
|
|
739
|
+
function SearchOutlineIcon(props) {
|
|
740
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(FillIcon, { ...props, children: [
|
|
741
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M11.894845 6.647401C11.894845 3.725463 9.534486 1.356779 6.623219 1.35657C3.711786 1.35657 1.351635 3.725338 1.351635 6.647401C1.351843 9.569296 3.711911 11.938273 6.623219 11.938273C9.534361 11.938064 11.894637 9.569171 11.894845 6.647401ZM13.245462 6.647401C13.245254 10.317935 10.280401 13.293613 6.623219 13.293821C2.965871 13.293821 0.000204 10.31806 0 6.647401C0 2.976574 2.965746 0 6.623219 0C10.280526 0.000205 13.245462 2.9767 13.245462 6.647401Z" }),
|
|
742
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M16.000417 15.041079L15.044449 16.000433L11.530434 12.473588L12.486298 11.514234L16.000417 15.041079Z" })
|
|
743
|
+
] });
|
|
744
|
+
}
|
|
745
|
+
function SlidersIcon(props) {
|
|
746
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FillIcon, { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M2.2 3.4h6.05a1.85 1.85 0 0 0 3.5 0H13.8v1.3H11.75a1.85 1.85 0 0 0-3.5 0H2.2V3.4Zm8.6 1.15A.75.75 0 1 1 10.05 4.55.75.75 0 0 1 10.8 4.55ZM2.2 7.35h2.35a1.85 1.85 0 0 0 3.5 0H13.8v1.3H8.05a1.85 1.85 0 0 0-3.5 0H2.2V7.35Zm4.1 1.15A.75.75 0 1 1 5.55 8.5a.75.75 0 0 1 .75-.75ZM2.2 11.3h7.35a1.85 1.85 0 0 0 3.5 0H13.8v1.3h-.75a1.85 1.85 0 0 0-3.5 0H2.2v-1.3Zm9.9 1.15a.75.75 0 1 1-.75-.75.75.75 0 0 1 .75.75Z" }) });
|
|
747
|
+
}
|
|
748
|
+
function FolderClosedIcon(props) {
|
|
749
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FillIcon, { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", transform: "translate(1.5 2.429)", d: "M5.05582 0.518756L4.50669 0.86654L5.05582 0.518756ZM13 9.4837L13.65 9.4837L13.65 3.53962L13 3.53962L12.35 3.53962L12.35 9.4837L13 9.4837ZM11.3264 1.86603L11.3264 1.21603L6.52313 1.21603L6.52313 1.86603L6.52313 2.51603L11.3264 2.51603L11.3264 1.86603ZM5.58054 1.34727L6.12968 0.999489L5.60495 0.170972L5.05582 0.518756L4.50669 0.86654L5.03141 1.69506L5.58054 1.34727ZM4.11323 1.23058e-13L4.11323 -0.65L1.67359 -0.65L1.67359 5.00699e-14L1.67359 0.65L4.11323 0.65L4.11323 1.23058e-13ZM0 1.67359L-0.65 1.67359L-0.65 9.4837L0 9.4837L0.65 9.4837L0.65 1.67359L0 1.67359ZM11.3264 11.1573L11.3264 10.5073L1.67359 10.5073L1.67359 11.1573L1.67359 11.8073L11.3264 11.8073L11.3264 11.1573ZM0 9.4837L-0.65 9.4837C-0.65 10.767 0.390308 11.8073 1.67359 11.8073L1.67359 11.1573L1.67359 10.5073C1.10828 10.5073 0.65 10.049 0.65 9.4837L0 9.4837ZM1.67359 5.00699e-14L1.67359 -0.65C0.390307 -0.65 -0.65 0.390309 -0.65 1.67359L0 1.67359L0.65 1.67359C0.65 1.10828 1.10828 0.65 1.67359 0.65L1.67359 5.00699e-14ZM5.05582 0.518756L5.60495 0.170972C5.28121 -0.340193 4.71829 -0.65 4.11323 -0.65L4.11323 1.23058e-13L4.11323 0.65C4.27282 0.65 4.4213 0.731715 4.50669 0.86654L5.05582 0.518756ZM6.52313 1.86603L6.52313 1.21603C6.36354 1.21603 6.21507 1.13431 6.12968 0.999489L5.58054 1.34727L5.03141 1.69506C5.35515 2.20622 5.91808 2.51603 6.52313 2.51603L6.52313 1.86603ZM13 3.53962L13.65 3.53962C13.65 2.25634 12.6097 1.21603 11.3264 1.21603L11.3264 1.86603L11.3264 2.51603C11.8917 2.51603 12.35 2.97431 12.35 3.53962L13 3.53962ZM13 9.4837L12.35 9.4837C12.35 10.049 11.8917 10.5073 11.3264 10.5073L11.3264 11.1573L11.3264 11.8073C12.6097 11.8073 13.65 10.767 13.65 9.4837L13 9.4837Z" }) });
|
|
750
|
+
}
|
|
751
|
+
function FolderOpenIcon(props) {
|
|
752
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(FillIcon, { ...props, children: [
|
|
753
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M5.19629 1.57104C5.81144 1.5711 6.38623 1.8786 6.72754 2.39038L7.19922 3.09839C7.28454 3.22635 7.42824 3.30344 7.58203 3.30347H12.1699C13.5039 3.30348 14.5859 4.38548 14.5859 5.71948V6.62671C15.2694 7.02689 15.6605 7.85012 15.4385 8.68726L14.3848 12.658C14.1037 13.7164 13.1449 14.4527 12.0498 14.4529H2.91699C1.51651 14.4529 0.451662 13.2814 0.501954 11.9519V3.98706C0.501954 2.65305 1.58396 1.57104 2.91797 1.57104H5.19629ZM3.7793 7.75562C3.30994 7.75562 2.89883 8.07153 2.77832 8.52515L1.91602 11.7722C1.74167 12.4291 2.23734 13.073 2.91699 13.073H12.0498C12.5191 13.0728 12.9304 12.757 13.0508 12.3035L14.1045 8.33374C14.1819 8.04202 13.9619 7.756 13.6602 7.75562H3.7793ZM2.91797 2.9519C2.34625 2.9519 1.88281 3.41534 1.88281 3.98706V7.2937C2.33068 6.7269 3.02249 6.37476 3.7793 6.37476H13.2051V5.71948C13.2051 5.14777 12.7416 4.68434 12.1699 4.68433H7.58203C6.96675 4.6843 6.39209 4.37595 6.05078 3.86401L5.5791 3.15601C5.49379 3.02821 5.34995 2.95196 5.19629 2.9519H2.91797Z" }),
|
|
754
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", opacity: "0.2", d: "M13.6602 7.75525C13.9618 7.7556 14.1815 8.04179 14.1045 8.33337L13.0508 12.3031C12.9304 12.7567 12.5191 13.0725 12.0498 13.0726H2.91701C2.23744 13.0725 1.7417 12.4287 1.91603 11.7719L2.77834 8.52478C2.89898 8.07146 3.31018 7.75532 3.77931 7.75525H13.6602ZM5.1963 2.95154C5.34985 2.95159 5.49377 3.02803 5.57912 3.15564L6.0508 3.86365C6.39205 4.37553 6.96685 4.68385 7.58205 4.68396H12.1699C12.7416 4.68396 13.2049 5.14754 13.2051 5.71912V6.37439H3.77931C3.02267 6.37444 2.33067 6.72671 1.88283 7.29333V3.98669C1.88299 3.4152 2.34649 2.95168 2.91798 2.95154H5.1963Z" })
|
|
755
|
+
] });
|
|
756
|
+
}
|
|
757
|
+
function ChevronIcon(props) {
|
|
758
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 14 14", width: props.width || 14, height: props.height || 14, fill: "none", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M4.25 2.828v8.344c0 .49.592.735.939.389l4.172-4.172a.55.55 0 0 0 0-.778L5.189 2.439c-.347-.347-.939-.101-.939.389Z" }) });
|
|
423
759
|
}
|
|
424
760
|
function EllipsisIcon(props) {
|
|
425
761
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(FillIcon, { ...props, children: [
|
|
@@ -796,7 +1132,7 @@ function CreateModal({
|
|
|
796
1132
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { children: editing === true ? t("modal.edit") : t("modal.title") }),
|
|
797
1133
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: t("form.subtitle") })
|
|
798
1134
|
] }),
|
|
799
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "dsh-st-
|
|
1135
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "dsh-st-modal-close", onClick: onClose, "aria-label": t("form.cancel"), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(CloseOutlineIcon, { width: 14, height: 14 }) })
|
|
800
1136
|
] }),
|
|
801
1137
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "dsh-st-field", children: [
|
|
802
1138
|
t("form.name"),
|
|
@@ -1371,14 +1707,29 @@ var IDLE_POLL_INTERVAL_MS = 15e3;
|
|
|
1371
1707
|
var ACTIVE_POLL_INTERVAL_MS = 2e3;
|
|
1372
1708
|
var HOST_SESSION_RETRY_REFRESH_GAPS = [1, 2, 4];
|
|
1373
1709
|
var HOST_SESSION_MAX_ATTEMPTS = HOST_SESSION_RETRY_REFRESH_GAPS.length + 1;
|
|
1710
|
+
var HOST_SESSION_REARM_INTERVAL_MS = 5 * 60 * 1e3;
|
|
1711
|
+
var RECENT_TERMINAL_RUN_WINDOW_MS = 24 * 60 * 60 * 1e3;
|
|
1374
1712
|
function snapshotPollIntervalMs(runs) {
|
|
1375
1713
|
return (runs ?? []).some((run) => run.status === "running" || run.status === "queued") ? ACTIVE_POLL_INTERVAL_MS : IDLE_POLL_INTERVAL_MS;
|
|
1376
1714
|
}
|
|
1715
|
+
function effectiveSnapshotPollIntervalMs(runs, foregroundSubscribers) {
|
|
1716
|
+
return foregroundSubscribers > 0 ? snapshotPollIntervalMs(runs) : IDLE_POLL_INTERVAL_MS;
|
|
1717
|
+
}
|
|
1377
1718
|
function isTransportError(error) {
|
|
1378
1719
|
const message = error instanceof Error ? error.message : String(error);
|
|
1379
1720
|
return /failed to fetch|networkerror|load failed|network request failed/i.test(message);
|
|
1380
1721
|
}
|
|
1381
|
-
function
|
|
1722
|
+
function sessionIdsNeedingHostSync(runs, serverNow) {
|
|
1723
|
+
const parsedNow = Date.parse(serverNow);
|
|
1724
|
+
const referenceTime = Number.isFinite(parsedNow) ? parsedNow : Date.now();
|
|
1725
|
+
const cutoff = referenceTime - RECENT_TERMINAL_RUN_WINDOW_MS;
|
|
1726
|
+
return [...new Set(runs.filter((run) => {
|
|
1727
|
+
if (run.status === "queued" || run.status === "running") return true;
|
|
1728
|
+
const timestamp = Date.parse(run.finishedAt ?? run.startedAt ?? run.scheduledFor);
|
|
1729
|
+
return Number.isFinite(timestamp) && timestamp >= cutoff;
|
|
1730
|
+
}).map((run) => run.sessionId).filter((sessionId) => sessionId !== void 0 && sessionId !== ""))].sort();
|
|
1731
|
+
}
|
|
1732
|
+
function installAutomationSessionSync(runtime, getSessions, options = {}) {
|
|
1382
1733
|
let stopped = false;
|
|
1383
1734
|
let completedRefreshes = 0;
|
|
1384
1735
|
let automationRefreshInProgress = runtime.source.getSnapshot().phase === "loading";
|
|
@@ -1386,6 +1737,7 @@ function installAutomationSessionSync(runtime, getSessions) {
|
|
|
1386
1737
|
let trackedMissingKey;
|
|
1387
1738
|
let attempts = 0;
|
|
1388
1739
|
let nextAttemptRefresh = 0;
|
|
1740
|
+
let nextRearmAt = 0;
|
|
1389
1741
|
let warnedMissingKey;
|
|
1390
1742
|
let hostRefreshPromise;
|
|
1391
1743
|
let reconcileAfterRefresh = false;
|
|
@@ -1393,6 +1745,7 @@ function installAutomationSessionSync(runtime, getSessions) {
|
|
|
1393
1745
|
trackedMissingKey = missingKey;
|
|
1394
1746
|
attempts = 0;
|
|
1395
1747
|
nextAttemptRefresh = completedRefreshes;
|
|
1748
|
+
nextRearmAt = 0;
|
|
1396
1749
|
warnedMissingKey = void 0;
|
|
1397
1750
|
};
|
|
1398
1751
|
const missingSessionKey = (sessions) => {
|
|
@@ -1403,7 +1756,7 @@ function installAutomationSessionSync(runtime, getSessions) {
|
|
|
1403
1756
|
...hostSnapshot.ids ?? [],
|
|
1404
1757
|
...Object.keys(hostSnapshot.byId ?? {})
|
|
1405
1758
|
]);
|
|
1406
|
-
return
|
|
1759
|
+
return sessionIdsNeedingHostSync(snapshot.runs, snapshot.serverNow).filter((sessionId) => !present.has(sessionId)).join("\0");
|
|
1407
1760
|
};
|
|
1408
1761
|
const reconcile = () => {
|
|
1409
1762
|
if (stopped) return;
|
|
@@ -1419,7 +1772,11 @@ function installAutomationSessionSync(runtime, getSessions) {
|
|
|
1419
1772
|
return;
|
|
1420
1773
|
}
|
|
1421
1774
|
if (missingKey !== trackedMissingKey) resetAttempts(missingKey);
|
|
1422
|
-
if (attempts >= HOST_SESSION_MAX_ATTEMPTS
|
|
1775
|
+
if (attempts >= HOST_SESSION_MAX_ATTEMPTS) {
|
|
1776
|
+
if ((options.now ?? Date.now)() < nextRearmAt) return;
|
|
1777
|
+
resetAttempts(missingKey);
|
|
1778
|
+
}
|
|
1779
|
+
if (completedRefreshes < nextAttemptRefresh) return;
|
|
1423
1780
|
if (hostRefreshPromise !== void 0) {
|
|
1424
1781
|
reconcileAfterRefresh = true;
|
|
1425
1782
|
return;
|
|
@@ -1428,6 +1785,9 @@ function installAutomationSessionSync(runtime, getSessions) {
|
|
|
1428
1785
|
attempts += 1;
|
|
1429
1786
|
const retryGap = HOST_SESSION_RETRY_REFRESH_GAPS[attemptIndex];
|
|
1430
1787
|
nextAttemptRefresh = retryGap === void 0 ? Number.POSITIVE_INFINITY : completedRefreshes + retryGap;
|
|
1788
|
+
if (attempts >= HOST_SESSION_MAX_ATTEMPTS) {
|
|
1789
|
+
nextRearmAt = (options.now ?? Date.now)() + HOST_SESSION_REARM_INTERVAL_MS;
|
|
1790
|
+
}
|
|
1431
1791
|
hostRefreshPromise = Promise.resolve().then(async () => {
|
|
1432
1792
|
await sessions.refresh();
|
|
1433
1793
|
}).catch((error) => {
|
|
@@ -1451,7 +1811,7 @@ function installAutomationSessionSync(runtime, getSessions) {
|
|
|
1451
1811
|
completedRefreshes += 1;
|
|
1452
1812
|
}
|
|
1453
1813
|
reconcile();
|
|
1454
|
-
});
|
|
1814
|
+
}, { background: true });
|
|
1455
1815
|
reconcile();
|
|
1456
1816
|
return () => {
|
|
1457
1817
|
stopped = true;
|
|
@@ -1465,19 +1825,23 @@ function createAutomationRuntime(rpc) {
|
|
|
1465
1825
|
let pollTimer;
|
|
1466
1826
|
let removePageResumeListeners = () => void 0;
|
|
1467
1827
|
const listeners2 = /* @__PURE__ */ new Set();
|
|
1828
|
+
const foregroundListeners = /* @__PURE__ */ new Set();
|
|
1468
1829
|
const armPoll = () => {
|
|
1469
1830
|
if (pollTimer !== void 0) clearInterval(pollTimer);
|
|
1470
1831
|
if (listeners2.size === 0) {
|
|
1471
1832
|
pollTimer = void 0;
|
|
1472
1833
|
return;
|
|
1473
1834
|
}
|
|
1474
|
-
pollTimer = setInterval(
|
|
1475
|
-
|
|
1476
|
-
|
|
1835
|
+
pollTimer = setInterval(
|
|
1836
|
+
() => {
|
|
1837
|
+
void refresh().catch(() => void 0);
|
|
1838
|
+
},
|
|
1839
|
+
effectiveSnapshotPollIntervalMs(state.snapshot?.runs, foregroundListeners.size)
|
|
1840
|
+
);
|
|
1477
1841
|
};
|
|
1478
1842
|
const armPageResumeListeners = () => {
|
|
1479
1843
|
removePageResumeListeners();
|
|
1480
|
-
if (
|
|
1844
|
+
if (foregroundListeners.size === 0) return;
|
|
1481
1845
|
const refreshOnResume = () => {
|
|
1482
1846
|
void refresh().catch(() => void 0);
|
|
1483
1847
|
};
|
|
@@ -1493,29 +1857,35 @@ function createAutomationRuntime(rpc) {
|
|
|
1493
1857
|
};
|
|
1494
1858
|
};
|
|
1495
1859
|
const publish = (next) => {
|
|
1496
|
-
const previousInterval =
|
|
1860
|
+
const previousInterval = effectiveSnapshotPollIntervalMs(state.snapshot?.runs, foregroundListeners.size);
|
|
1497
1861
|
state = next;
|
|
1498
|
-
if (listeners2.size > 0 && previousInterval !==
|
|
1862
|
+
if (listeners2.size > 0 && previousInterval !== effectiveSnapshotPollIntervalMs(state.snapshot?.runs, foregroundListeners.size)) armPoll();
|
|
1499
1863
|
for (const listener of [...listeners2]) listener();
|
|
1500
1864
|
};
|
|
1501
1865
|
const source = {
|
|
1502
1866
|
getSnapshot: () => state,
|
|
1503
|
-
subscribe: (listener) => {
|
|
1867
|
+
subscribe: (listener, options = {}) => {
|
|
1868
|
+
const hadListeners = listeners2.size > 0;
|
|
1869
|
+
const hadForegroundListeners = foregroundListeners.size > 0;
|
|
1504
1870
|
listeners2.add(listener);
|
|
1505
|
-
if (
|
|
1871
|
+
if (options.background !== true) foregroundListeners.add(listener);
|
|
1872
|
+
if (!hadListeners || options.background !== true && !hadForegroundListeners) {
|
|
1506
1873
|
queueMicrotask(() => {
|
|
1507
1874
|
if (listeners2.size > 0) void refresh().catch(() => void 0);
|
|
1508
1875
|
});
|
|
1509
|
-
armPoll();
|
|
1510
|
-
armPageResumeListeners();
|
|
1511
1876
|
}
|
|
1877
|
+
armPoll();
|
|
1878
|
+
if (foregroundListeners.size > 0 && !hadForegroundListeners) armPageResumeListeners();
|
|
1512
1879
|
return () => {
|
|
1513
1880
|
listeners2.delete(listener);
|
|
1881
|
+
foregroundListeners.delete(listener);
|
|
1514
1882
|
if (listeners2.size === 0 && pollTimer !== void 0) {
|
|
1515
1883
|
clearInterval(pollTimer);
|
|
1516
1884
|
pollTimer = void 0;
|
|
1885
|
+
} else if (listeners2.size > 0) {
|
|
1886
|
+
armPoll();
|
|
1517
1887
|
}
|
|
1518
|
-
if (
|
|
1888
|
+
if (foregroundListeners.size === 0) removePageResumeListeners();
|
|
1519
1889
|
};
|
|
1520
1890
|
}
|
|
1521
1891
|
};
|
|
@@ -1557,11 +1927,17 @@ function createAutomationRuntime(rpc) {
|
|
|
1557
1927
|
};
|
|
1558
1928
|
const mutateThenRefresh = async (endpoint, payload, patch) => {
|
|
1559
1929
|
unwrapRpcResult(await callRpc(endpoint, payload));
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1930
|
+
const applyPatch = () => {
|
|
1931
|
+
if (patch !== void 0 && state.snapshot !== void 0) {
|
|
1932
|
+
publish({ phase: "ready", snapshot: patch(state.snapshot), refreshedAt: Date.now() });
|
|
1933
|
+
}
|
|
1934
|
+
};
|
|
1563
1935
|
const pendingBeforeRefresh = refreshPromise;
|
|
1564
|
-
|
|
1936
|
+
applyPatch();
|
|
1937
|
+
if (pendingBeforeRefresh !== void 0) {
|
|
1938
|
+
await pendingBeforeRefresh.catch(() => void 0);
|
|
1939
|
+
applyPatch();
|
|
1940
|
+
}
|
|
1565
1941
|
try {
|
|
1566
1942
|
await refresh();
|
|
1567
1943
|
} catch {
|
|
@@ -1579,7 +1955,10 @@ function createAutomationRuntime(rpc) {
|
|
|
1579
1955
|
await mutateThenRefresh("mutate", payload, mutation === "delete" ? (snapshot) => ({
|
|
1580
1956
|
...snapshot,
|
|
1581
1957
|
automations: snapshot.automations.filter((item) => item.id !== automationId)
|
|
1582
|
-
}) :
|
|
1958
|
+
}) : (snapshot) => ({
|
|
1959
|
+
...snapshot,
|
|
1960
|
+
automations: snapshot.automations.map((item) => item.id === automationId ? { ...item, status: mutation === "pause" ? "paused" : "active" } : item)
|
|
1961
|
+
}));
|
|
1583
1962
|
},
|
|
1584
1963
|
async updateAutomation(automationId, input) {
|
|
1585
1964
|
const payload = { sessionId: "settings", automationId, input };
|
|
@@ -1958,7 +2337,7 @@ function AutomationView({ t, permissionT, modelT, runtime, closeSettings }) {
|
|
|
1958
2337
|
busy,
|
|
1959
2338
|
onEdit: () => openEdit(item),
|
|
1960
2339
|
onToggle: () => {
|
|
1961
|
-
void runAction(() => runtime.mutateAutomation(item.id, item.status
|
|
2340
|
+
void runAction(() => runtime.mutateAutomation(item.id, automationToggleMutation(item.status)));
|
|
1962
2341
|
},
|
|
1963
2342
|
onRun: () => {
|
|
1964
2343
|
void runAction(() => runtime.runNow(item.id));
|
|
@@ -2553,493 +2932,157 @@ function createNativeTabRegistry(officialTree) {
|
|
|
2553
2932
|
version: 1,
|
|
2554
2933
|
officialTree,
|
|
2555
2934
|
sessionFilters,
|
|
2556
|
-
getTabs() {
|
|
2557
|
-
return cachedTabs;
|
|
2558
|
-
},
|
|
2559
|
-
subscribe(listener) {
|
|
2560
|
-
listeners2.add(listener);
|
|
2561
|
-
return () => {
|
|
2562
|
-
listeners2.delete(listener);
|
|
2563
|
-
};
|
|
2564
|
-
},
|
|
2565
|
-
insert(tab) {
|
|
2566
|
-
if (tab.id === "") return () => void 0;
|
|
2567
|
-
const existed = tabs.get(tab.id);
|
|
2568
|
-
tabs.set(tab.id, tab);
|
|
2569
|
-
if (existed !== tab) {
|
|
2570
|
-
rebuild();
|
|
2571
|
-
emit();
|
|
2572
|
-
}
|
|
2573
|
-
return () => {
|
|
2574
|
-
tabs.delete(tab.id);
|
|
2575
|
-
rebuild();
|
|
2576
|
-
emit();
|
|
2577
|
-
};
|
|
2578
|
-
},
|
|
2579
|
-
addSessionFilter(filter) {
|
|
2580
|
-
sessionFilters.push(filter);
|
|
2581
|
-
emit();
|
|
2582
|
-
return () => {
|
|
2583
|
-
const index = sessionFilters.indexOf(filter);
|
|
2584
|
-
if (index >= 0) sessionFilters.splice(index, 1);
|
|
2585
|
-
emit();
|
|
2586
|
-
};
|
|
2587
|
-
}
|
|
2588
|
-
};
|
|
2589
|
-
}
|
|
2590
|
-
function getNativeTabRegistry(target) {
|
|
2591
|
-
if (target === void 0 || target === null || typeof target !== "object" && typeof target !== "function") return void 0;
|
|
2592
|
-
const registry = target[NATIVE_TABS_KEY];
|
|
2593
|
-
if (registry === void 0 || registry === null || typeof registry !== "object") return void 0;
|
|
2594
|
-
return typeof registry.insert === "function" ? registry : void 0;
|
|
2595
|
-
}
|
|
2596
|
-
function attachNativeTabRegistry(target, registry) {
|
|
2597
|
-
try {
|
|
2598
|
-
target[NATIVE_TABS_KEY] = registry;
|
|
2599
|
-
} catch {
|
|
2600
|
-
}
|
|
2601
|
-
return registry;
|
|
2602
|
-
}
|
|
2603
|
-
function findNativeTabRegistry(entry) {
|
|
2604
|
-
const record = entry;
|
|
2605
|
-
return getNativeTabRegistry(entry) ?? getNativeTabRegistry(record?.component);
|
|
2606
|
-
}
|
|
2607
|
-
function isForeignSidebarHost(component) {
|
|
2608
|
-
if (component === void 0 || component === null) return false;
|
|
2609
|
-
const flags = component;
|
|
2610
|
-
if (flags.__dshNativeTabHost === true) return true;
|
|
2611
|
-
if (flags.__imConnectWrapped === true) return true;
|
|
2612
|
-
return getNativeTabRegistry(component) !== void 0;
|
|
2613
|
-
}
|
|
2614
|
-
|
|
2615
|
-
// src/client/native-session-list.tsx
|
|
2616
|
-
var import_react9 = require("react");
|
|
2617
|
-
var import_react_dom3 = require("react-dom");
|
|
2618
|
-
var import_dsh_client_ui_primitives3 = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
2619
|
-
|
|
2620
|
-
// src/client/native-session-menu.ts
|
|
2621
|
-
function resolveEventElement(target) {
|
|
2622
|
-
if (target == null || typeof target !== "object") return null;
|
|
2623
|
-
const node = target;
|
|
2624
|
-
if (node.nodeType === 3 || node.nodeType === 8) {
|
|
2625
|
-
return node.parentElement ?? null;
|
|
2626
|
-
}
|
|
2627
|
-
return node;
|
|
2628
|
-
}
|
|
2629
|
-
function shouldCloseNativeSessionMenu(target, keepInside) {
|
|
2630
|
-
const el = resolveEventElement(target);
|
|
2631
|
-
if (el == null) return true;
|
|
2632
|
-
return !keepInside.some((root) => {
|
|
2633
|
-
if (root == null || typeof root !== "object") return false;
|
|
2634
|
-
if (root === el) return true;
|
|
2635
|
-
const box = root;
|
|
2636
|
-
return typeof box.contains === "function" && box.contains(el);
|
|
2637
|
-
});
|
|
2638
|
-
}
|
|
2639
|
-
function pointerPoint(event) {
|
|
2640
|
-
const x = Number(event?.clientX);
|
|
2641
|
-
const y = Number(event?.clientY);
|
|
2642
|
-
return {
|
|
2643
|
-
x: Number.isFinite(x) ? x : 8,
|
|
2644
|
-
y: Number.isFinite(y) ? y : 8
|
|
2645
|
-
};
|
|
2646
|
-
}
|
|
2647
|
-
function clampMenuPoint(x, y, width, height, viewport) {
|
|
2648
|
-
const pad = 8;
|
|
2649
|
-
const vw = viewport.width || width + pad * 2;
|
|
2650
|
-
const vh = viewport.height || height + pad * 2;
|
|
2651
|
-
return {
|
|
2652
|
-
x: Math.max(pad, Math.min(x, Math.max(pad, vw - width - pad))),
|
|
2653
|
-
y: Math.max(pad, Math.min(y, Math.max(pad, vh - height - pad)))
|
|
2654
|
-
};
|
|
2655
|
-
}
|
|
2656
|
-
function nextOpenSessionMenu(current, clicked, point) {
|
|
2657
|
-
if (current?.id === clicked) return null;
|
|
2658
|
-
return { id: clicked, x: point.x, y: point.y };
|
|
2659
|
-
}
|
|
2660
|
-
function nativeSessionMenuStyle(point, size = { width: 218, height: 176 }, viewport = { width: 1e3, height: 800 }) {
|
|
2661
|
-
const pos = clampMenuPoint(point.x, point.y, size.width, size.height, viewport);
|
|
2662
|
-
return {
|
|
2663
|
-
position: "fixed",
|
|
2664
|
-
zIndex: 4e3,
|
|
2665
|
-
left: `${Math.round(pos.x)}px`,
|
|
2666
|
-
top: `${Math.round(pos.y)}px`
|
|
2667
|
-
};
|
|
2668
|
-
}
|
|
2669
|
-
function nativeSessionHoverStyle(row, card, viewport) {
|
|
2670
|
-
const pad = 8;
|
|
2671
|
-
const left = row.right + pad;
|
|
2672
|
-
const top = row.top + card.height > viewport.height - pad ? Math.max(pad, viewport.height - card.height - pad) : Math.max(pad, row.top);
|
|
2673
|
-
return {
|
|
2674
|
-
position: "fixed",
|
|
2675
|
-
zIndex: 4100,
|
|
2676
|
-
left: `${Math.round(left)}px`,
|
|
2677
|
-
top: `${Math.round(top)}px`
|
|
2678
|
-
};
|
|
2679
|
-
}
|
|
2680
|
-
function relativeTime(value, t, now = Date.now()) {
|
|
2681
|
-
const ts = Date.parse(value || "");
|
|
2682
|
-
if (!Number.isFinite(ts)) return "";
|
|
2683
|
-
const delta = Math.max(0, now - ts);
|
|
2684
|
-
const min = Math.floor(delta / 6e4);
|
|
2685
|
-
if (min < 1) return t("time.now");
|
|
2686
|
-
if (min < 60) return t("time.minuteAgo", { count: min });
|
|
2687
|
-
const hour = Math.floor(min / 60);
|
|
2688
|
-
if (hour < 24) return t("time.hourAgo", { count: hour });
|
|
2689
|
-
return t("time.dayAgo", { count: Math.floor(hour / 24) });
|
|
2690
|
-
}
|
|
2691
|
-
|
|
2692
|
-
// src/client/native-group-actions.ts
|
|
2693
|
-
var ARCHIVE_MANAGER_PLUGIN = "@michengai/dsh-archive-manager";
|
|
2694
|
-
function hasArchiveManagerPlugin(root) {
|
|
2695
|
-
return root?.querySelector(`[data-plugin="${ARCHIVE_MANAGER_PLUGIN}"]`) != null;
|
|
2696
|
-
}
|
|
2697
|
-
function scheduledGroupShowsActiveFolder(expanded, sessionIds, selectedId) {
|
|
2698
|
-
return expanded && selectedId !== null && sessionIds.includes(selectedId);
|
|
2699
|
-
}
|
|
2700
|
-
async function archiveScheduledGroup(sessionIds, archiveSession) {
|
|
2701
|
-
for (const sessionId of sessionIds) await archiveSession(sessionId);
|
|
2702
|
-
}
|
|
2703
|
-
|
|
2704
|
-
// src/run-title.ts
|
|
2705
|
-
var RUN_STAMP_OPTIONS = {
|
|
2706
|
-
year: "numeric",
|
|
2707
|
-
month: "2-digit",
|
|
2708
|
-
day: "2-digit",
|
|
2709
|
-
hour: "2-digit",
|
|
2710
|
-
minute: "2-digit",
|
|
2711
|
-
hourCycle: "h23"
|
|
2712
|
-
};
|
|
2713
|
-
var zonedRunStampFormatters = /* @__PURE__ */ new Map();
|
|
2714
|
-
function runStampFormatter(timeZone) {
|
|
2715
|
-
const cached = zonedRunStampFormatters.get(timeZone);
|
|
2716
|
-
if (cached !== void 0) return cached;
|
|
2717
|
-
const formatter = new Intl.DateTimeFormat("en-CA", { ...RUN_STAMP_OPTIONS, timeZone });
|
|
2718
|
-
zonedRunStampFormatters.set(timeZone, formatter);
|
|
2719
|
-
return formatter;
|
|
2720
|
-
}
|
|
2721
|
-
function formatRunStamp(iso, timeZone) {
|
|
2722
|
-
const value = new Date(iso);
|
|
2723
|
-
if (Number.isNaN(value.getTime())) return iso;
|
|
2724
|
-
if (timeZone === void 0) {
|
|
2725
|
-
const date = `${value.getFullYear()}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`;
|
|
2726
|
-
const time = `${String(value.getHours()).padStart(2, "0")}:${String(value.getMinutes()).padStart(2, "0")}`;
|
|
2727
|
-
return `${date} ${time}`;
|
|
2728
|
-
}
|
|
2729
|
-
try {
|
|
2730
|
-
const parts = runStampFormatter(timeZone).formatToParts(value);
|
|
2731
|
-
const part = (type) => parts.find((item) => item.type === type)?.value;
|
|
2732
|
-
const [year, month, day, hour, minute] = ["year", "month", "day", "hour", "minute"].map((type) => part(type));
|
|
2733
|
-
if ([year, month, day, hour, minute].some((item) => item === void 0)) return iso;
|
|
2734
|
-
return `${year}-${month}-${day} ${hour}:${minute}`;
|
|
2735
|
-
} catch {
|
|
2736
|
-
return iso;
|
|
2737
|
-
}
|
|
2738
|
-
}
|
|
2739
|
-
|
|
2740
|
-
// src/client/schedule-rail-model.ts
|
|
2741
|
-
var AUTOMATION_SESSION_PREFIX = "dsh-automation-session-";
|
|
2742
|
-
var NATIVE_SIDEBAR_TAB_KEY = "dsh-automation.sidebar-tab";
|
|
2743
|
-
function groupScheduledSessions(automations, runs) {
|
|
2744
|
-
const nameById = /* @__PURE__ */ new Map();
|
|
2745
|
-
const timeZoneById = /* @__PURE__ */ new Map();
|
|
2746
|
-
for (const item of automations) {
|
|
2747
|
-
nameById.set(item.id, item.name);
|
|
2748
|
-
if (item.timeZone !== void 0) timeZoneById.set(item.id, item.timeZone);
|
|
2749
|
-
}
|
|
2750
|
-
for (const run of runs) {
|
|
2751
|
-
const stored = (run.automationName || "").trim();
|
|
2752
|
-
if (stored !== "" && stored !== run.automationId && !nameById.has(run.automationId)) {
|
|
2753
|
-
nameById.set(run.automationId, stored);
|
|
2754
|
-
}
|
|
2755
|
-
}
|
|
2756
|
-
const ids = [];
|
|
2757
|
-
const seen = /* @__PURE__ */ new Set();
|
|
2758
|
-
for (const item of automations) {
|
|
2759
|
-
if (seen.has(item.id)) continue;
|
|
2760
|
-
ids.push(item.id);
|
|
2761
|
-
seen.add(item.id);
|
|
2762
|
-
}
|
|
2763
|
-
for (const run of runs) {
|
|
2764
|
-
if (run.sessionId === void 0 || run.sessionId === "" || seen.has(run.automationId)) continue;
|
|
2765
|
-
ids.push(run.automationId);
|
|
2766
|
-
seen.add(run.automationId);
|
|
2767
|
-
}
|
|
2768
|
-
return ids.map((id) => {
|
|
2769
|
-
const name2 = nameById.get(id) ?? id;
|
|
2770
|
-
return {
|
|
2771
|
-
id,
|
|
2772
|
-
name: name2,
|
|
2773
|
-
sessions: runs.filter((run) => run.automationId === id && run.sessionId !== void 0 && run.sessionId !== "").slice().sort((left, right) => Date.parse(right.startedAt ?? right.scheduledFor) - Date.parse(left.startedAt ?? left.scheduledFor)).map((run) => ({
|
|
2774
|
-
id: run.sessionId,
|
|
2775
|
-
running: run.status === "running" || run.status === "queued",
|
|
2776
|
-
label: formatRunStamp(run.startedAt ?? run.scheduledFor, timeZoneById.get(id)) + " - " + name2
|
|
2777
|
-
}))
|
|
2778
|
-
};
|
|
2779
|
-
}).filter((group) => group.sessions.length > 0);
|
|
2780
|
-
}
|
|
2781
|
-
function automationToggleMutation(status) {
|
|
2782
|
-
return status === "active" ? "pause" : "resume";
|
|
2783
|
-
}
|
|
2784
|
-
function deriveTaskOverviewRows(automations, runs) {
|
|
2785
|
-
const lastByAutomation = /* @__PURE__ */ new Map();
|
|
2786
|
-
for (const run of runs) {
|
|
2787
|
-
if (run.sessionId === void 0 || run.sessionId === "") continue;
|
|
2788
|
-
const current = lastByAutomation.get(run.automationId);
|
|
2789
|
-
const stamp = Date.parse(run.startedAt ?? run.scheduledFor);
|
|
2790
|
-
const currentStamp = current === void 0 ? Number.NaN : Date.parse(current.startedAt ?? current.scheduledFor);
|
|
2791
|
-
if (current === void 0 || stamp >= currentStamp) lastByAutomation.set(run.automationId, run);
|
|
2792
|
-
}
|
|
2793
|
-
return automations.map((item) => {
|
|
2794
|
-
const last = lastByAutomation.get(item.id);
|
|
2795
|
-
return {
|
|
2796
|
-
id: item.id,
|
|
2797
|
-
name: item.name,
|
|
2798
|
-
status: item.status,
|
|
2799
|
-
...item.nextRunAt === void 0 ? {} : { nextRunAt: item.nextRunAt },
|
|
2800
|
-
...last === void 0 ? {} : { lastSessionId: last.sessionId }
|
|
2801
|
-
};
|
|
2802
|
-
});
|
|
2803
|
-
}
|
|
2804
|
-
function keepScheduledSessionLink(sessionId, archived, _presentIds) {
|
|
2805
|
-
if (sessionId === void 0 || sessionId === "") return false;
|
|
2806
|
-
if (archived.has(sessionId)) return false;
|
|
2807
|
-
return true;
|
|
2808
|
-
}
|
|
2809
|
-
function scheduledSessionNeedsSnapshotRefresh(sessionId, runs) {
|
|
2810
|
-
if (sessionId === void 0 || sessionId === null || sessionId === "") return false;
|
|
2811
|
-
if (!sessionId.startsWith(AUTOMATION_SESSION_PREFIX)) return false;
|
|
2812
|
-
return !(runs ?? []).some((run) => run.sessionId === sessionId);
|
|
2813
|
-
}
|
|
2814
|
-
function collectScheduledSessionIds(runs) {
|
|
2815
|
-
const ids = /* @__PURE__ */ new Set();
|
|
2816
|
-
for (const run of runs ?? []) {
|
|
2817
|
-
const id = run.sessionId;
|
|
2818
|
-
if (typeof id === "string" && id !== "") ids.add(id);
|
|
2819
|
-
}
|
|
2820
|
-
return ids;
|
|
2821
|
-
}
|
|
2822
|
-
var AUTOMATION_TITLE_RE = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}/;
|
|
2823
|
-
function isAutomationSidebarSession(id, item, scheduledIds = /* @__PURE__ */ new Set()) {
|
|
2824
|
-
if (id.startsWith(AUTOMATION_SESSION_PREFIX) || scheduledIds.has(id)) return true;
|
|
2825
|
-
const title = String(item?.title ?? item?.displayTitle ?? "");
|
|
2826
|
-
return AUTOMATION_TITLE_RE.test(title);
|
|
2827
|
-
}
|
|
2828
|
-
function isNativeTaskSession(item, scheduledIds = /* @__PURE__ */ new Set()) {
|
|
2829
|
-
if (item === void 0 || item.blank === true) return false;
|
|
2830
|
-
if (item.origin === "im" || item.origin === "subagent") return false;
|
|
2831
|
-
const id = item.id ?? "";
|
|
2832
|
-
if (id.startsWith("im:")) return false;
|
|
2833
|
-
if (isAutomationSidebarSession(id, item, scheduledIds)) return false;
|
|
2834
|
-
return true;
|
|
2835
|
-
}
|
|
2836
|
-
function groupNativeTaskSessions(sessions, workspaces, ungroupedLabel, scheduledIds = /* @__PURE__ */ new Set()) {
|
|
2837
|
-
const byId = sessions.byId ?? {};
|
|
2838
|
-
const archived = new Set(workspaces?.archivedSessionIds ?? []);
|
|
2839
|
-
const assigned = /* @__PURE__ */ new Set();
|
|
2840
|
-
const groups = [];
|
|
2841
|
-
for (const workspace of workspaces?.items ?? []) {
|
|
2842
|
-
const items = (workspace.sessionIds ?? []).map((id) => byId[id]).filter((item) => item !== void 0 && item.id !== void 0 && isNativeTaskSession(item, scheduledIds) && !archived.has(item.id));
|
|
2843
|
-
for (const item of items) {
|
|
2844
|
-
if (item.id !== void 0) assigned.add(item.id);
|
|
2845
|
-
}
|
|
2846
|
-
if (items.length > 0) {
|
|
2847
|
-
groups.push({
|
|
2848
|
-
id: workspace.workspaceId ?? workspace.id ?? workspace.path ?? workspace.title ?? "workspace",
|
|
2849
|
-
label: workspace.title || workspace.path || ungroupedLabel,
|
|
2850
|
-
sessions: items
|
|
2851
|
-
});
|
|
2852
|
-
}
|
|
2853
|
-
}
|
|
2854
|
-
const ungrouped = (sessions.ids ?? []).map((id) => byId[id]).filter((item) => item !== void 0 && item.id !== void 0 && !assigned.has(item.id) && isNativeTaskSession(item, scheduledIds) && !archived.has(item.id));
|
|
2855
|
-
if (ungrouped.length > 0) groups.push({ id: "", label: ungroupedLabel, sessions: ungrouped });
|
|
2856
|
-
return groups;
|
|
2857
|
-
}
|
|
2858
|
-
function readNativeSidebarTab(raw) {
|
|
2859
|
-
if (raw === "channels" || raw === "schedule" || raw === "tasks") return raw;
|
|
2860
|
-
return "tasks";
|
|
2861
|
-
}
|
|
2862
|
-
function shouldFollowSessionTab(previousCurrent, current) {
|
|
2863
|
-
const prev = previousCurrent ?? "";
|
|
2864
|
-
const next = current ?? "";
|
|
2865
|
-
return next !== "" && prev !== next;
|
|
2866
|
-
}
|
|
2867
|
-
function ownedSidebarTabIds(input) {
|
|
2868
|
-
const ids = ["tasks"];
|
|
2869
|
-
for (const id of input.extraTabIds) {
|
|
2870
|
-
if (id === "" || id === "tasks" || id === "schedule" || ids.includes(id)) continue;
|
|
2871
|
-
ids.push(id);
|
|
2872
|
-
}
|
|
2873
|
-
if (input.channelsReady && !ids.includes("channels")) ids.push("channels");
|
|
2874
|
-
ids.push("schedule");
|
|
2875
|
-
return ids;
|
|
2876
|
-
}
|
|
2877
|
-
function resolveVisibleSidebarTab(input) {
|
|
2878
|
-
if (input.extraTabIds.includes(input.tab)) return input.tab;
|
|
2879
|
-
if (input.tab === "channels" && !input.channelsReady) return "tasks";
|
|
2880
|
-
return input.tab;
|
|
2881
|
-
}
|
|
2882
|
-
function tabForSessionId(sessionId, scheduledIds) {
|
|
2883
|
-
if (sessionId === void 0 || sessionId === null || sessionId === "") return void 0;
|
|
2884
|
-
if (scheduledIds !== void 0 ? scheduledIds.has(sessionId) : sessionId.startsWith(AUTOMATION_SESSION_PREFIX)) return "schedule";
|
|
2885
|
-
if (sessionId.startsWith("im:")) return "channels";
|
|
2886
|
-
return void 0;
|
|
2887
|
-
}
|
|
2888
|
-
function occupantLooksLikeCodexUi(value) {
|
|
2889
|
-
return /dsh-codex-ui|michengai-codex-ui|michengai\.codexUi|codex-ui/i.test(String(value ?? ""));
|
|
2890
|
-
}
|
|
2891
|
-
function slotOccupantName(item) {
|
|
2892
|
-
const record = item;
|
|
2893
|
-
return String(
|
|
2894
|
-
record?.options?.locale ?? record?.options?.id ?? record?.options?.name ?? record?.options?.registrant ?? record?.component?.displayName ?? record?.component?.name ?? record?.id ?? record?.name ?? ""
|
|
2895
|
-
);
|
|
2896
|
-
}
|
|
2897
|
-
function hasCodexUiSidebar(entries) {
|
|
2898
|
-
return (entries ?? []).some((item) => occupantLooksLikeCodexUi(slotOccupantName(item)));
|
|
2899
|
-
}
|
|
2900
|
-
var taskFilterCache = /* @__PURE__ */ new WeakMap();
|
|
2901
|
-
var workspaceFilterCache = /* @__PURE__ */ new WeakMap();
|
|
2902
|
-
function scheduledCacheKey(scheduledIds) {
|
|
2903
|
-
if (scheduledIds.size === 0) return "";
|
|
2904
|
-
return [...scheduledIds].sort().join("\0");
|
|
2935
|
+
getTabs() {
|
|
2936
|
+
return cachedTabs;
|
|
2937
|
+
},
|
|
2938
|
+
subscribe(listener) {
|
|
2939
|
+
listeners2.add(listener);
|
|
2940
|
+
return () => {
|
|
2941
|
+
listeners2.delete(listener);
|
|
2942
|
+
};
|
|
2943
|
+
},
|
|
2944
|
+
insert(tab) {
|
|
2945
|
+
if (tab.id === "") return () => void 0;
|
|
2946
|
+
const existed = tabs.get(tab.id);
|
|
2947
|
+
tabs.set(tab.id, tab);
|
|
2948
|
+
if (existed !== tab) {
|
|
2949
|
+
rebuild();
|
|
2950
|
+
emit();
|
|
2951
|
+
}
|
|
2952
|
+
return () => {
|
|
2953
|
+
tabs.delete(tab.id);
|
|
2954
|
+
rebuild();
|
|
2955
|
+
emit();
|
|
2956
|
+
};
|
|
2957
|
+
},
|
|
2958
|
+
addSessionFilter(filter) {
|
|
2959
|
+
sessionFilters.push(filter);
|
|
2960
|
+
emit();
|
|
2961
|
+
return () => {
|
|
2962
|
+
const index = sessionFilters.indexOf(filter);
|
|
2963
|
+
if (index >= 0) sessionFilters.splice(index, 1);
|
|
2964
|
+
emit();
|
|
2965
|
+
};
|
|
2966
|
+
}
|
|
2967
|
+
};
|
|
2905
2968
|
}
|
|
2906
|
-
function
|
|
2907
|
-
|
|
2908
|
-
const
|
|
2909
|
-
if (
|
|
2910
|
-
|
|
2911
|
-
if (hit !== void 0 && hit.key === key) return hit.result;
|
|
2912
|
-
}
|
|
2913
|
-
const ids = (src.ids ?? []).filter((id) => {
|
|
2914
|
-
const value = String(id);
|
|
2915
|
-
return !value.startsWith("im:") && !isAutomationSidebarSession(value, src.byId?.[value], scheduledIds);
|
|
2916
|
-
});
|
|
2917
|
-
const unchanged = ids.length === (src.ids ?? []).length;
|
|
2918
|
-
const result = unchanged ? src : { ...src, ids, byId: Object.fromEntries(ids.map((id) => [id, src.byId?.[id]]).filter((entry) => entry[1] !== void 0)) };
|
|
2919
|
-
if (typeof src === "object" && src !== null) taskFilterCache.set(src, { key, result });
|
|
2920
|
-
return result;
|
|
2969
|
+
function getNativeTabRegistry(target) {
|
|
2970
|
+
if (target === void 0 || target === null || typeof target !== "object" && typeof target !== "function") return void 0;
|
|
2971
|
+
const registry = target[NATIVE_TABS_KEY];
|
|
2972
|
+
if (registry === void 0 || registry === null || typeof registry !== "object") return void 0;
|
|
2973
|
+
return typeof registry.insert === "function" ? registry : void 0;
|
|
2921
2974
|
}
|
|
2922
|
-
function
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
if (typeof attempt !== "function") continue;
|
|
2927
|
-
try {
|
|
2928
|
-
attempt(id);
|
|
2929
|
-
return true;
|
|
2930
|
-
} catch {
|
|
2931
|
-
}
|
|
2975
|
+
function attachNativeTabRegistry(target, registry) {
|
|
2976
|
+
try {
|
|
2977
|
+
target[NATIVE_TABS_KEY] = registry;
|
|
2978
|
+
} catch {
|
|
2932
2979
|
}
|
|
2933
|
-
return
|
|
2980
|
+
return registry;
|
|
2934
2981
|
}
|
|
2935
|
-
|
|
2936
|
-
const
|
|
2937
|
-
|
|
2938
|
-
await input.adopt?.(id).catch(() => void 0);
|
|
2939
|
-
const listed = () => input.listed?.(id) === true;
|
|
2940
|
-
if (!listed() && input.refresh !== void 0) {
|
|
2941
|
-
await input.refresh().catch(() => void 0);
|
|
2942
|
-
}
|
|
2943
|
-
if (openScheduledSession(id, input.openRuntime, input.openHost)) return true;
|
|
2944
|
-
if (input.refresh !== void 0) {
|
|
2945
|
-
await input.refresh().catch(() => void 0);
|
|
2946
|
-
}
|
|
2947
|
-
return openScheduledSession(id, input.openRuntime, input.openHost);
|
|
2982
|
+
function findNativeTabRegistry(entry) {
|
|
2983
|
+
const record = entry;
|
|
2984
|
+
return getNativeTabRegistry(entry) ?? getNativeTabRegistry(record?.component);
|
|
2948
2985
|
}
|
|
2949
|
-
function
|
|
2950
|
-
|
|
2986
|
+
function isForeignSidebarHost(component) {
|
|
2987
|
+
if (component === void 0 || component === null) return false;
|
|
2988
|
+
const flags = component;
|
|
2989
|
+
if (flags.__dshNativeTabHost === true) return true;
|
|
2990
|
+
if (flags.__imConnectWrapped === true) return true;
|
|
2991
|
+
return getNativeTabRegistry(component) !== void 0;
|
|
2951
2992
|
}
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2993
|
+
|
|
2994
|
+
// src/client/native-session-list.tsx
|
|
2995
|
+
var import_react9 = require("react");
|
|
2996
|
+
var import_react_dom3 = require("react-dom");
|
|
2997
|
+
var import_dsh_client_ui_primitives3 = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
2998
|
+
|
|
2999
|
+
// src/client/native-session-menu.ts
|
|
3000
|
+
function resolveEventElement(target) {
|
|
3001
|
+
if (target == null || typeof target !== "object") return null;
|
|
3002
|
+
const node = target;
|
|
3003
|
+
if (node.nodeType === 3 || node.nodeType === 8) {
|
|
3004
|
+
return node.parentElement ?? null;
|
|
2958
3005
|
}
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
return
|
|
3006
|
+
return node;
|
|
3007
|
+
}
|
|
3008
|
+
function shouldCloseNativeSessionMenu(target, keepInside) {
|
|
3009
|
+
const el = resolveEventElement(target);
|
|
3010
|
+
if (el == null) return true;
|
|
3011
|
+
return !keepInside.some((root) => {
|
|
3012
|
+
if (root == null || typeof root !== "object") return false;
|
|
3013
|
+
if (root === el) return true;
|
|
3014
|
+
const box = root;
|
|
3015
|
+
return typeof box.contains === "function" && box.contains(el);
|
|
2967
3016
|
});
|
|
2968
|
-
const result = changed ? { ...src, items } : src;
|
|
2969
|
-
if (typeof src === "object" && src !== null) workspaceFilterCache.set(src, { key, result });
|
|
2970
|
-
return result;
|
|
2971
3017
|
}
|
|
2972
|
-
function
|
|
2973
|
-
|
|
2974
|
-
|
|
3018
|
+
function pointerPoint(event) {
|
|
3019
|
+
const x = Number(event?.clientX);
|
|
3020
|
+
const y = Number(event?.clientY);
|
|
3021
|
+
return {
|
|
3022
|
+
x: Number.isFinite(x) ? x : 8,
|
|
3023
|
+
y: Number.isFinite(y) ? y : 8
|
|
3024
|
+
};
|
|
2975
3025
|
}
|
|
2976
|
-
function
|
|
2977
|
-
|
|
3026
|
+
function clampMenuPoint(x, y, width, height, viewport) {
|
|
3027
|
+
const pad = 8;
|
|
3028
|
+
const vw = viewport.width || width + pad * 2;
|
|
3029
|
+
const vh = viewport.height || height + pad * 2;
|
|
3030
|
+
return {
|
|
3031
|
+
x: Math.max(pad, Math.min(x, Math.max(pad, vw - width - pad))),
|
|
3032
|
+
y: Math.max(pad, Math.min(y, Math.max(pad, vh - height - pad)))
|
|
3033
|
+
};
|
|
2978
3034
|
}
|
|
2979
|
-
function
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
while (current !== void 0 && current !== null && !seen.has(current)) {
|
|
2983
|
-
seen.add(current);
|
|
2984
|
-
const flags = wrapperFlags(current);
|
|
2985
|
-
const next = flags.__dshAutomationOriginal ?? flags.__imConnectOriginal;
|
|
2986
|
-
if (next !== void 0 && next !== current) {
|
|
2987
|
-
current = next;
|
|
2988
|
-
continue;
|
|
2989
|
-
}
|
|
2990
|
-
if (flags.__dshAutomationWrapped === true || flags.__imConnectWrapped === true) return void 0;
|
|
2991
|
-
return current;
|
|
2992
|
-
}
|
|
2993
|
-
return void 0;
|
|
3035
|
+
function nextOpenSessionMenu(current, clicked, point) {
|
|
3036
|
+
if (current?.id === clicked) return null;
|
|
3037
|
+
return { id: clicked, x: point.x, y: point.y };
|
|
2994
3038
|
}
|
|
2995
|
-
function
|
|
2996
|
-
const
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3039
|
+
function nativeSessionMenuStyle(point, size = { width: 218, height: 176 }, viewport = { width: 1e3, height: 800 }) {
|
|
3040
|
+
const pos = clampMenuPoint(point.x, point.y, size.width, size.height, viewport);
|
|
3041
|
+
return {
|
|
3042
|
+
position: "fixed",
|
|
3043
|
+
zIndex: 4e3,
|
|
3044
|
+
left: `${Math.round(pos.x)}px`,
|
|
3045
|
+
top: `${Math.round(pos.y)}px`
|
|
3046
|
+
};
|
|
3000
3047
|
}
|
|
3001
|
-
function
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3048
|
+
function nativeSessionHoverStyle(row, card, viewport) {
|
|
3049
|
+
const pad = 8;
|
|
3050
|
+
const left = row.right + pad;
|
|
3051
|
+
const top = row.top + card.height > viewport.height - pad ? Math.max(pad, viewport.height - card.height - pad) : Math.max(pad, row.top);
|
|
3052
|
+
return {
|
|
3053
|
+
position: "fixed",
|
|
3054
|
+
zIndex: 4100,
|
|
3055
|
+
left: `${Math.round(left)}px`,
|
|
3056
|
+
top: `${Math.round(top)}px`
|
|
3057
|
+
};
|
|
3009
3058
|
}
|
|
3010
|
-
function
|
|
3011
|
-
const
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
if (
|
|
3019
|
-
|
|
3020
|
-
if (sort === "time") sessions.sort((left, right) => sessionTime(right) - sessionTime(left));
|
|
3021
|
-
return sessions.length === 0 ? [] : [{ ...filtered[0], name: "", sessions }];
|
|
3022
|
-
}
|
|
3023
|
-
if (sort === "manual") return filtered;
|
|
3024
|
-
return [...filtered].sort((left, right) => latestSessionTime(right) - latestSessionTime(left));
|
|
3059
|
+
function relativeTime(value, t, now = Date.now()) {
|
|
3060
|
+
const ts = Date.parse(value || "");
|
|
3061
|
+
if (!Number.isFinite(ts)) return "";
|
|
3062
|
+
const delta = Math.max(0, now - ts);
|
|
3063
|
+
const min = Math.floor(delta / 6e4);
|
|
3064
|
+
if (min < 1) return t("time.now");
|
|
3065
|
+
if (min < 60) return t("time.minuteAgo", { count: min });
|
|
3066
|
+
const hour = Math.floor(min / 60);
|
|
3067
|
+
if (hour < 24) return t("time.hourAgo", { count: hour });
|
|
3068
|
+
return t("time.dayAgo", { count: Math.floor(hour / 24) });
|
|
3025
3069
|
}
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3070
|
+
|
|
3071
|
+
// src/client/native-group-actions.ts
|
|
3072
|
+
var ARCHIVE_MANAGER_PLUGIN = "@michengai/dsh-archive-manager";
|
|
3073
|
+
function hasArchiveManagerPlugin(root) {
|
|
3074
|
+
return root?.querySelector(`[data-plugin="${ARCHIVE_MANAGER_PLUGIN}"]`) != null;
|
|
3029
3075
|
}
|
|
3030
|
-
function
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
}
|
|
3036
|
-
return latest;
|
|
3076
|
+
function scheduledGroupShowsActiveFolder(expanded, sessionIds, selectedId) {
|
|
3077
|
+
return expanded && selectedId !== null && sessionIds.includes(selectedId);
|
|
3078
|
+
}
|
|
3079
|
+
async function archiveScheduledGroup(sessionIds, archiveSession) {
|
|
3080
|
+
for (const sessionId of sessionIds) await archiveSession(sessionId);
|
|
3037
3081
|
}
|
|
3038
3082
|
|
|
3039
3083
|
// src/client/schedule-overview.tsx
|
|
3040
3084
|
var import_react7 = require("react");
|
|
3041
3085
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
3042
|
-
var EMPTY_SET = /* @__PURE__ */ new Set();
|
|
3043
3086
|
var SORT_STORAGE2 = typeof window === "undefined" ? void 0 : window.localStorage;
|
|
3044
3087
|
function ScheduleViewSwitch({
|
|
3045
3088
|
t,
|
|
@@ -3054,11 +3097,8 @@ function ScheduleViewSwitch({
|
|
|
3054
3097
|
function ScheduleOverview({
|
|
3055
3098
|
t,
|
|
3056
3099
|
automations,
|
|
3057
|
-
runs,
|
|
3058
|
-
openSession,
|
|
3059
3100
|
serverNow,
|
|
3060
|
-
|
|
3061
|
-
presentIds,
|
|
3101
|
+
openTaskSettings,
|
|
3062
3102
|
onToggleAutomation
|
|
3063
3103
|
}) {
|
|
3064
3104
|
const [sortKey, setSortKey] = (0, import_react7.useState)(() => readSortDefault(SORT_STORAGE2, OVERVIEW_SORT_DEFAULT_KEY)?.key ?? "planned");
|
|
@@ -3067,14 +3107,8 @@ function ScheduleOverview({
|
|
|
3067
3107
|
const now = (0, import_react7.useMemo)(() => new Date(serverNow ?? Date.now()), [serverNow]);
|
|
3068
3108
|
const rows = (0, import_react7.useMemo)(() => {
|
|
3069
3109
|
const sorted = sortAutomations(automations, sortKey, sortDirection);
|
|
3070
|
-
return deriveTaskOverviewRows(sorted
|
|
3071
|
-
|
|
3072
|
-
const { lastSessionId: _dropped, ...rest } = row;
|
|
3073
|
-
return rest;
|
|
3074
|
-
}
|
|
3075
|
-
return row;
|
|
3076
|
-
});
|
|
3077
|
-
}, [archived, automations, presentIds, runs, sortDirection, sortKey]);
|
|
3110
|
+
return deriveTaskOverviewRows(sorted);
|
|
3111
|
+
}, [automations, sortDirection, sortKey]);
|
|
3078
3112
|
const scheduleSummaries = (0, import_react7.useMemo)(() => new Map(automations.map((item) => [item.id, formatSchedule(item.schedule, t)])), [automations, t]);
|
|
3079
3113
|
const toggleAutomation = (automationId, mutation) => {
|
|
3080
3114
|
if (onToggleAutomation === void 0 || busyIds.has(automationId)) return;
|
|
@@ -3122,7 +3156,7 @@ function ScheduleOverview({
|
|
|
3122
3156
|
scheduleSummary: scheduleSummaries.get(row.id) ?? "",
|
|
3123
3157
|
toggleDisabled: onToggleAutomation === void 0 || busyIds.has(row.id),
|
|
3124
3158
|
onToggleAutomation: toggleAutomation,
|
|
3125
|
-
...
|
|
3159
|
+
...openTaskSettings === void 0 ? {} : { openTaskSettings }
|
|
3126
3160
|
},
|
|
3127
3161
|
row.id
|
|
3128
3162
|
))
|
|
@@ -3133,12 +3167,14 @@ function OverviewRow({
|
|
|
3133
3167
|
row,
|
|
3134
3168
|
now,
|
|
3135
3169
|
scheduleSummary,
|
|
3136
|
-
|
|
3170
|
+
openTaskSettings,
|
|
3137
3171
|
toggleDisabled,
|
|
3138
3172
|
onToggleAutomation
|
|
3139
3173
|
}) {
|
|
3140
3174
|
const paused = row.status !== "active";
|
|
3141
3175
|
const nextRun = row.nextRunAt === void 0 ? t("stats.noneScheduled") : formatWithin(row.nextRunAt, now, t);
|
|
3176
|
+
const nextRunCompact = row.nextRunAt === void 0 ? t("stats.noneScheduled") : formatRelativeTime(row.nextRunAt, now, t);
|
|
3177
|
+
const nextRunLabel = `${t("stats.next")}: ${nextRun}`;
|
|
3142
3178
|
const toggleLabel = paused ? t("card.resume") : t("card.pause");
|
|
3143
3179
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: `dsh-st-overview-row${paused ? " is-paused" : ""}`, children: [
|
|
3144
3180
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
@@ -3146,23 +3182,19 @@ function OverviewRow({
|
|
|
3146
3182
|
{
|
|
3147
3183
|
type: "button",
|
|
3148
3184
|
className: "dsh-st-overview-open",
|
|
3149
|
-
disabled:
|
|
3185
|
+
disabled: openTaskSettings === void 0,
|
|
3150
3186
|
onClick: () => {
|
|
3151
|
-
|
|
3187
|
+
openTaskSettings?.({ automationId: row.id, name: row.name, sessionIds: [] });
|
|
3152
3188
|
},
|
|
3153
3189
|
children: [
|
|
3154
3190
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "dsh-st-overview-copy", children: [
|
|
3155
3191
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "dsh-st-overview-name", children: row.name }),
|
|
3156
3192
|
scheduleSummary !== "" && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "dsh-st-overview-schedule", children: [
|
|
3157
3193
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CalendarIcon, { width: 14, height: 14 }),
|
|
3158
|
-
scheduleSummary
|
|
3194
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: scheduleSummary })
|
|
3159
3195
|
] })
|
|
3160
3196
|
] }),
|
|
3161
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.
|
|
3162
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: t("stats.next") }),
|
|
3163
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("strong", { children: nextRun })
|
|
3164
|
-
] }),
|
|
3165
|
-
row.lastSessionId !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ChevronIcon, { width: 12, height: 12, className: "dsh-st-overview-chevron" })
|
|
3197
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "dsh-st-overview-next", title: nextRunLabel, "aria-label": nextRunLabel, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("strong", { children: nextRunCompact }) })
|
|
3166
3198
|
]
|
|
3167
3199
|
}
|
|
3168
3200
|
),
|
|
@@ -3364,12 +3396,9 @@ function NativeScheduleSessionList(props) {
|
|
|
3364
3396
|
{
|
|
3365
3397
|
t,
|
|
3366
3398
|
automations: state.snapshot.automations,
|
|
3367
|
-
runs: state.snapshot.runs,
|
|
3368
3399
|
onToggleAutomation: (automationId, mutation) => runtime.mutateAutomation(automationId, mutation),
|
|
3369
|
-
...
|
|
3370
|
-
...state.snapshot.serverNow === void 0 ? {} : { serverNow: state.snapshot.serverNow }
|
|
3371
|
-
archived,
|
|
3372
|
-
...presentIds === void 0 ? {} : { presentIds }
|
|
3400
|
+
...openTaskSettings === void 0 ? {} : { openTaskSettings },
|
|
3401
|
+
...state.snapshot.serverNow === void 0 ? {} : { serverNow: state.snapshot.serverNow }
|
|
3373
3402
|
}
|
|
3374
3403
|
) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
3375
3404
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(WorkspaceToolbar, { t, query, sort, groupMode, onQueryChange: setQuery, onSortChange: setSort, onGroupModeChange: setGroupMode }),
|
|
@@ -3688,6 +3717,7 @@ function ScheduleRail({
|
|
|
3688
3717
|
t,
|
|
3689
3718
|
runtime,
|
|
3690
3719
|
openSession,
|
|
3720
|
+
openTaskSettings,
|
|
3691
3721
|
view: controlledView,
|
|
3692
3722
|
showViewSwitch = true
|
|
3693
3723
|
}) {
|
|
@@ -3707,9 +3737,8 @@ function ScheduleRail({
|
|
|
3707
3737
|
{
|
|
3708
3738
|
t,
|
|
3709
3739
|
automations: snapshot.automations,
|
|
3710
|
-
runs: snapshot.runs,
|
|
3711
3740
|
onToggleAutomation: (automationId, mutation) => runtime.mutateAutomation(automationId, mutation),
|
|
3712
|
-
...
|
|
3741
|
+
...openTaskSettings === void 0 ? {} : { openTaskSettings },
|
|
3713
3742
|
...snapshot.serverNow === void 0 ? {} : { serverNow: snapshot.serverNow }
|
|
3714
3743
|
}
|
|
3715
3744
|
) : /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
|
|
@@ -3751,6 +3780,7 @@ function NativeScheduleShell({
|
|
|
3751
3780
|
officialTree,
|
|
3752
3781
|
hostProps,
|
|
3753
3782
|
openSession,
|
|
3783
|
+
openTaskSettings,
|
|
3754
3784
|
useSessions,
|
|
3755
3785
|
useWorkspaces,
|
|
3756
3786
|
renderSlot,
|
|
@@ -3847,7 +3877,7 @@ function NativeScheduleShell({
|
|
|
3847
3877
|
extraTabIds: ownedSidebarTabIds({ extraTabIds: foreignTabs.map((item) => item.id), channelsReady })
|
|
3848
3878
|
});
|
|
3849
3879
|
const hostedSchedule = extraTabs.find((item) => item.id === "schedule");
|
|
3850
|
-
const scheduleBody = hostedSchedule === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(NativeScheduleSessionList, { t, runtime, ...openSession === void 0 ? {} : { openSession }, ...useSessions === void 0 ? {} : { useSessions }, ...useWorkspaces === void 0 ? {} : { useWorkspaces } }) : hostedSchedule.render({ ...hostProps ?? {}, openSession, open: openSession, useSessions, wide: true });
|
|
3880
|
+
const scheduleBody = hostedSchedule === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(NativeScheduleSessionList, { t, runtime, ...openSession === void 0 ? {} : { openSession }, ...openTaskSettings === void 0 ? {} : { openTaskSettings }, ...useSessions === void 0 ? {} : { useSessions }, ...useWorkspaces === void 0 ? {} : { useWorkspaces } }) : hostedSchedule.render({ ...hostProps ?? {}, openSession, open: openSession, useSessions, wide: true });
|
|
3851
3881
|
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "dsh-st-shell-rail", children: [
|
|
3852
3882
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "dsh-st-shell-tabs", role: "tablist", "aria-label": t("sidebar.tabs"), children: [
|
|
3853
3883
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", role: "tab", "aria-selected": visibleTab === "tasks", className: visibleTab === "tasks" ? "is-on" : void 0, onClick: () => setTab("tasks"), children: t("sidebar.tasksTab") }),
|
|
@@ -3975,11 +4005,14 @@ var CSS_TEXT = `
|
|
|
3975
4005
|
.dsh-st-run p{display:flex;gap:10px;margin:0;color:var(--dsw-alias-label-tertiary);font-size:12px}
|
|
3976
4006
|
.dsh-st-error{color:#ff6b6b;font-size:12px}
|
|
3977
4007
|
.dsh-st-muted{color:var(--dsw-alias-label-secondary)}
|
|
3978
|
-
.dsh-st-mask{position:fixed;inset:0;z-index:40;display:flex;align-items:center;justify-content:center;padding:24px;overflow:auto;background:
|
|
3979
|
-
.dsh-st-modal,.dsh-st-modal *{box-sizing:border-box}.dsh-st-modal{display:flex;flex-direction:column;width:min(760px,calc(100vw - 48px));max-width:100%;max-height:min(92vh,900px);overflow:hidden;padding:24px;border:
|
|
4008
|
+
.dsh-st-mask{position:fixed;inset:0;z-index:40;display:flex;align-items:center;justify-content:center;padding:24px;overflow:auto;background:var(--dsw-alias-bg-mask-1);backdrop-filter:var(--dsw-mask-blur)}.dsh-st-flyout-root{position:absolute;inset:0;z-index:1200;overflow:visible;pointer-events:none}.dsh-st-flyout-root .dsh-st-select-menu,.dsh-st-flyout-root .dsh-st-model-select-menu{pointer-events:auto}
|
|
4009
|
+
.dsh-st-modal,.dsh-st-modal *{box-sizing:border-box}.dsh-st-modal{display:flex;flex-direction:column;width:min(760px,calc(100vw - 48px));max-width:100%;max-height:min(92vh,900px);overflow:hidden;padding:24px;border:0;border-radius:24px;background:var(--dsw-alias-bg-layer-2);box-shadow:var(--dsw-elevation-prominent)}
|
|
3980
4010
|
.dsh-st-confirm-modal,.dsh-st-confirm-modal *{box-sizing:border-box}.dsh-st-confirm-modal{width:min(420px,calc(100vw - 48px));padding:24px;border:1px solid var(--dsw-alias-border-l2);border-radius:18px;background:var(--dsw-alias-bg-base);box-shadow:var(--dsw-shadow-lv3,0 12px 36px rgba(0,0,0,.36))}.dsh-st-confirm-modal h2{margin:0 0 10px;font-size:18px}.dsh-st-confirm-modal p{margin:0 0 8px;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:1.5}.dsh-st-confirm-modal .dsh-st-confirm-target{color:var(--dsw-alias-label-primary);font-weight:600;overflow-wrap:anywhere}
|
|
3981
4011
|
.dsh-st-modal-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:14px}
|
|
3982
4012
|
.dsh-st-modal-head h2{margin:0 0 4px;font-size:20px}
|
|
4013
|
+
.dsh-st-modal-close{display:inline-flex;align-items:center;justify-content:center;flex:none;width:28px;height:28px;padding:0;border:0;border-radius:8px;background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer}
|
|
4014
|
+
.dsh-st-modal-close:hover{background:var(--dsw-alias-interactive-bg-hover)}
|
|
4015
|
+
.dsh-st-modal-close:focus-visible{outline:2px solid var(--dsw-alias-label-tertiary);outline-offset:-2px}
|
|
3983
4016
|
.dsh-st-field{display:flex;flex-direction:column;gap:6px;margin-bottom:12px;min-width:0;max-width:100%;font-size:13px}.dsh-st-field:has(.dsh-st-prompt-card){flex:1;min-height:0;margin-bottom:10px}
|
|
3984
4017
|
.dsh-st-field input,.dsh-st-field select,.dsh-st-field textarea{width:100%;padding:9px 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-bg-layer-1);color:inherit}
|
|
3985
4018
|
.dsh-st-field textarea{min-height:140px;max-width:100%;resize:vertical}
|
|
@@ -4051,16 +4084,17 @@ var CSS_TEXT = `
|
|
|
4051
4084
|
.dsh-st-overview-sort{display:flex;align-items:center}
|
|
4052
4085
|
.dsh-st-overview-row{position:relative;width:100%;min-height:56px;margin:0 0 8px;border:1px solid var(--dsw-alias-border-l2,rgba(255,255,255,.1));border-radius:9px;background:var(--dsw-alias-bg-layer-2,rgba(255,255,255,.035));color:var(--dsw-alias-label-primary,inherit);box-shadow:inset 0 1px rgba(255,255,255,.025);transition:background .14s ease,border-color .14s ease;overflow:hidden}
|
|
4053
4086
|
.dsh-st-overview-row:hover{border-color:var(--dsw-alias-border-inverted,rgba(255,255,255,.18));background:var(--dsw-alias-bg-layer-3,rgba(255,255,255,.06))}
|
|
4054
|
-
.dsh-st-overview-open{display:grid;grid-template-columns:minmax(0,1fr) auto
|
|
4087
|
+
.dsh-st-overview-open{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-rows:18px 18px;align-items:center;gap:4px 8px;width:100%;min-height:56px;padding:8px 9px;border:0;background:transparent;color:inherit;text-align:left;cursor:pointer}
|
|
4055
4088
|
.dsh-st-overview-open:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4c8dff);outline-offset:-2px}
|
|
4056
4089
|
.dsh-st-overview-open:disabled{cursor:default}
|
|
4057
4090
|
.dsh-st-overview-copy{display:contents}
|
|
4058
|
-
.dsh-st-overview-name{box-sizing:border-box;grid-column:1/
|
|
4091
|
+
.dsh-st-overview-name{box-sizing:border-box;grid-column:1/3;grid-row:1;min-width:0;padding-right:44px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:13px;line-height:18px;font-weight:580}
|
|
4059
4092
|
.dsh-st-overview-schedule{display:inline-flex;grid-column:1;grid-row:2;align-items:center;gap:5px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-tertiary,#8b8f98);font-size:12px;line-height:16px}
|
|
4060
|
-
.dsh-st-overview-
|
|
4093
|
+
.dsh-st-overview-schedule svg{flex:none}
|
|
4094
|
+
.dsh-st-overview-schedule>span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
4095
|
+
.dsh-st-overview-next{display:inline-flex;grid-column:2;grid-row:2;justify-self:end;flex:none;min-width:0;align-items:center;color:var(--dsw-alias-label-tertiary,#8b8f98);line-height:16px;white-space:nowrap}
|
|
4061
4096
|
.dsh-st-overview-next strong{color:var(--dsw-alias-label-secondary,#b6bac2);font-size:12px;font-weight:600;line-height:16px;white-space:nowrap}
|
|
4062
4097
|
.dsh-st-overview-row:not(.is-paused) .dsh-st-overview-next strong{color:#45d483}
|
|
4063
|
-
.dsh-st-overview-chevron{grid-column:3;grid-row:2;flex:none;color:var(--dsw-alias-label-tertiary,#8b8f98)}
|
|
4064
4098
|
.dsh-st-overview-toggle{position:absolute;top:3px;right:2px;z-index:1;display:inline-flex;align-items:center;justify-content:center;width:44px;height:28px;cursor:pointer}
|
|
4065
4099
|
.dsh-st-overview-toggle input{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
|
|
4066
4100
|
.dsh-st-overview-toggle>span{position:relative;width:28px;height:16px;border-radius:999px;background:var(--dsw-alias-bg-layer-3,rgba(255,255,255,.14));box-shadow:inset 0 0 0 1px var(--dsw-alias-border-l2,rgba(255,255,255,.12));transition:background .14s ease}
|
|
@@ -4235,6 +4269,15 @@ function apply(ctx) {
|
|
|
4235
4269
|
const permissionT = ctx.locale.bind("permission.access");
|
|
4236
4270
|
const modelT = ctx.locale.bind("model");
|
|
4237
4271
|
const runtime = createAutomationRuntime(ctx.connection.rpc);
|
|
4272
|
+
const openTaskSettings = (request) => {
|
|
4273
|
+
requestAutomationTaskSettings(request);
|
|
4274
|
+
openSettingsSection(
|
|
4275
|
+
[t("tab"), "Scheduled tasks", "\u5B9A\u65F6\u4EFB\u52A1"],
|
|
4276
|
+
() => {
|
|
4277
|
+
requestAutomationTaskSettings(request);
|
|
4278
|
+
}
|
|
4279
|
+
);
|
|
4280
|
+
};
|
|
4238
4281
|
ctx.effect(() => installAutomationSessionSync(runtime, () => ctx.sessions), "dsh-automation: session sync");
|
|
4239
4282
|
ctx.effect(() => installSettingsNavIcon(() => [t("tab"), "Scheduled tasks", "\u5B9A\u65F6\u4EFB\u52A1"]), "dsh-automation: settings icon");
|
|
4240
4283
|
ctx.slots.inject("settings.section", () => ctx.slots.register({
|
|
@@ -4258,6 +4301,7 @@ function apply(ctx) {
|
|
|
4258
4301
|
t,
|
|
4259
4302
|
runtime,
|
|
4260
4303
|
openSession: createScheduledSessionOpener(ctx, runtime, props.openSession),
|
|
4304
|
+
openTaskSettings,
|
|
4261
4305
|
...props.view === void 0 ? {} : { view: props.view },
|
|
4262
4306
|
...props.showViewSwitch === void 0 ? {} : { showViewSwitch: props.showViewSwitch }
|
|
4263
4307
|
});
|
|
@@ -4312,15 +4356,7 @@ function apply(ctx) {
|
|
|
4312
4356
|
...typeof props.archiveSession === "function" ? { archiveSession: props.archiveSession } : {},
|
|
4313
4357
|
...typeof props.deleteSession === "function" ? { deleteSession: props.deleteSession } : {},
|
|
4314
4358
|
...typeof props.forkSession === "function" ? { forkSession: props.forkSession } : {},
|
|
4315
|
-
openTaskSettings
|
|
4316
|
-
requestAutomationTaskSettings(request);
|
|
4317
|
-
openSettingsSection(
|
|
4318
|
-
[t("tab"), "Scheduled tasks", "\u5B9A\u65F6\u4EFB\u52A1"],
|
|
4319
|
-
() => {
|
|
4320
|
-
requestAutomationTaskSettings(request);
|
|
4321
|
-
}
|
|
4322
|
-
);
|
|
4323
|
-
}
|
|
4359
|
+
openTaskSettings
|
|
4324
4360
|
});
|
|
4325
4361
|
}
|
|
4326
4362
|
});
|
|
@@ -4357,6 +4393,7 @@ function apply(ctx) {
|
|
|
4357
4393
|
runtime,
|
|
4358
4394
|
hostProps: innerProps,
|
|
4359
4395
|
openSession,
|
|
4396
|
+
openTaskSettings,
|
|
4360
4397
|
tabRegistry: registry,
|
|
4361
4398
|
...innerProps.wide === void 0 ? {} : { wide: innerProps.wide },
|
|
4362
4399
|
hasChannels: () => slotHasEntries(ctx, "sidebar.channels"),
|