@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/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/client/icons.tsx
328
- var import_jsx_runtime = require("react/jsx-runtime");
329
- function IconFrame({ children, ...props }) {
330
- 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 });
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 PlusIcon(props) {
333
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconFrame, { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 5v14M5 12h14" }) });
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
- function RefreshIcon(props) {
336
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(IconFrame, { ...props, children: [
337
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M19 7v5h-5" }),
338
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M18.1 15.5A7.5 7.5 0 1 1 19 12" })
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 PlayIcon(props) {
342
- 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" }) });
417
+ function automationToggleMutation(status) {
418
+ return status === "active" ? "pause" : "resume";
343
419
  }
344
- function TrashIcon(props) {
345
- 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" }) });
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 ShieldIcon(props) {
348
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(IconFrame, { ...props, children: [
349
- /* @__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" }),
350
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m9.4 12 1.7 1.7 3.7-4" })
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 CalendarIcon(props) {
354
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(IconFrame, { ...props, children: [
355
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "4", y: "5.5", width: "16", height: "14", rx: "2" }),
356
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M8 3.8v3.4M16 3.8v3.4M4 9.5h16" })
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 MoreIcon(props) {
360
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(IconFrame, { ...props, children: [
361
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "6", cy: "12", r: "1.2", fill: "currentColor" }),
362
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "1.2", fill: "currentColor" }),
363
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "18", cy: "12", r: "1.2", fill: "currentColor" })
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
- function InfoIcon(props) {
367
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(IconFrame, { ...props, children: [
368
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "8.25" }),
369
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 10.4V16" }),
370
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 7.6h.01" })
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 ClockIcon(props) {
374
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(IconFrame, { ...props, children: [
375
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "8.25" }),
376
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 7.6v4.6l3 1.8" })
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 ChatIcon(props) {
380
- 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" }) });
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 GithubIcon(props) {
383
- 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" }) });
482
+ function readNativeSidebarTab(raw) {
483
+ if (raw === "channels" || raw === "schedule" || raw === "tasks") return raw;
484
+ return "tasks";
384
485
  }
385
- function FolderIcon(props) {
386
- 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" }) });
486
+ function shouldFollowSessionTab(previousCurrent, current) {
487
+ const prev = previousCurrent ?? "";
488
+ const next = current ?? "";
489
+ return next !== "" && prev !== next;
387
490
  }
388
- function SparkleIcon(props) {
389
- 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" }) });
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 FillIcon({ children, width = 16, height = 16 }) {
392
- 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 });
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 CloseOutlineIcon(props) {
395
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(FillIcon, { ...props, children: [
396
- /* @__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" }),
397
- /* @__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" })
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 CheckOutlineIcon(props) {
401
- 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" }) });
512
+ function occupantLooksLikeCodexUi(value) {
513
+ return /dsh-codex-ui|michengai-codex-ui|michengai\.codexUi|codex-ui/i.test(String(value ?? ""));
402
514
  }
403
- function SearchOutlineIcon(props) {
404
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(FillIcon, { ...props, children: [
405
- /* @__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" }),
406
- /* @__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" })
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 SlidersIcon(props) {
410
- 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" }) });
521
+ function hasCodexUiSidebar(entries) {
522
+ return (entries ?? []).some((item) => occupantLooksLikeCodexUi(slotOccupantName(item)));
411
523
  }
412
- function FolderClosedIcon(props) {
413
- 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" }) });
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 FolderOpenIcon(props) {
416
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(FillIcon, { ...props, children: [
417
- /* @__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" }),
418
- /* @__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" })
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 ChevronIcon(props) {
422
- 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" }) });
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-icon", onClick: onClose, "aria-label": t("form.cancel"), children: "\xD7" })
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 installAutomationSessionSync(runtime, getSessions) {
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 [...new Set(snapshot.runs.map((run) => run.sessionId).filter((sessionId) => sessionId !== void 0 && sessionId !== ""))].filter((sessionId) => !present.has(sessionId)).sort().join("\0");
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 || completedRefreshes < nextAttemptRefresh) return;
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
- void refresh().catch(() => void 0);
1476
- }, snapshotPollIntervalMs(state.snapshot?.runs));
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 (listeners2.size === 0) return;
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 = snapshotPollIntervalMs(state.snapshot?.runs);
1860
+ const previousInterval = effectiveSnapshotPollIntervalMs(state.snapshot?.runs, foregroundListeners.size);
1497
1861
  state = next;
1498
- if (listeners2.size > 0 && previousInterval !== snapshotPollIntervalMs(state.snapshot?.runs)) armPoll();
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 (listeners2.size === 1) {
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 (listeners2.size === 0) removePageResumeListeners();
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
- if (patch !== void 0 && state.snapshot !== void 0) {
1561
- publish({ phase: "ready", snapshot: patch(state.snapshot), refreshedAt: Date.now() });
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
- if (pendingBeforeRefresh !== void 0) await pendingBeforeRefresh.catch(() => void 0);
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
- }) : void 0);
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 === "active" ? "pause" : "resume"));
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 filterTaskSessionState(state, scheduledIds = /* @__PURE__ */ new Set()) {
2907
- const src = state ?? { ids: [], byId: {}, current: null };
2908
- const key = scheduledCacheKey(scheduledIds);
2909
- if (typeof src === "object" && src !== null) {
2910
- const hit = taskFilterCache.get(src);
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 openScheduledSession(id, openRuntime, openHost) {
2923
- if (id === "") return false;
2924
- const attempts = id.startsWith(AUTOMATION_SESSION_PREFIX) || id.startsWith("im:") ? [openRuntime, openHost] : [openHost, openRuntime];
2925
- for (const attempt of attempts) {
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 false;
2980
+ return registry;
2934
2981
  }
2935
- async function ensureOpenScheduledSession(input) {
2936
- const id = input.id.trim();
2937
- if (id === "") return false;
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 isHiddenSidebarSessionId(id, scheduledIds = /* @__PURE__ */ new Set()) {
2950
- return id.startsWith("im:") || isAutomationSidebarSession(id, void 0, scheduledIds);
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
- function filterWorkspaceListState(state, scheduledIds = /* @__PURE__ */ new Set()) {
2953
- const src = state ?? { items: [], archivedSessionIds: [] };
2954
- const key = scheduledCacheKey(scheduledIds);
2955
- if (typeof src === "object" && src !== null) {
2956
- const hit = workspaceFilterCache.get(src);
2957
- if (hit !== void 0 && hit.key === key) return hit.result;
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
- let changed = false;
2960
- const items = (src.items ?? []).map((workspace) => {
2961
- const sessionIds = (workspace.sessionIds ?? []).filter((sid) => !isHiddenSidebarSessionId(String(sid), scheduledIds));
2962
- if (sessionIds.length !== (workspace.sessionIds ?? []).length) {
2963
- changed = true;
2964
- return { ...workspace, sessionIds };
2965
- }
2966
- return workspace;
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 wrapperFlags(component) {
2973
- if (component === void 0 || component === null || typeof component !== "function" && typeof component !== "object") return {};
2974
- return component;
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 isOwnAutomationWrapper(component) {
2977
- return wrapperFlags(component).__dshAutomationWrapped === true;
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 resolveOfficialTreeComponent(component) {
2980
- const seen = /* @__PURE__ */ new Set();
2981
- let current = component;
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 isAutomationWorkspaceWrapper(item) {
2996
- const record = item;
2997
- const id = String(record?.options?.id ?? "");
2998
- const name2 = String(record?.component?.displayName ?? record?.component?.name ?? "");
2999
- return id === "dsh-automation-native-switcher" || id === "dsh-automation-wrap-bump" || name2 === "AutomationNativeWorkspaceShell" || name2 === "AutomationWrapBump" || isOwnAutomationWrapper(record?.component);
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 pickWrappableWorkspacesEntry(entries) {
3002
- for (const item of entries) {
3003
- const record = item;
3004
- if (record?.component === void 0) continue;
3005
- if (isAutomationWorkspaceWrapper(item)) continue;
3006
- return item;
3007
- }
3008
- return void 0;
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 applyWorkspaceBrowserQuery(groups, query, sort, groupMode = "workspace") {
3011
- const needle = query.trim().toLocaleLowerCase();
3012
- const filtered = groups.map((group) => {
3013
- if (needle === "") return group;
3014
- if (group.name.toLocaleLowerCase().includes(needle)) return group;
3015
- const sessions = group.sessions.filter((session) => `${session.title ?? ""} ${session.label ?? ""}`.toLocaleLowerCase().includes(needle));
3016
- return { ...group, sessions };
3017
- }).filter((group) => group.sessions.length > 0 || needle !== "" && group.name.toLocaleLowerCase().includes(needle));
3018
- if (groupMode === "list") {
3019
- const sessions = filtered.flatMap((group) => [...group.sessions]);
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
- function sessionTime(session) {
3027
- const ts = Date.parse(session.updatedAt ?? "");
3028
- return Number.isFinite(ts) ? ts : 0;
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 latestSessionTime(group) {
3031
- let latest = 0;
3032
- for (const session of group.sessions) {
3033
- const ts = sessionTime(session);
3034
- if (ts > latest) latest = ts;
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
- archived,
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, runs).map((row) => {
3071
- if (row.lastSessionId === void 0 || !keepScheduledSessionLink(row.lastSessionId, archived ?? EMPTY_SET, presentIds)) {
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
- ...openSession === void 0 ? {} : { openSession }
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
- openSession,
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: row.lastSessionId === void 0,
3185
+ disabled: openTaskSettings === void 0,
3150
3186
  onClick: () => {
3151
- if (row.lastSessionId !== void 0) openSession?.(row.lastSessionId);
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.jsxs)("span", { className: "dsh-st-overview-next", children: [
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
- ...openSession === void 0 ? {} : { openSession },
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
- ...openSession === void 0 ? {} : { openSession },
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:rgba(0,0,0,.45)}.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}
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:1px solid var(--dsw-alias-border-l2);border-radius:20px;background:var(--dsw-alias-bg-base)}
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 12px;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}
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/4;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}
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-next{display:inline-flex;grid-column:2;grid-row:2;flex:none;min-width:0;flex-direction:row;align-items:baseline;gap:4px;color:var(--dsw-alias-label-tertiary,#8b8f98);font-size:10px;line-height:14px;white-space:nowrap}
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: (request) => {
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"),