@michengai/dsh-automation 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -31
- package/README.zh-CN.md +50 -27
- package/assets/branding/dsh-banner.png +0 -0
- package/assets/screenshots/chat-approval.png +0 -0
- package/assets/screenshots/chat-create.png +0 -0
- package/assets/screenshots/chat-created.png +0 -0
- package/assets/screenshots/settings-runs.png +0 -0
- package/assets/screenshots/settings-tasks.png +0 -0
- package/assets/screenshots/workspace-scheduled.png +0 -0
- package/docs/00-/344/272/244/346/216/245/345/205/245/345/217/243/02-/345/275/223/345/211/215/347/212/266/346/200/201.md +2 -3
- package/docs/00-/344/272/244/346/216/245/345/205/245/345/217/243/03-/345/276/205/345/212/236/344/270/216/351/230/273/345/241/236.md +2 -2
- package/docs/01-/345/275/223/345/211/215/345/267/245/344/275/234/I001-/344/273/273/345/212/241/350/207/252/345/212/250/345/214/226/346/217/222/344/273/266/00-/350/277/255/344/273/243/346/200/273/350/247/210.md +10 -4
- package/lib/client.js +746 -424
- package/lib/client.js.map +4 -4
- package/lib/index.js +46 -5
- package/lib/types/client/AutomationView.d.ts +1 -1
- package/lib/types/client/ScheduleRail.d.ts +2 -2
- package/lib/types/client/contracts.d.ts +12 -0
- package/lib/types/client/create-modal-logic.d.ts +7 -0
- package/lib/types/client/create-modal.d.ts +2 -1
- package/lib/types/client/icons.d.ts +6 -0
- package/lib/types/client/locales.d.ts +18 -2
- package/lib/types/client/native-session-list.d.ts +1 -1
- package/lib/types/client/native-session-menu.d.ts +43 -4
- package/lib/types/client/schedule-rail-model.d.ts +46 -7
- package/lib/types/client/workspace-toolbar.d.ts +13 -0
- package/lib/types/index.d.ts +18 -1
- package/lib/types/prompt.d.ts +6 -0
- package/package.json +2 -6
package/lib/client.js
CHANGED
|
@@ -27,7 +27,7 @@ __export(index_exports, {
|
|
|
27
27
|
name: () => name
|
|
28
28
|
});
|
|
29
29
|
module.exports = __toCommonJS(index_exports);
|
|
30
|
-
var
|
|
30
|
+
var import_react7 = require("react");
|
|
31
31
|
|
|
32
32
|
// src/client/AutomationView.tsx
|
|
33
33
|
var import_react3 = require("react");
|
|
@@ -323,14 +323,32 @@ function SparkleIcon(props) {
|
|
|
323
323
|
function FillIcon({ children, width = 16, height = 16 }) {
|
|
324
324
|
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 });
|
|
325
325
|
}
|
|
326
|
+
function CloseOutlineIcon(props) {
|
|
327
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(FillIcon, { ...props, children: [
|
|
328
|
+
/* @__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" }),
|
|
329
|
+
/* @__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" })
|
|
330
|
+
] });
|
|
331
|
+
}
|
|
332
|
+
function CheckOutlineIcon(props) {
|
|
333
|
+
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" }) });
|
|
334
|
+
}
|
|
335
|
+
function SearchOutlineIcon(props) {
|
|
336
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(FillIcon, { ...props, children: [
|
|
337
|
+
/* @__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" }),
|
|
338
|
+
/* @__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" })
|
|
339
|
+
] });
|
|
340
|
+
}
|
|
341
|
+
function SlidersIcon(props) {
|
|
342
|
+
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" }) });
|
|
343
|
+
}
|
|
326
344
|
function FolderClosedIcon(props) {
|
|
327
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FillIcon, { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor",
|
|
345
|
+
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" }) });
|
|
328
346
|
}
|
|
329
347
|
function FolderOpenIcon(props) {
|
|
330
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
|
|
348
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(FillIcon, { ...props, children: [
|
|
349
|
+
/* @__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" }),
|
|
350
|
+
/* @__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" })
|
|
351
|
+
] });
|
|
334
352
|
}
|
|
335
353
|
function EllipsisIcon(props) {
|
|
336
354
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(FillIcon, { ...props, children: [
|
|
@@ -379,6 +397,13 @@ function RunningStateDot() {
|
|
|
379
397
|
// src/client/create-modal.tsx
|
|
380
398
|
var import_react2 = require("react");
|
|
381
399
|
|
|
400
|
+
// src/client/create-modal-logic.ts
|
|
401
|
+
async function adoptPickedWorkspace(input) {
|
|
402
|
+
const path = await input.pick();
|
|
403
|
+
if (path == null || path.trim() === "") return null;
|
|
404
|
+
return input.add(path.trim());
|
|
405
|
+
}
|
|
406
|
+
|
|
382
407
|
// src/client/menu.tsx
|
|
383
408
|
var import_react = require("react");
|
|
384
409
|
var import_react_dom = require("react-dom");
|
|
@@ -598,12 +623,11 @@ function CreateModal({
|
|
|
598
623
|
editing,
|
|
599
624
|
onClose,
|
|
600
625
|
onSubmit,
|
|
601
|
-
onAddWorkspace
|
|
626
|
+
onAddWorkspace,
|
|
627
|
+
pickWorkspaceDirectory
|
|
602
628
|
}) {
|
|
603
629
|
const [form, setForm] = (0, import_react2.useState)(() => ({ ...defaultFormState(/* @__PURE__ */ new Date(), workspaces, defaultModel), ...draft }));
|
|
604
630
|
const [validationError, setValidationError] = (0, import_react2.useState)();
|
|
605
|
-
const [addingWorkspace, setAddingWorkspace] = (0, import_react2.useState)(false);
|
|
606
|
-
const [workspacePath, setWorkspacePath] = (0, import_react2.useState)("");
|
|
607
631
|
const update = (patch) => {
|
|
608
632
|
setForm((current) => ({ ...current, ...patch }));
|
|
609
633
|
setValidationError(void 0);
|
|
@@ -656,206 +680,177 @@ function CreateModal({
|
|
|
656
680
|
caretRef.current = next.caret;
|
|
657
681
|
});
|
|
658
682
|
};
|
|
659
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
660
|
-
"
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
onClose()
|
|
667
|
-
},
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
683
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-st-mask", role: "presentation", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(MenuHostProvider, { host: menuHost, children: [
|
|
684
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("form", { className: "dsh-st-modal", onClick: (event) => event.stopPropagation(), onSubmit: handleSubmit, children: [
|
|
685
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dsh-st-modal-head", children: [
|
|
686
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
687
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { children: editing === true ? t("modal.edit") : t("modal.title") }),
|
|
688
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: t("form.subtitle") })
|
|
689
|
+
] }),
|
|
690
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "dsh-st-icon", onClick: onClose, "aria-label": t("form.cancel"), children: "\xD7" })
|
|
691
|
+
] }),
|
|
692
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "dsh-st-field", children: [
|
|
693
|
+
t("form.name"),
|
|
694
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { value: form.name, placeholder: t("form.namePlaceholder"), onChange: (event) => update({ name: event.target.value }) })
|
|
695
|
+
] }),
|
|
696
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dsh-st-field", children: [
|
|
697
|
+
t("form.planTime"),
|
|
698
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dsh-st-inline", children: [
|
|
699
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
700
|
+
MenuSelect,
|
|
701
|
+
{
|
|
702
|
+
value: form.scheduleKind,
|
|
703
|
+
options: KINDS.map((kind) => ({ value: kind, label: t(`form.${kind}`) })),
|
|
704
|
+
onChange: (value) => update({ scheduleKind: value })
|
|
705
|
+
}
|
|
706
|
+
),
|
|
707
|
+
form.scheduleKind === "once" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
708
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "date", min: today, value: datePart, onChange: (event) => update({ onceAt: clampOnceAt(`${event.target.value}T${timePart}`) }) }),
|
|
709
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TimeSelect, { value: timePart, ...minOnceTime === void 0 ? {} : { minTime: minOnceTime }, onChange: (value) => update({ onceAt: clampOnceAt(`${datePart}T${value}`) }) })
|
|
676
710
|
] }),
|
|
677
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
678
|
-
|
|
679
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("
|
|
711
|
+
form.scheduleKind === "interval" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
712
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { className: "is-narrow", type: "number", min: 5, value: form.everyMinutes, onChange: (event) => update({ everyMinutes: event.target.value }) }),
|
|
713
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-st-suffix", children: t("form.minutesShort") })
|
|
680
714
|
] }),
|
|
681
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
682
|
-
|
|
683
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.
|
|
684
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
685
|
-
MenuSelect,
|
|
686
|
-
{
|
|
687
|
-
value: form.scheduleKind,
|
|
688
|
-
options: KINDS.map((kind) => ({ value: kind, label: t(`form.${kind}`) })),
|
|
689
|
-
onChange: (value) => update({ scheduleKind: value })
|
|
690
|
-
}
|
|
691
|
-
),
|
|
692
|
-
form.scheduleKind === "once" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
693
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "date", min: today, value: datePart, onChange: (event) => update({ onceAt: clampOnceAt(`${event.target.value}T${timePart}`) }) }),
|
|
694
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TimeSelect, { value: timePart, ...minOnceTime === void 0 ? {} : { minTime: minOnceTime }, onChange: (value) => update({ onceAt: clampOnceAt(`${datePart}T${value}`) }) })
|
|
695
|
-
] }),
|
|
696
|
-
form.scheduleKind === "interval" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
697
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { className: "is-narrow", type: "number", min: 5, value: form.everyMinutes, onChange: (event) => update({ everyMinutes: event.target.value }) }),
|
|
698
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-st-suffix", children: t("form.minutesShort") })
|
|
699
|
-
] }),
|
|
700
|
-
form.scheduleKind === "hourly" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
701
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MenuSelect, { value: form.hourlyMinute, options: MINUTES.map((item) => ({ value: item, label: item })), onChange: (value) => update({ hourlyMinute: value }) }),
|
|
702
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-st-suffix", children: t("form.minutesShort") })
|
|
703
|
-
] }),
|
|
704
|
-
(form.scheduleKind === "daily" || form.scheduleKind === "weekly") && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TimeSelect, { value: form.time, onChange: (value) => update({ time: value }) }),
|
|
705
|
-
form.scheduleKind === "monthly" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
706
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
707
|
-
MenuSelect,
|
|
708
|
-
{
|
|
709
|
-
value: form.monthDay,
|
|
710
|
-
options: Array.from({ length: 31 }, (_, index) => {
|
|
711
|
-
const day = String(index + 1);
|
|
712
|
-
return { value: day, label: t("form.monthDay", { day }) };
|
|
713
|
-
}),
|
|
714
|
-
onChange: (value) => update({ monthDay: value })
|
|
715
|
-
}
|
|
716
|
-
),
|
|
717
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TimeSelect, { value: form.time, onChange: (value) => update({ time: value }) })
|
|
718
|
-
] }),
|
|
719
|
-
form.scheduleKind === "custom" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
720
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { className: "is-narrow", type: "number", min: 1, value: form.customDays, onChange: (event) => update({ customDays: event.target.value }) }),
|
|
721
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-st-suffix", children: t("form.daysShort") }),
|
|
722
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TimeSelect, { value: form.time, onChange: (value) => update({ time: value }) })
|
|
723
|
-
] })
|
|
724
|
-
] })
|
|
715
|
+
form.scheduleKind === "hourly" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
716
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MenuSelect, { value: form.hourlyMinute, options: MINUTES.map((item) => ({ value: item, label: item })), onChange: (value) => update({ hourlyMinute: value }) }),
|
|
717
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-st-suffix", children: t("form.minutesShort") })
|
|
725
718
|
] }),
|
|
726
|
-
form.scheduleKind === "weekly" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
},
|
|
787
|
-
item.id
|
|
788
|
-
))
|
|
789
|
-
] }),
|
|
719
|
+
(form.scheduleKind === "daily" || form.scheduleKind === "weekly") && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TimeSelect, { value: form.time, onChange: (value) => update({ time: value }) }),
|
|
720
|
+
form.scheduleKind === "monthly" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
721
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
722
|
+
MenuSelect,
|
|
723
|
+
{
|
|
724
|
+
value: form.monthDay,
|
|
725
|
+
options: Array.from({ length: 31 }, (_, index) => {
|
|
726
|
+
const day = String(index + 1);
|
|
727
|
+
return { value: day, label: t("form.monthDay", { day }) };
|
|
728
|
+
}),
|
|
729
|
+
onChange: (value) => update({ monthDay: value })
|
|
730
|
+
}
|
|
731
|
+
),
|
|
732
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TimeSelect, { value: form.time, onChange: (value) => update({ time: value }) })
|
|
733
|
+
] }),
|
|
734
|
+
form.scheduleKind === "custom" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
735
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { className: "is-narrow", type: "number", min: 1, value: form.customDays, onChange: (event) => update({ customDays: event.target.value }) }),
|
|
736
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-st-suffix", children: t("form.daysShort") }),
|
|
737
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TimeSelect, { value: form.time, onChange: (value) => update({ time: value }) })
|
|
738
|
+
] })
|
|
739
|
+
] })
|
|
740
|
+
] }),
|
|
741
|
+
form.scheduleKind === "weekly" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-st-weekdays", children: WEEKDAYS.map((day) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
742
|
+
"button",
|
|
743
|
+
{
|
|
744
|
+
type: "button",
|
|
745
|
+
className: form.weekdays.includes(day) ? "is-on" : "",
|
|
746
|
+
onClick: () => update({
|
|
747
|
+
weekdays: form.weekdays.includes(day) ? form.weekdays.filter((value) => value !== day) : [...form.weekdays, day]
|
|
748
|
+
}),
|
|
749
|
+
children: t(`day.${day}`)
|
|
750
|
+
},
|
|
751
|
+
day
|
|
752
|
+
)) }),
|
|
753
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dsh-st-field", children: [
|
|
754
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: t("form.prompt") }),
|
|
755
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dsh-st-prompt-card", children: [
|
|
756
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("textarea", { ref: promptRef, value: form.prompt, placeholder: t("form.promptPlaceholder"), onChange: (event) => {
|
|
757
|
+
rememberCaret();
|
|
758
|
+
update({ prompt: event.target.value });
|
|
759
|
+
}, onSelect: rememberCaret, onClick: rememberCaret, onKeyUp: rememberCaret }),
|
|
760
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dsh-st-composer", children: [
|
|
761
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dsh-st-composer-left", children: [
|
|
762
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(MenuPanel, { ghost: true, up: true, label: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
763
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(FolderIcon, { width: 14, height: 14 }),
|
|
764
|
+
workspace?.title || t("form.workspace")
|
|
765
|
+
] }), children: [
|
|
766
|
+
workspaces.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-st-select-empty", children: t("form.error.workspace") }),
|
|
767
|
+
workspaces.map((item) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
768
|
+
MenuRow,
|
|
769
|
+
{
|
|
770
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(FolderIcon, { width: 14, height: 14 }),
|
|
771
|
+
label: item.title,
|
|
772
|
+
active: item.id === form.workspaceId,
|
|
773
|
+
onClick: () => update({ workspaceId: item.id })
|
|
774
|
+
},
|
|
775
|
+
item.id
|
|
776
|
+
)),
|
|
777
|
+
pickWorkspaceDirectory !== void 0 && onAddWorkspace !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
778
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-st-menu-split" }),
|
|
790
779
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
791
|
-
|
|
780
|
+
MenuRow,
|
|
792
781
|
{
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
782
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PlusIcon, { width: 14, height: 14 }),
|
|
783
|
+
label: t("form.addWorkspace"),
|
|
784
|
+
onClick: () => {
|
|
785
|
+
void (async () => {
|
|
786
|
+
try {
|
|
787
|
+
const id = await adoptPickedWorkspace({
|
|
788
|
+
pick: pickWorkspaceDirectory,
|
|
789
|
+
add: onAddWorkspace
|
|
790
|
+
});
|
|
791
|
+
if (id !== null) update({ workspaceId: id });
|
|
792
|
+
} catch (caught) {
|
|
793
|
+
setValidationError(caught instanceof Error ? caught.message : t("error.action"));
|
|
794
|
+
}
|
|
795
|
+
})();
|
|
796
|
+
}
|
|
803
797
|
}
|
|
804
798
|
)
|
|
805
|
-
] })
|
|
806
|
-
|
|
807
|
-
|
|
799
|
+
] })
|
|
800
|
+
] }),
|
|
801
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(MenuPanel, { ghost: true, up: true, label: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
802
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SparkleIcon, { width: 14, height: 14 }),
|
|
803
|
+
t("form.skills")
|
|
804
|
+
] }), children: [
|
|
805
|
+
skills.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-st-select-empty", children: t("form.skillsEmpty") }),
|
|
806
|
+
skills.map((item) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
807
|
+
MenuRow,
|
|
808
808
|
{
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
) })
|
|
817
|
-
] })
|
|
818
|
-
] })
|
|
819
|
-
] }),
|
|
820
|
-
addingWorkspace && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dsh-st-subdialog", children: [
|
|
821
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: t("form.addWorkspace") }),
|
|
822
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "dsh-st-field", children: [
|
|
823
|
-
t("form.workspacePath"),
|
|
824
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { value: workspacePath, placeholder: t("form.workspacePathPlaceholder"), onChange: (event) => setWorkspacePath(event.target.value) })
|
|
825
|
-
] }),
|
|
826
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dsh-st-modal-actions", children: [
|
|
827
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "dsh-st-btn", onClick: () => setAddingWorkspace(false), children: t("form.cancel") }),
|
|
809
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SparkleIcon, { width: 14, height: 14 }),
|
|
810
|
+
label: item.name,
|
|
811
|
+
onClick: () => insertSkill(item)
|
|
812
|
+
},
|
|
813
|
+
item.id
|
|
814
|
+
))
|
|
815
|
+
] }),
|
|
828
816
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
829
|
-
|
|
817
|
+
MenuSelect,
|
|
830
818
|
{
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
setValidationError(caught instanceof Error ? caught.message : t("error.action"));
|
|
842
|
-
}
|
|
843
|
-
},
|
|
844
|
-
children: t("modal.save")
|
|
819
|
+
pill: true,
|
|
820
|
+
up: true,
|
|
821
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ShieldIcon, { width: 14, height: 14 }),
|
|
822
|
+
value: form.permission,
|
|
823
|
+
options: [
|
|
824
|
+
{ value: "read-only", label: t("form.readOnly"), icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ShieldIcon, { width: 14, height: 14 }) },
|
|
825
|
+
{ value: "workspace-write", label: t("form.workspaceWrite"), icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ShieldIcon, { width: 14, height: 14 }) },
|
|
826
|
+
{ value: "full-access", label: t("form.fullAccess"), icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ShieldIcon, { width: 14, height: 14 }) }
|
|
827
|
+
],
|
|
828
|
+
onChange: (value) => update({ permission: value })
|
|
845
829
|
}
|
|
846
830
|
)
|
|
847
|
-
] })
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
831
|
+
] }),
|
|
832
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-st-composer-right", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
833
|
+
ModelPicker,
|
|
834
|
+
{
|
|
835
|
+
t,
|
|
836
|
+
models,
|
|
837
|
+
modelKey: form.modelKey,
|
|
838
|
+
effort: form.reasoningEffort,
|
|
839
|
+
onModelKey: (value) => update({ modelKey: value }),
|
|
840
|
+
onEffort: (value) => update({ reasoningEffort: value })
|
|
841
|
+
}
|
|
842
|
+
) })
|
|
853
843
|
] })
|
|
854
|
-
] })
|
|
855
|
-
|
|
844
|
+
] })
|
|
845
|
+
] }),
|
|
846
|
+
validationError !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "dsh-st-error", children: validationError }),
|
|
847
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dsh-st-modal-actions", children: [
|
|
848
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "dsh-st-btn", onClick: onClose, disabled: busy, children: t("form.cancel") }),
|
|
849
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "submit", className: "dsh-st-btn dsh-st-btn--primary", disabled: busy, children: t("modal.save") })
|
|
856
850
|
] })
|
|
857
|
-
}
|
|
858
|
-
|
|
851
|
+
] }),
|
|
852
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-st-flyout-root", ref: setMenuHost })
|
|
853
|
+
] }) });
|
|
859
854
|
}
|
|
860
855
|
function ModelPicker({
|
|
861
856
|
t,
|
|
@@ -1160,7 +1155,7 @@ var EXAMPLES = [
|
|
|
1160
1155
|
{ name: "\u6BCF\u5468\u4F9D\u8D56\u5DE1\u68C0", scheduleKind: "weekly", time: "10:00", weekdays: [1] },
|
|
1161
1156
|
{ name: "\u5DE5\u4F5C\u65E5\u65E9\u62A5", scheduleKind: "weekly", time: "08:00", weekdays: [1, 2, 3, 4, 5] }
|
|
1162
1157
|
];
|
|
1163
|
-
function AutomationView({ t, runtime, closeSettings }) {
|
|
1158
|
+
function AutomationView({ t, runtime, closeSettings, pickWorkspaceDirectory }) {
|
|
1164
1159
|
const state = (0, import_react3.useSyncExternalStore)(runtime.source.subscribe, runtime.source.getSnapshot, runtime.source.getSnapshot);
|
|
1165
1160
|
const [tab, setTab] = (0, import_react3.useState)("mine");
|
|
1166
1161
|
const [query, setQuery] = (0, import_react3.useState)("");
|
|
@@ -1334,6 +1329,7 @@ function AutomationView({ t, runtime, closeSettings }) {
|
|
|
1334
1329
|
defaultModel: snapshot?.defaultModel ?? null,
|
|
1335
1330
|
skills: snapshot?.skills ?? [],
|
|
1336
1331
|
onAddWorkspace: async (path) => runtime.addWorkspace(path).then((value) => value.id),
|
|
1332
|
+
...pickWorkspaceDirectory === void 0 ? {} : { pickWorkspaceDirectory },
|
|
1337
1333
|
editing: editingId !== void 0,
|
|
1338
1334
|
...draft === void 0 ? {} : { draft },
|
|
1339
1335
|
onClose: closeModal,
|
|
@@ -1436,6 +1432,17 @@ var en = {
|
|
|
1436
1432
|
"sidebar.tasksEmpty": "No web tasks yet.",
|
|
1437
1433
|
"sidebar.ungrouped": "Ungrouped",
|
|
1438
1434
|
"sidebar.section": "Scheduled",
|
|
1435
|
+
"sidebar.workspaces": "Workspaces",
|
|
1436
|
+
"sidebar.search": "Search",
|
|
1437
|
+
"sidebar.searchSessions": "Search sessions...",
|
|
1438
|
+
"sidebar.clearSearch": "Clear search",
|
|
1439
|
+
"sidebar.filter": "Filter",
|
|
1440
|
+
"sidebar.groupBy": "Group by",
|
|
1441
|
+
"sidebar.groupWorkspace": "By workspace",
|
|
1442
|
+
"sidebar.groupList": "Single list",
|
|
1443
|
+
"sidebar.sortBy": "Sort by",
|
|
1444
|
+
"sidebar.sortManual": "Manual",
|
|
1445
|
+
"sidebar.sortTime": "Recently updated",
|
|
1439
1446
|
"header.lead": "Plan automatic tasks, or trigger them by hand. Describe the recurring work in any chat to create it quickly.",
|
|
1440
1447
|
"examples.title": "Recommended examples",
|
|
1441
1448
|
"examples.1.title": "Daily regression check",
|
|
@@ -1454,8 +1461,13 @@ var en = {
|
|
|
1454
1461
|
"session.rename": "Rename",
|
|
1455
1462
|
"session.fork": "Fork session",
|
|
1456
1463
|
"session.archive": "Archive session",
|
|
1457
|
-
"session.
|
|
1458
|
-
"session.
|
|
1464
|
+
"session.idle": "Idle",
|
|
1465
|
+
"session.runningStatus": "Running",
|
|
1466
|
+
"session.delete": "Remove from Scheduled",
|
|
1467
|
+
"session.deleteFolder": "Remove folder",
|
|
1468
|
+
"session.confirmDeleteFolder": "Remove this folder from Scheduled?",
|
|
1469
|
+
"session.confirmDeleteFolderHint": 'This only unlists {count} session(s) in "{name}" from Scheduled. Host sessions are not deleted and they stay hidden from Tasks.',
|
|
1470
|
+
"session.confirmDeleteFolderAction": "Remove from Scheduled",
|
|
1459
1471
|
"history.range.day": "By day",
|
|
1460
1472
|
"history.range.week": "By week",
|
|
1461
1473
|
"history.range.month": "By month",
|
|
@@ -1620,6 +1632,17 @@ var zh = {
|
|
|
1620
1632
|
"sidebar.tasksEmpty": "\u6682\u65E0\u7F51\u9875\u4EFB\u52A1",
|
|
1621
1633
|
"sidebar.ungrouped": "\u672A\u5206\u7EC4",
|
|
1622
1634
|
"sidebar.section": "\u5B9A\u65F6\u4EFB\u52A1",
|
|
1635
|
+
"sidebar.workspaces": "\u5DE5\u4F5C\u533A",
|
|
1636
|
+
"sidebar.search": "\u641C\u7D22",
|
|
1637
|
+
"sidebar.searchSessions": "\u641C\u7D22\u4F1A\u8BDD...",
|
|
1638
|
+
"sidebar.clearSearch": "\u6E05\u9664\u641C\u7D22",
|
|
1639
|
+
"sidebar.filter": "\u7B5B\u9009",
|
|
1640
|
+
"sidebar.groupBy": "\u5206\u7EC4\u65B9\u5F0F",
|
|
1641
|
+
"sidebar.groupWorkspace": "\u6309\u5DE5\u4F5C\u533A",
|
|
1642
|
+
"sidebar.groupList": "\u5355\u5217\u8868",
|
|
1643
|
+
"sidebar.sortBy": "\u6392\u5E8F\u65B9\u5F0F",
|
|
1644
|
+
"sidebar.sortManual": "\u624B\u52A8\u6392\u5E8F",
|
|
1645
|
+
"sidebar.sortTime": "\u6700\u8FD1\u66F4\u65B0",
|
|
1623
1646
|
"header.lead": "\u6309\u8BA1\u5212\u81EA\u52A8\u6267\u884C\u4EFB\u52A1\uFF0C\u4E5F\u53EF\u968F\u65F6\u624B\u52A8\u89E6\u53D1\u3002\u5728\u4EFB\u610F\u5BF9\u8BDD\u4E2D\u63CF\u8FF0\u4F60\u60F3\u5B9A\u671F\u505A\u7684\u4E8B\uFF0C\u5373\u53EF\u5FEB\u901F\u521B\u5EFA",
|
|
1624
1647
|
"examples.title": "\u63A8\u8350\u6848\u4F8B",
|
|
1625
1648
|
"examples.1.title": "\u6BCF\u65E5\u56DE\u5F52\u68C0\u67E5",
|
|
@@ -1638,8 +1661,13 @@ var zh = {
|
|
|
1638
1661
|
"session.rename": "\u91CD\u547D\u540D",
|
|
1639
1662
|
"session.fork": "\u5206\u53C9\u4F1A\u8BDD",
|
|
1640
1663
|
"session.archive": "\u5F52\u6863\u4F1A\u8BDD",
|
|
1641
|
-
"session.
|
|
1642
|
-
"session.
|
|
1664
|
+
"session.idle": "\u7A7A\u95F2",
|
|
1665
|
+
"session.runningStatus": "\u8FD0\u884C\u4E2D",
|
|
1666
|
+
"session.delete": "\u4ECE\u5B9A\u65F6\u9875\u79FB\u9664",
|
|
1667
|
+
"session.deleteFolder": "\u4ECE\u5B9A\u65F6\u9875\u79FB\u9664\u6587\u4EF6\u5939",
|
|
1668
|
+
"session.confirmDeleteFolder": "\u4ECE\u5B9A\u65F6\u9875\u79FB\u9664\u8FD9\u4E2A\u6587\u4EF6\u5939\uFF1F",
|
|
1669
|
+
"session.confirmDeleteFolderHint": "\u53EA\u4F1A\u628A\u300C{name}\u300D\u4E0B\u7684 {count} \u6761\u4F1A\u8BDD\u4ECE\u5B9A\u65F6\u9875\u6458\u6389\uFF0C\u4E0D\u4F1A\u5220\u9664\u5BBF\u4E3B Session\u3002\u4EFB\u52A1\u9875\u672C\u6765\u4E5F\u4E0D\u5C55\u793A\u8FD9\u4E9B\u81EA\u52A8\u5316\u4F1A\u8BDD\u3002",
|
|
1670
|
+
"session.confirmDeleteFolderAction": "\u4ECE\u5B9A\u65F6\u9875\u79FB\u9664",
|
|
1643
1671
|
"history.range.day": "\u6309\u5929",
|
|
1644
1672
|
"history.range.week": "\u6309\u5468",
|
|
1645
1673
|
"history.range.month": "\u6309\u6708",
|
|
@@ -1872,7 +1900,7 @@ function isForeignSidebarHost(component) {
|
|
|
1872
1900
|
}
|
|
1873
1901
|
|
|
1874
1902
|
// src/client/native-session-list.tsx
|
|
1875
|
-
var
|
|
1903
|
+
var import_react5 = require("react");
|
|
1876
1904
|
var import_react_dom2 = require("react-dom");
|
|
1877
1905
|
|
|
1878
1906
|
// src/client/native-session-menu.ts
|
|
@@ -1894,15 +1922,45 @@ function shouldCloseNativeSessionMenu(target, keepInside) {
|
|
|
1894
1922
|
return typeof box.contains === "function" && box.contains(el);
|
|
1895
1923
|
});
|
|
1896
1924
|
}
|
|
1897
|
-
function
|
|
1898
|
-
|
|
1925
|
+
function pointerPoint(event) {
|
|
1926
|
+
const x = Number(event?.clientX);
|
|
1927
|
+
const y = Number(event?.clientY);
|
|
1928
|
+
return {
|
|
1929
|
+
x: Number.isFinite(x) ? x : 8,
|
|
1930
|
+
y: Number.isFinite(y) ? y : 8
|
|
1931
|
+
};
|
|
1932
|
+
}
|
|
1933
|
+
function clampMenuPoint(x, y, width, height, viewport) {
|
|
1934
|
+
const pad = 8;
|
|
1935
|
+
const vw = viewport.width || width + pad * 2;
|
|
1936
|
+
const vh = viewport.height || height + pad * 2;
|
|
1937
|
+
return {
|
|
1938
|
+
x: Math.max(pad, Math.min(x, Math.max(pad, vw - width - pad))),
|
|
1939
|
+
y: Math.max(pad, Math.min(y, Math.max(pad, vh - height - pad)))
|
|
1940
|
+
};
|
|
1941
|
+
}
|
|
1942
|
+
function nextOpenSessionMenu(current, clicked, point) {
|
|
1943
|
+
if (current?.id === clicked) return null;
|
|
1944
|
+
return { id: clicked, x: point.x, y: point.y };
|
|
1899
1945
|
}
|
|
1900
|
-
function nativeSessionMenuStyle(
|
|
1946
|
+
function nativeSessionMenuStyle(point, size = { width: 218, height: 176 }, viewport = { width: 1e3, height: 800 }) {
|
|
1947
|
+
const pos = clampMenuPoint(point.x, point.y, size.width, size.height, viewport);
|
|
1901
1948
|
return {
|
|
1902
1949
|
position: "fixed",
|
|
1903
|
-
zIndex:
|
|
1904
|
-
|
|
1905
|
-
|
|
1950
|
+
zIndex: 4e3,
|
|
1951
|
+
left: `${Math.round(pos.x)}px`,
|
|
1952
|
+
top: `${Math.round(pos.y)}px`
|
|
1953
|
+
};
|
|
1954
|
+
}
|
|
1955
|
+
function nativeSessionHoverStyle(row, card, viewport) {
|
|
1956
|
+
const pad = 8;
|
|
1957
|
+
const left = row.right + pad;
|
|
1958
|
+
const top = row.top + card.height > viewport.height - pad ? Math.max(pad, viewport.height - card.height - pad) : Math.max(pad, row.top);
|
|
1959
|
+
return {
|
|
1960
|
+
position: "fixed",
|
|
1961
|
+
zIndex: 4100,
|
|
1962
|
+
left: `${Math.round(left)}px`,
|
|
1963
|
+
top: `${Math.round(top)}px`
|
|
1906
1964
|
};
|
|
1907
1965
|
}
|
|
1908
1966
|
function relativeTime(value) {
|
|
@@ -1911,10 +1969,10 @@ function relativeTime(value) {
|
|
|
1911
1969
|
const delta = Math.max(0, Date.now() - ts);
|
|
1912
1970
|
const min = Math.floor(delta / 6e4);
|
|
1913
1971
|
if (min < 1) return "\u521A\u521A";
|
|
1914
|
-
if (min < 60) return String(min) + "\u5206\u949F";
|
|
1972
|
+
if (min < 60) return String(min) + "\u5206\u949F\u524D";
|
|
1915
1973
|
const hour = Math.floor(min / 60);
|
|
1916
|
-
if (hour < 24) return String(hour) + "\u5C0F\u65F6";
|
|
1917
|
-
return String(Math.floor(hour / 24)) + "\u5929";
|
|
1974
|
+
if (hour < 24) return String(hour) + "\u5C0F\u65F6\u524D";
|
|
1975
|
+
return String(Math.floor(hour / 24)) + "\u5929\u524D";
|
|
1918
1976
|
}
|
|
1919
1977
|
|
|
1920
1978
|
// src/run-title.ts
|
|
@@ -1963,21 +2021,35 @@ function groupScheduledSessions(automations, runs) {
|
|
|
1963
2021
|
};
|
|
1964
2022
|
}).filter((group) => group.sessions.length > 0);
|
|
1965
2023
|
}
|
|
1966
|
-
function
|
|
2024
|
+
function collectScheduledSessionIds(runs) {
|
|
2025
|
+
const ids = /* @__PURE__ */ new Set();
|
|
2026
|
+
for (const run of runs ?? []) {
|
|
2027
|
+
const id = run.sessionId;
|
|
2028
|
+
if (typeof id === "string" && id !== "") ids.add(id);
|
|
2029
|
+
}
|
|
2030
|
+
return ids;
|
|
2031
|
+
}
|
|
2032
|
+
var AUTOMATION_TITLE_RE = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}/;
|
|
2033
|
+
function isAutomationSidebarSession(id, item, scheduledIds = /* @__PURE__ */ new Set()) {
|
|
2034
|
+
if (id.startsWith(AUTOMATION_SESSION_PREFIX) || scheduledIds.has(id)) return true;
|
|
2035
|
+
const title = String(item?.title ?? item?.displayTitle ?? "");
|
|
2036
|
+
return AUTOMATION_TITLE_RE.test(title);
|
|
2037
|
+
}
|
|
2038
|
+
function isNativeTaskSession(item, scheduledIds = /* @__PURE__ */ new Set()) {
|
|
1967
2039
|
if (item === void 0 || item.blank === true) return false;
|
|
1968
2040
|
if (item.origin === "im" || item.origin === "subagent") return false;
|
|
1969
2041
|
const id = item.id ?? "";
|
|
1970
2042
|
if (id.startsWith("im:")) return false;
|
|
1971
|
-
if (id
|
|
2043
|
+
if (isAutomationSidebarSession(id, item, scheduledIds)) return false;
|
|
1972
2044
|
return true;
|
|
1973
2045
|
}
|
|
1974
|
-
function groupNativeTaskSessions(sessions, workspaces, ungroupedLabel) {
|
|
2046
|
+
function groupNativeTaskSessions(sessions, workspaces, ungroupedLabel, scheduledIds = /* @__PURE__ */ new Set()) {
|
|
1975
2047
|
const byId = sessions.byId ?? {};
|
|
1976
2048
|
const archived = new Set(workspaces?.archivedSessionIds ?? []);
|
|
1977
2049
|
const assigned = /* @__PURE__ */ new Set();
|
|
1978
2050
|
const groups = [];
|
|
1979
2051
|
for (const workspace of workspaces?.items ?? []) {
|
|
1980
|
-
const items = (workspace.sessionIds ?? []).map((id) => byId[id]).filter((item) => item !== void 0 && item.id !== void 0 && isNativeTaskSession(item) && !archived.has(item.id));
|
|
2052
|
+
const items = (workspace.sessionIds ?? []).map((id) => byId[id]).filter((item) => item !== void 0 && item.id !== void 0 && isNativeTaskSession(item, scheduledIds) && !archived.has(item.id));
|
|
1981
2053
|
for (const item of items) {
|
|
1982
2054
|
if (item.id !== void 0) assigned.add(item.id);
|
|
1983
2055
|
}
|
|
@@ -1989,7 +2061,7 @@ function groupNativeTaskSessions(sessions, workspaces, ungroupedLabel) {
|
|
|
1989
2061
|
});
|
|
1990
2062
|
}
|
|
1991
2063
|
}
|
|
1992
|
-
const ungrouped = (sessions.ids ?? []).map((id) => byId[id]).filter((item) => item !== void 0 && item.id !== void 0 && !assigned.has(item.id) && isNativeTaskSession(item) && !archived.has(item.id));
|
|
2064
|
+
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));
|
|
1993
2065
|
if (ungrouped.length > 0) groups.push({ id: "", label: ungroupedLabel, sessions: ungrouped });
|
|
1994
2066
|
return groups;
|
|
1995
2067
|
}
|
|
@@ -1997,9 +2069,29 @@ function readNativeSidebarTab(raw) {
|
|
|
1997
2069
|
if (raw === "channels" || raw === "schedule" || raw === "tasks") return raw;
|
|
1998
2070
|
return "tasks";
|
|
1999
2071
|
}
|
|
2000
|
-
function
|
|
2072
|
+
function shouldFollowSessionTab(previousCurrent, current) {
|
|
2073
|
+
const prev = previousCurrent ?? "";
|
|
2074
|
+
const next = current ?? "";
|
|
2075
|
+
return next !== "" && prev !== next;
|
|
2076
|
+
}
|
|
2077
|
+
function ownedSidebarTabIds(input) {
|
|
2078
|
+
const ids = ["tasks"];
|
|
2079
|
+
for (const id of input.extraTabIds) {
|
|
2080
|
+
if (id === "" || id === "tasks" || id === "schedule" || ids.includes(id)) continue;
|
|
2081
|
+
ids.push(id);
|
|
2082
|
+
}
|
|
2083
|
+
if (input.channelsReady && !ids.includes("channels")) ids.push("channels");
|
|
2084
|
+
ids.push("schedule");
|
|
2085
|
+
return ids;
|
|
2086
|
+
}
|
|
2087
|
+
function resolveVisibleSidebarTab(input) {
|
|
2088
|
+
if (input.extraTabIds.includes(input.tab)) return input.tab;
|
|
2089
|
+
if (input.tab === "channels" && !input.channelsReady) return "tasks";
|
|
2090
|
+
return input.tab;
|
|
2091
|
+
}
|
|
2092
|
+
function tabForSessionId(sessionId, scheduledIds) {
|
|
2001
2093
|
if (sessionId === void 0 || sessionId === null || sessionId === "") return void 0;
|
|
2002
|
-
if (sessionId.startsWith(AUTOMATION_SESSION_PREFIX)) return "schedule";
|
|
2094
|
+
if (scheduledIds !== void 0 ? scheduledIds.has(sessionId) : sessionId.startsWith(AUTOMATION_SESSION_PREFIX)) return "schedule";
|
|
2003
2095
|
if (sessionId.startsWith("im:")) return "channels";
|
|
2004
2096
|
return void 0;
|
|
2005
2097
|
}
|
|
@@ -2015,41 +2107,77 @@ function slotOccupantName(item) {
|
|
|
2015
2107
|
function hasCodexUiSidebar(entries) {
|
|
2016
2108
|
return (entries ?? []).some((item) => occupantLooksLikeCodexUi(slotOccupantName(item)));
|
|
2017
2109
|
}
|
|
2018
|
-
|
|
2110
|
+
var taskFilterCache = /* @__PURE__ */ new WeakMap();
|
|
2111
|
+
var workspaceFilterCache = /* @__PURE__ */ new WeakMap();
|
|
2112
|
+
function scheduledCacheKey(scheduledIds) {
|
|
2113
|
+
if (scheduledIds.size === 0) return "";
|
|
2114
|
+
return [...scheduledIds].sort().join("\0");
|
|
2115
|
+
}
|
|
2116
|
+
function filterTaskSessionState(state, scheduledIds = /* @__PURE__ */ new Set()) {
|
|
2019
2117
|
const src = state ?? { ids: [], byId: {}, current: null };
|
|
2118
|
+
const key = scheduledCacheKey(scheduledIds);
|
|
2119
|
+
if (typeof src === "object" && src !== null) {
|
|
2120
|
+
const hit = taskFilterCache.get(src);
|
|
2121
|
+
if (hit !== void 0 && hit.key === key) return hit.result;
|
|
2122
|
+
}
|
|
2020
2123
|
const ids = (src.ids ?? []).filter((id) => {
|
|
2021
2124
|
const value = String(id);
|
|
2022
|
-
return !value.startsWith(
|
|
2125
|
+
return !value.startsWith("im:") && !isAutomationSidebarSession(value, src.byId?.[value], scheduledIds);
|
|
2023
2126
|
});
|
|
2024
|
-
const
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
}
|
|
2029
|
-
return { ...src, ids, byId };
|
|
2127
|
+
const unchanged = ids.length === (src.ids ?? []).length;
|
|
2128
|
+
const result = unchanged ? src : { ...src, ids, byId: Object.fromEntries(ids.map((id) => [id, src.byId?.[id]]).filter((entry) => entry[1] !== void 0)) };
|
|
2129
|
+
if (typeof src === "object" && src !== null) taskFilterCache.set(src, { key, result });
|
|
2130
|
+
return result;
|
|
2030
2131
|
}
|
|
2031
2132
|
function openScheduledSession(id, openRuntime, openHost) {
|
|
2032
|
-
if (id === "") return;
|
|
2133
|
+
if (id === "") return false;
|
|
2033
2134
|
const attempts = id.startsWith(AUTOMATION_SESSION_PREFIX) || id.startsWith("im:") ? [openRuntime, openHost] : [openHost, openRuntime];
|
|
2034
2135
|
for (const attempt of attempts) {
|
|
2035
2136
|
if (typeof attempt !== "function") continue;
|
|
2036
2137
|
try {
|
|
2037
2138
|
attempt(id);
|
|
2038
|
-
return;
|
|
2139
|
+
return true;
|
|
2039
2140
|
} catch {
|
|
2040
2141
|
}
|
|
2041
2142
|
}
|
|
2143
|
+
return false;
|
|
2144
|
+
}
|
|
2145
|
+
async function ensureOpenScheduledSession(input) {
|
|
2146
|
+
const id = input.id.trim();
|
|
2147
|
+
if (id === "") return false;
|
|
2148
|
+
await input.adopt?.(id).catch(() => void 0);
|
|
2149
|
+
const listed = () => input.listed?.(id) === true;
|
|
2150
|
+
if (!listed() && input.refresh !== void 0) {
|
|
2151
|
+
await input.refresh().catch(() => void 0);
|
|
2152
|
+
}
|
|
2153
|
+
if (openScheduledSession(id, input.openRuntime, input.openHost)) return true;
|
|
2154
|
+
if (input.refresh !== void 0) {
|
|
2155
|
+
await input.refresh().catch(() => void 0);
|
|
2156
|
+
}
|
|
2157
|
+
return openScheduledSession(id, input.openRuntime, input.openHost);
|
|
2042
2158
|
}
|
|
2043
|
-
function isHiddenSidebarSessionId(id) {
|
|
2044
|
-
return id.startsWith(
|
|
2159
|
+
function isHiddenSidebarSessionId(id, scheduledIds = /* @__PURE__ */ new Set()) {
|
|
2160
|
+
return id.startsWith("im:") || isAutomationSidebarSession(id, void 0, scheduledIds);
|
|
2045
2161
|
}
|
|
2046
|
-
function filterWorkspaceListState(state) {
|
|
2162
|
+
function filterWorkspaceListState(state, scheduledIds = /* @__PURE__ */ new Set()) {
|
|
2047
2163
|
const src = state ?? { items: [], archivedSessionIds: [] };
|
|
2048
|
-
const
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2164
|
+
const key = scheduledCacheKey(scheduledIds);
|
|
2165
|
+
if (typeof src === "object" && src !== null) {
|
|
2166
|
+
const hit = workspaceFilterCache.get(src);
|
|
2167
|
+
if (hit !== void 0 && hit.key === key) return hit.result;
|
|
2168
|
+
}
|
|
2169
|
+
let changed = false;
|
|
2170
|
+
const items = (src.items ?? []).map((workspace) => {
|
|
2171
|
+
const sessionIds = (workspace.sessionIds ?? []).filter((sid) => !isHiddenSidebarSessionId(String(sid), scheduledIds));
|
|
2172
|
+
if (sessionIds.length !== (workspace.sessionIds ?? []).length) {
|
|
2173
|
+
changed = true;
|
|
2174
|
+
return { ...workspace, sessionIds };
|
|
2175
|
+
}
|
|
2176
|
+
return workspace;
|
|
2177
|
+
});
|
|
2178
|
+
const result = changed ? { ...src, items } : src;
|
|
2179
|
+
if (typeof src === "object" && src !== null) workspaceFilterCache.set(src, { key, result });
|
|
2180
|
+
return result;
|
|
2053
2181
|
}
|
|
2054
2182
|
function wrapperFlags(component) {
|
|
2055
2183
|
if (component === void 0 || component === null || typeof component !== "function" && typeof component !== "object") return {};
|
|
@@ -2089,19 +2217,140 @@ function pickWrappableWorkspacesEntry(entries) {
|
|
|
2089
2217
|
}
|
|
2090
2218
|
return void 0;
|
|
2091
2219
|
}
|
|
2220
|
+
function applyWorkspaceBrowserQuery(groups, query, sort, groupMode = "workspace") {
|
|
2221
|
+
const needle = query.trim().toLocaleLowerCase();
|
|
2222
|
+
const filtered = groups.map((group) => {
|
|
2223
|
+
if (needle === "") return group;
|
|
2224
|
+
if (group.name.toLocaleLowerCase().includes(needle)) return group;
|
|
2225
|
+
const sessions = group.sessions.filter((session) => `${session.title ?? ""} ${session.label ?? ""}`.toLocaleLowerCase().includes(needle));
|
|
2226
|
+
return { ...group, sessions };
|
|
2227
|
+
}).filter((group) => group.sessions.length > 0 || needle !== "" && group.name.toLocaleLowerCase().includes(needle));
|
|
2228
|
+
if (groupMode === "list") {
|
|
2229
|
+
const sessions = filtered.flatMap((group) => [...group.sessions]);
|
|
2230
|
+
if (sort === "time") sessions.sort((left, right) => sessionTime(right) - sessionTime(left));
|
|
2231
|
+
return sessions.length === 0 ? [] : [{ ...filtered[0], name: "", sessions }];
|
|
2232
|
+
}
|
|
2233
|
+
if (sort === "manual") return filtered;
|
|
2234
|
+
return [...filtered].sort((left, right) => latestSessionTime(right) - latestSessionTime(left));
|
|
2235
|
+
}
|
|
2236
|
+
function sessionTime(session) {
|
|
2237
|
+
const ts = Date.parse(session.updatedAt ?? "");
|
|
2238
|
+
return Number.isFinite(ts) ? ts : 0;
|
|
2239
|
+
}
|
|
2240
|
+
function latestSessionTime(group) {
|
|
2241
|
+
let latest = 0;
|
|
2242
|
+
for (const session of group.sessions) {
|
|
2243
|
+
const ts = sessionTime(session);
|
|
2244
|
+
if (ts > latest) latest = ts;
|
|
2245
|
+
}
|
|
2246
|
+
return latest;
|
|
2247
|
+
}
|
|
2092
2248
|
|
|
2093
|
-
// src/client/
|
|
2249
|
+
// src/client/workspace-toolbar.tsx
|
|
2250
|
+
var import_react4 = require("react");
|
|
2094
2251
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
2252
|
+
function officialSearchIconSize(expanded) {
|
|
2253
|
+
return expanded ? 11 : 14;
|
|
2254
|
+
}
|
|
2255
|
+
function WorkspaceToolbar({
|
|
2256
|
+
t,
|
|
2257
|
+
query,
|
|
2258
|
+
sort,
|
|
2259
|
+
groupMode,
|
|
2260
|
+
onQueryChange,
|
|
2261
|
+
onSortChange,
|
|
2262
|
+
onGroupModeChange
|
|
2263
|
+
}) {
|
|
2264
|
+
const [searching, setSearching] = (0, import_react4.useState)(query.trim() !== "");
|
|
2265
|
+
const [filterOpen, setFilterOpen] = (0, import_react4.useState)(false);
|
|
2266
|
+
const inputRef = (0, import_react4.useRef)(null);
|
|
2267
|
+
const rootRef = (0, import_react4.useRef)(null);
|
|
2268
|
+
const searchSize = officialSearchIconSize(searching);
|
|
2269
|
+
(0, import_react4.useEffect)(() => {
|
|
2270
|
+
if (searching) inputRef.current?.focus();
|
|
2271
|
+
}, [searching]);
|
|
2272
|
+
(0, import_react4.useEffect)(() => {
|
|
2273
|
+
if (!filterOpen) return;
|
|
2274
|
+
const close = (event) => {
|
|
2275
|
+
const target = event.target;
|
|
2276
|
+
if (target instanceof Node && rootRef.current?.contains(target)) return;
|
|
2277
|
+
setFilterOpen(false);
|
|
2278
|
+
};
|
|
2279
|
+
document.addEventListener("mousedown", close);
|
|
2280
|
+
return () => document.removeEventListener("mousedown", close);
|
|
2281
|
+
}, [filterOpen]);
|
|
2282
|
+
const openSearch = () => {
|
|
2283
|
+
setFilterOpen(false);
|
|
2284
|
+
setSearching(true);
|
|
2285
|
+
};
|
|
2286
|
+
const closeSearch = () => {
|
|
2287
|
+
onQueryChange("");
|
|
2288
|
+
setSearching(false);
|
|
2289
|
+
};
|
|
2290
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: searching ? "dsh-st-n-toolbar is-search" : "dsh-st-n-toolbar", ref: rootRef, children: [
|
|
2291
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "dsh-st-n-head-label", children: t("sidebar.workspaces") }),
|
|
2292
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "dsh-st-n-search-slot", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "dsh-st-n-search", onClick: openSearch, children: [
|
|
2293
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "dsh-st-n-search-btn", "aria-label": t("sidebar.search"), "aria-expanded": searching, onClick: openSearch, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SearchOutlineIcon, { width: searchSize, height: searchSize }) }),
|
|
2294
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { ref: inputRef, className: "dsh-st-n-search-input", value: query, placeholder: t("sidebar.searchSessions"), "aria-label": t("sidebar.searchSessions"), tabIndex: searching ? 0 : -1, "aria-hidden": !searching, onChange: (event) => onQueryChange(event.target.value), onKeyDown: (event) => {
|
|
2295
|
+
if (event.key === "Escape") closeSearch();
|
|
2296
|
+
} }),
|
|
2297
|
+
searching && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "dsh-st-n-search-clear", "aria-label": t("sidebar.clearSearch"), onClick: (event) => {
|
|
2298
|
+
event.stopPropagation();
|
|
2299
|
+
closeSearch();
|
|
2300
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CloseOutlineIcon, { width: 14, height: 14 }) })
|
|
2301
|
+
] }) }),
|
|
2302
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "dsh-st-n-head-acts", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "dsh-st-n-head-filter", children: [
|
|
2303
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: filterOpen ? "dsh-st-n-head-btn is-on" : "dsh-st-n-head-btn", "aria-label": t("sidebar.filter"), "aria-expanded": filterOpen, onClick: () => setFilterOpen((open) => !open), children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SlidersIcon, { width: 16, height: 16 }) }),
|
|
2304
|
+
filterOpen && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "dsh-st-n-filter-menu", role: "menu", children: [
|
|
2305
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "dsh-st-n-filter-label", children: t("sidebar.groupBy") }),
|
|
2306
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(FilterRow, { label: t("sidebar.groupWorkspace"), selected: groupMode === "workspace", onSelect: () => {
|
|
2307
|
+
onGroupModeChange("workspace");
|
|
2308
|
+
setFilterOpen(false);
|
|
2309
|
+
} }),
|
|
2310
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(FilterRow, { label: t("sidebar.groupList"), selected: groupMode === "list", onSelect: () => {
|
|
2311
|
+
onGroupModeChange("list");
|
|
2312
|
+
setFilterOpen(false);
|
|
2313
|
+
} }),
|
|
2314
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "dsh-st-n-filter-split" }),
|
|
2315
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "dsh-st-n-filter-label", children: t("sidebar.sortBy") }),
|
|
2316
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(FilterRow, { label: t("sidebar.sortManual"), selected: sort === "manual", onSelect: () => {
|
|
2317
|
+
onSortChange("manual");
|
|
2318
|
+
setFilterOpen(false);
|
|
2319
|
+
} }),
|
|
2320
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(FilterRow, { label: t("sidebar.sortTime"), selected: sort === "time", onSelect: () => {
|
|
2321
|
+
onSortChange("time");
|
|
2322
|
+
setFilterOpen(false);
|
|
2323
|
+
} })
|
|
2324
|
+
] })
|
|
2325
|
+
] }) })
|
|
2326
|
+
] });
|
|
2327
|
+
}
|
|
2328
|
+
function FilterRow({
|
|
2329
|
+
label,
|
|
2330
|
+
selected,
|
|
2331
|
+
onSelect
|
|
2332
|
+
}) {
|
|
2333
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("button", { type: "button", role: "menuitemradio", "aria-checked": selected, className: selected ? "is-on" : void 0, onClick: onSelect, children: [
|
|
2334
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: label }),
|
|
2335
|
+
selected ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CheckOutlineIcon, { width: 16, height: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "dsh-st-n-filter-tick" })
|
|
2336
|
+
] });
|
|
2337
|
+
}
|
|
2338
|
+
|
|
2339
|
+
// src/client/native-session-list.tsx
|
|
2340
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
2095
2341
|
var EMPTY_SESSION_BY_ID = {};
|
|
2096
2342
|
function NativeScheduleSessionList(props) {
|
|
2097
|
-
const { t, runtime, openSession, useSessions, useWorkspaces, renameSession, archiveSession,
|
|
2098
|
-
const state = (0,
|
|
2343
|
+
const { t, runtime, openSession, useSessions, useWorkspaces, renameSession, archiveSession, forkSession } = props;
|
|
2344
|
+
const state = (0, import_react5.useSyncExternalStore)(runtime.source.subscribe, runtime.source.getSnapshot, runtime.source.getSnapshot);
|
|
2099
2345
|
const selectedId = useSessions ? useSessions((snap) => snap?.current ?? null) : null;
|
|
2100
2346
|
const sessionById = useSessions ? useSessions((snap) => snap?.byId ?? EMPTY_SESSION_BY_ID) : EMPTY_SESSION_BY_ID;
|
|
2101
2347
|
const archivedIds = useWorkspaces ? useWorkspaces((snap) => snap?.archivedSessionIds ?? []) : [];
|
|
2102
|
-
const [folded, setFolded] = (0,
|
|
2103
|
-
const [
|
|
2104
|
-
(0,
|
|
2348
|
+
const [folded, setFolded] = (0, import_react5.useState)({});
|
|
2349
|
+
const [openMenu, setOpenMenu] = (0, import_react5.useState)(null);
|
|
2350
|
+
const [query, setQuery] = (0, import_react5.useState)("");
|
|
2351
|
+
const [sort, setSort] = (0, import_react5.useState)("time");
|
|
2352
|
+
const [groupMode, setGroupMode] = (0, import_react5.useState)("workspace");
|
|
2353
|
+
(0, import_react5.useEffect)(() => {
|
|
2105
2354
|
void runtime.refresh().catch(() => void 0);
|
|
2106
2355
|
const timer = window.setInterval(() => {
|
|
2107
2356
|
void runtime.refresh().catch(() => void 0);
|
|
@@ -2110,8 +2359,8 @@ function NativeScheduleSessionList(props) {
|
|
|
2110
2359
|
window.clearInterval(timer);
|
|
2111
2360
|
};
|
|
2112
2361
|
}, [runtime]);
|
|
2113
|
-
const archived = (0,
|
|
2114
|
-
const groups = (0,
|
|
2362
|
+
const archived = (0, import_react5.useMemo)(() => new Set(archivedIds), [archivedIds]);
|
|
2363
|
+
const groups = (0, import_react5.useMemo)(() => {
|
|
2115
2364
|
const snapshot = state.snapshot;
|
|
2116
2365
|
if (snapshot === void 0) return [];
|
|
2117
2366
|
return groupScheduledSessions(snapshot.automations, snapshot.runs).map((group) => ({
|
|
@@ -2127,84 +2376,63 @@ function NativeScheduleSessionList(props) {
|
|
|
2127
2376
|
})
|
|
2128
2377
|
})).filter((group) => group.sessions.length > 0);
|
|
2129
2378
|
}, [archived, sessionById, state.snapshot]);
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
/* @__PURE__ */ (0,
|
|
2140
|
-
|
|
2141
|
-
"
|
|
2379
|
+
const visibleGroups = (0, import_react5.useMemo)(() => applyWorkspaceBrowserQuery(groups.map((group) => ({ ...group, name: group.name })), query, sort, groupMode), [groups, query, sort, groupMode]);
|
|
2380
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-st-n", children: [
|
|
2381
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(WorkspaceToolbar, { t, query, sort, groupMode, onQueryChange: setQuery, onSortChange: setSort, onGroupModeChange: setGroupMode }),
|
|
2382
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-st-n-tree", role: "tree", children: [
|
|
2383
|
+
state.phase === "loading" && visibleGroups.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "dsh-st-n-empty", children: t("loading") }),
|
|
2384
|
+
visibleGroups.length === 0 && state.phase !== "loading" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "dsh-st-n-empty", children: t("sidebar.empty") }),
|
|
2385
|
+
visibleGroups.map((group) => {
|
|
2386
|
+
const expanded = folded[group.id] !== true;
|
|
2387
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-st-n-group", children: [
|
|
2388
|
+
groupMode === "workspace" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-st-n-row", role: "treeitem", "aria-expanded": expanded, onClick: () => setFolded((current) => ({ ...current, [group.id]: expanded })), children: [
|
|
2389
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-st-n-slot dsh-st-n-folder", children: expanded ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FolderOpenIcon, { width: 16, height: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FolderClosedIcon, { width: 16, height: 16 }) }),
|
|
2390
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-st-n-title", children: group.name })
|
|
2391
|
+
] }),
|
|
2392
|
+
(groupMode === "list" || expanded) && group.sessions.map((session) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2393
|
+
NativeSessionRow,
|
|
2142
2394
|
{
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
})();
|
|
2395
|
+
t,
|
|
2396
|
+
id: session.id,
|
|
2397
|
+
title: session.title,
|
|
2398
|
+
hoverTitle: String(sessionById[session.id]?.displayTitle ?? sessionById[session.id]?.title ?? group.name),
|
|
2399
|
+
updatedAt: session.updatedAt,
|
|
2400
|
+
running: session.running,
|
|
2401
|
+
selected: selectedId === session.id,
|
|
2402
|
+
menuOpen: openMenu?.id === session.id,
|
|
2403
|
+
menuPoint: openMenu === null || openMenu.id !== session.id ? { x: 8, y: 8 } : { x: openMenu.x, y: openMenu.y },
|
|
2404
|
+
onToggleMenu: (event) => setOpenMenu((current) => nextOpenSessionMenu(current, session.id, pointerPoint(event))),
|
|
2405
|
+
onCloseMenu: () => setOpenMenu((current) => current?.id === session.id ? null : current),
|
|
2406
|
+
onOpen: () => {
|
|
2407
|
+
setOpenMenu(null);
|
|
2408
|
+
openSession?.(session.id);
|
|
2158
2409
|
},
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
] }),
|
|
2163
|
-
expanded && group.sessions.map((session) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2164
|
-
NativeSessionRow,
|
|
2165
|
-
{
|
|
2166
|
-
t,
|
|
2167
|
-
id: session.id,
|
|
2168
|
-
title: session.title,
|
|
2169
|
-
updatedAt: session.updatedAt,
|
|
2170
|
-
running: session.running,
|
|
2171
|
-
selected: selectedId === session.id,
|
|
2172
|
-
menuOpen: openMenuId === session.id,
|
|
2173
|
-
onToggleMenu: () => setOpenMenuId((current) => nextOpenSessionMenuId(current, session.id)),
|
|
2174
|
-
onCloseMenu: () => setOpenMenuId((current) => current === session.id ? null : current),
|
|
2175
|
-
onOpen: () => {
|
|
2176
|
-
setOpenMenuId(null);
|
|
2177
|
-
openSession?.(session.id);
|
|
2178
|
-
void runtime.adoptSession?.(session.id).catch(() => void 0);
|
|
2179
|
-
},
|
|
2180
|
-
onDelete: async () => {
|
|
2181
|
-
try {
|
|
2182
|
-
await deleteSession?.(session.id);
|
|
2183
|
-
} catch {
|
|
2184
|
-
}
|
|
2185
|
-
await runtime.forgetSession(session.id);
|
|
2410
|
+
...renameSession === void 0 ? {} : { renameSession },
|
|
2411
|
+
...archiveSession === void 0 ? {} : { archiveSession },
|
|
2412
|
+
...forkSession === void 0 ? {} : { forkSession }
|
|
2186
2413
|
},
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
] }, group.id);
|
|
2194
|
-
})
|
|
2195
|
-
] }) });
|
|
2414
|
+
session.id
|
|
2415
|
+
))
|
|
2416
|
+
] }, group.id);
|
|
2417
|
+
})
|
|
2418
|
+
] })
|
|
2419
|
+
] });
|
|
2196
2420
|
}
|
|
2197
2421
|
function NativeSessionRow(props) {
|
|
2198
|
-
const { t, id, title, updatedAt, running, selected, menuOpen, onToggleMenu, onCloseMenu, onOpen,
|
|
2199
|
-
const rowRef = (0,
|
|
2200
|
-
const menuRef = (0,
|
|
2201
|
-
const
|
|
2202
|
-
const [
|
|
2203
|
-
const [
|
|
2204
|
-
(0,
|
|
2422
|
+
const { t, id, title, hoverTitle, updatedAt, running, selected, menuOpen, menuPoint, onToggleMenu, onCloseMenu, onOpen, renameSession, archiveSession, forkSession } = props;
|
|
2423
|
+
const rowRef = (0, import_react5.useRef)(null);
|
|
2424
|
+
const menuRef = (0, import_react5.useRef)(null);
|
|
2425
|
+
const hoverRef = (0, import_react5.useRef)(null);
|
|
2426
|
+
const [hoverOpen, setHoverOpen] = (0, import_react5.useState)(false);
|
|
2427
|
+
const [hoverStyle, setHoverStyle] = (0, import_react5.useState)({});
|
|
2428
|
+
const hoverTimer = (0, import_react5.useRef)(void 0);
|
|
2429
|
+
const [renaming, setRenaming] = (0, import_react5.useState)(false);
|
|
2430
|
+
const [draft, setDraft] = (0, import_react5.useState)(title);
|
|
2431
|
+
const [menuStyle, setMenuStyle] = (0, import_react5.useState)({});
|
|
2432
|
+
(0, import_react5.useEffect)(() => {
|
|
2205
2433
|
setDraft(title);
|
|
2206
2434
|
}, [title]);
|
|
2207
|
-
(0,
|
|
2435
|
+
(0, import_react5.useEffect)(() => {
|
|
2208
2436
|
if (!menuOpen) return;
|
|
2209
2437
|
const close = (event) => {
|
|
2210
2438
|
if (!shouldCloseNativeSessionMenu(event.target, [rowRef.current, menuRef.current])) return;
|
|
@@ -2220,12 +2448,12 @@ function NativeSessionRow(props) {
|
|
|
2220
2448
|
document.removeEventListener("keydown", onKey);
|
|
2221
2449
|
};
|
|
2222
2450
|
}, [menuOpen, onCloseMenu]);
|
|
2223
|
-
(0,
|
|
2451
|
+
(0, import_react5.useLayoutEffect)(() => {
|
|
2224
2452
|
if (!menuOpen) return;
|
|
2225
2453
|
const update = () => {
|
|
2226
|
-
const
|
|
2227
|
-
|
|
2228
|
-
setMenuStyle(nativeSessionMenuStyle(
|
|
2454
|
+
const el = menuRef.current;
|
|
2455
|
+
const size = el === null ? { width: 218, height: 176 } : { width: el.offsetWidth, height: el.offsetHeight };
|
|
2456
|
+
setMenuStyle(nativeSessionMenuStyle(menuPoint, size, { width: window.innerWidth, height: window.innerHeight }));
|
|
2229
2457
|
};
|
|
2230
2458
|
update();
|
|
2231
2459
|
window.addEventListener("resize", update);
|
|
@@ -2234,13 +2462,42 @@ function NativeSessionRow(props) {
|
|
|
2234
2462
|
window.removeEventListener("resize", update);
|
|
2235
2463
|
document.removeEventListener("scroll", update, true);
|
|
2236
2464
|
};
|
|
2237
|
-
}, [menuOpen]);
|
|
2465
|
+
}, [menuOpen, menuPoint]);
|
|
2466
|
+
(0, import_react5.useEffect)(() => {
|
|
2467
|
+
if (!hoverOpen || menuOpen) return;
|
|
2468
|
+
const update = () => {
|
|
2469
|
+
const row = rowRef.current?.getBoundingClientRect();
|
|
2470
|
+
const card = hoverRef.current;
|
|
2471
|
+
if (row === void 0) return;
|
|
2472
|
+
const size = card === null ? { width: 220, height: 96 } : { width: card.offsetWidth, height: card.offsetHeight };
|
|
2473
|
+
setHoverStyle(nativeSessionHoverStyle({ right: row.right, top: row.top }, size, { width: window.innerWidth, height: window.innerHeight }));
|
|
2474
|
+
};
|
|
2475
|
+
update();
|
|
2476
|
+
window.addEventListener("resize", update);
|
|
2477
|
+
document.addEventListener("scroll", update, true);
|
|
2478
|
+
return () => {
|
|
2479
|
+
window.removeEventListener("resize", update);
|
|
2480
|
+
document.removeEventListener("scroll", update, true);
|
|
2481
|
+
};
|
|
2482
|
+
}, [hoverOpen, menuOpen, title, updatedAt, running]);
|
|
2483
|
+
(0, import_react5.useEffect)(() => () => {
|
|
2484
|
+
if (hoverTimer.current !== void 0) window.clearTimeout(hoverTimer.current);
|
|
2485
|
+
}, []);
|
|
2238
2486
|
const run = (action) => {
|
|
2239
2487
|
void Promise.resolve(action()).catch(() => void 0);
|
|
2240
2488
|
};
|
|
2489
|
+
const showHover = () => {
|
|
2490
|
+
if (menuOpen) return;
|
|
2491
|
+
if (hoverTimer.current !== void 0) window.clearTimeout(hoverTimer.current);
|
|
2492
|
+
hoverTimer.current = window.setTimeout(() => setHoverOpen(true), 500);
|
|
2493
|
+
};
|
|
2494
|
+
const hideHover = () => {
|
|
2495
|
+
if (hoverTimer.current !== void 0) window.clearTimeout(hoverTimer.current);
|
|
2496
|
+
setHoverOpen(false);
|
|
2497
|
+
};
|
|
2241
2498
|
const rowClass = "dsh-st-n-sess" + (selected ? " is-on" : "") + (menuOpen ? " is-menu" : "");
|
|
2242
2499
|
if (renaming) {
|
|
2243
|
-
return /* @__PURE__ */ (0,
|
|
2500
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: rowClass, ref: rowRef, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("input", { className: "dsh-st-n-rename", value: draft, autoFocus: true, "aria-label": t("session.rename"), onChange: (event) => setDraft(event.target.value), onClick: (event) => event.stopPropagation(), onKeyDown: (event) => {
|
|
2244
2501
|
if (event.key === "Enter") {
|
|
2245
2502
|
event.preventDefault();
|
|
2246
2503
|
setRenaming(false);
|
|
@@ -2257,24 +2514,23 @@ function NativeSessionRow(props) {
|
|
|
2257
2514
|
} }) });
|
|
2258
2515
|
}
|
|
2259
2516
|
const menuItems = [
|
|
2260
|
-
{ id: "rename", label: t("session.rename"), icon: /* @__PURE__ */ (0,
|
|
2517
|
+
{ id: "rename", label: t("session.rename"), icon: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PencilIcon, { width: 16, height: 16 }), go: () => {
|
|
2261
2518
|
setRenaming(true);
|
|
2262
2519
|
} },
|
|
2263
|
-
{ id: "fork", label: t("session.fork"), icon: /* @__PURE__ */ (0,
|
|
2264
|
-
{ id: "archive", label: t("session.archive"), icon: /* @__PURE__ */ (0,
|
|
2265
|
-
{ id: "delete", label: t("session.delete"), icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TrashIcon, { width: 16, height: 16 }), danger: true, go: () => run(() => onDelete()) }
|
|
2520
|
+
{ id: "fork", label: t("session.fork"), icon: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(BranchIcon, { width: 16, height: 16 }), go: () => run(() => forkSession?.(id)) },
|
|
2521
|
+
{ id: "archive", label: t("session.archive"), icon: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ArchiveIcon, { width: 16, height: 16 }), go: () => run(() => archiveSession?.(id)) }
|
|
2266
2522
|
];
|
|
2267
2523
|
const menu = menuOpen && typeof document !== "undefined" ? (0, import_react_dom2.createPortal)(
|
|
2268
|
-
/* @__PURE__ */ (0,
|
|
2524
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { ref: menuRef, className: "dsh-st-n-menu is-float", "data-n-menu": id, style: menuStyle, onMouseDown: (event) => event.stopPropagation(), onClick: (event) => event.stopPropagation(), children: menuItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("button", { type: "button", className: void 0, onClick: () => {
|
|
2269
2525
|
onCloseMenu();
|
|
2270
2526
|
item.go();
|
|
2271
2527
|
}, children: [
|
|
2272
|
-
/* @__PURE__ */ (0,
|
|
2528
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-st-n-mi", children: item.icon }),
|
|
2273
2529
|
item.label
|
|
2274
2530
|
] }, item.id)) }),
|
|
2275
2531
|
document.body
|
|
2276
2532
|
) : null;
|
|
2277
|
-
return /* @__PURE__ */ (0,
|
|
2533
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: rowClass, ref: rowRef, role: "treeitem", tabIndex: 0, "aria-selected": selected, "data-n-menu-root": id, onClick: onOpen, onMouseEnter: showHover, onMouseLeave: hideHover, onKeyDown: (event) => {
|
|
2278
2534
|
if (event.key === "Enter" || event.key === " ") {
|
|
2279
2535
|
event.preventDefault();
|
|
2280
2536
|
onOpen();
|
|
@@ -2282,24 +2538,37 @@ function NativeSessionRow(props) {
|
|
|
2282
2538
|
}, onContextMenu: (event) => {
|
|
2283
2539
|
event.preventDefault();
|
|
2284
2540
|
event.stopPropagation();
|
|
2285
|
-
onToggleMenu();
|
|
2541
|
+
onToggleMenu(event);
|
|
2286
2542
|
}, children: [
|
|
2287
|
-
/* @__PURE__ */ (0,
|
|
2288
|
-
/* @__PURE__ */ (0,
|
|
2289
|
-
/* @__PURE__ */ (0,
|
|
2290
|
-
/* @__PURE__ */ (0,
|
|
2543
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-st-n-slot", children: running ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(RunningStateDot, {}) : null }),
|
|
2544
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-st-n-title", children: title }),
|
|
2545
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-st-n-time", children: relativeTime(updatedAt) }),
|
|
2546
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-st-n-acts", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "dsh-st-n-ico", "aria-label": title + " \u66F4\u591A", onMouseDown: (event) => event.stopPropagation(), onClick: (event) => {
|
|
2291
2547
|
event.stopPropagation();
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2548
|
+
hideHover();
|
|
2549
|
+
onToggleMenu(event);
|
|
2550
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(EllipsisIcon, { width: 16, height: 16 }) }) }),
|
|
2551
|
+
menu,
|
|
2552
|
+
hoverOpen && !menuOpen && typeof document !== "undefined" && (0, import_react_dom2.createPortal)(
|
|
2553
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { ref: hoverRef, className: "dsh-st-n-hover", style: hoverStyle, onMouseEnter: showHover, onMouseLeave: hideHover, children: [
|
|
2554
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "dsh-st-n-hover-title", children: (hoverTitle ?? title).trim() || title }),
|
|
2555
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "dsh-st-n-hover-time", children: relativeTime(updatedAt) }),
|
|
2556
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-st-n-hover-state", children: [
|
|
2557
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: running ? "dsh-st-n-hover-dot is-run" : "dsh-st-n-hover-dot" }),
|
|
2558
|
+
running ? t("session.runningStatus") : t("session.idle")
|
|
2559
|
+
] })
|
|
2560
|
+
] }),
|
|
2561
|
+
document.body
|
|
2562
|
+
)
|
|
2295
2563
|
] });
|
|
2296
2564
|
}
|
|
2297
2565
|
|
|
2298
2566
|
// src/client/ScheduleRail.tsx
|
|
2299
|
-
var
|
|
2300
|
-
var
|
|
2567
|
+
var import_react6 = require("react");
|
|
2568
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
2301
2569
|
var EMPTY_EXTRA_TABS = [];
|
|
2302
|
-
var
|
|
2570
|
+
var noopSubscribe = (_listener) => () => void 0;
|
|
2571
|
+
var OfficialTreeGuard = class extends import_react6.Component {
|
|
2303
2572
|
state = { failed: false };
|
|
2304
2573
|
static getDerivedStateFromError() {
|
|
2305
2574
|
return { failed: true };
|
|
@@ -2316,9 +2585,9 @@ function ScheduleRail({
|
|
|
2316
2585
|
runtime,
|
|
2317
2586
|
openSession
|
|
2318
2587
|
}) {
|
|
2319
|
-
const state = (0,
|
|
2320
|
-
const [folded, setFolded] = (0,
|
|
2321
|
-
(0,
|
|
2588
|
+
const state = (0, import_react6.useSyncExternalStore)(runtime.source.subscribe, runtime.source.getSnapshot, runtime.source.getSnapshot);
|
|
2589
|
+
const [folded, setFolded] = (0, import_react6.useState)({});
|
|
2590
|
+
(0, import_react6.useEffect)(() => {
|
|
2322
2591
|
void runtime.refresh().catch(() => void 0);
|
|
2323
2592
|
const timer = window.setInterval(() => {
|
|
2324
2593
|
void runtime.refresh().catch(() => void 0);
|
|
@@ -2327,36 +2596,36 @@ function ScheduleRail({
|
|
|
2327
2596
|
window.clearInterval(timer);
|
|
2328
2597
|
};
|
|
2329
2598
|
}, [runtime]);
|
|
2330
|
-
const groups = (0,
|
|
2599
|
+
const groups = (0, import_react6.useMemo)(() => {
|
|
2331
2600
|
const snapshot = state.snapshot;
|
|
2332
2601
|
if (snapshot === void 0) return [];
|
|
2333
2602
|
return groupScheduledSessions(snapshot.automations, snapshot.runs);
|
|
2334
2603
|
}, [state.snapshot]);
|
|
2335
|
-
return /* @__PURE__ */ (0,
|
|
2336
|
-
state.phase === "loading" && groups.length === 0 && /* @__PURE__ */ (0,
|
|
2337
|
-
groups.length === 0 && state.phase !== "loading" && /* @__PURE__ */ (0,
|
|
2338
|
-
groups.map((group) => /* @__PURE__ */ (0,
|
|
2339
|
-
/* @__PURE__ */ (0,
|
|
2604
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dsh-st-rail", children: [
|
|
2605
|
+
state.phase === "loading" && groups.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "dsh-st-rail-empty", children: t("loading") }),
|
|
2606
|
+
groups.length === 0 && state.phase !== "loading" && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "dsh-st-rail-empty", children: t("sidebar.empty") }),
|
|
2607
|
+
groups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("section", { className: "dsh-st-rail-group", children: [
|
|
2608
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
2340
2609
|
"button",
|
|
2341
2610
|
{
|
|
2342
2611
|
type: "button",
|
|
2343
2612
|
className: "dsh-st-rail-head",
|
|
2344
2613
|
onClick: () => setFolded((current) => ({ ...current, [group.id]: !current[group.id] })),
|
|
2345
2614
|
children: [
|
|
2346
|
-
/* @__PURE__ */ (0,
|
|
2347
|
-
/* @__PURE__ */ (0,
|
|
2615
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "dsh-st-rail-folder", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ClockIcon, { width: 16, height: 16 }) }),
|
|
2616
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "dsh-st-rail-title", children: group.name })
|
|
2348
2617
|
]
|
|
2349
2618
|
}
|
|
2350
2619
|
),
|
|
2351
|
-
folded[group.id] !== true && group.sessions.map((session) => /* @__PURE__ */ (0,
|
|
2620
|
+
folded[group.id] !== true && group.sessions.map((session) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
2352
2621
|
"button",
|
|
2353
2622
|
{
|
|
2354
2623
|
type: "button",
|
|
2355
2624
|
className: "dsh-st-rail-session",
|
|
2356
2625
|
onClick: () => openSession?.(session.id),
|
|
2357
2626
|
children: [
|
|
2358
|
-
/* @__PURE__ */ (0,
|
|
2359
|
-
session.running && /* @__PURE__ */ (0,
|
|
2627
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: session.label }),
|
|
2628
|
+
session.running && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(RunningStateDot, {})
|
|
2360
2629
|
]
|
|
2361
2630
|
},
|
|
2362
2631
|
session.id
|
|
@@ -2379,26 +2648,20 @@ function NativeScheduleShell({
|
|
|
2379
2648
|
wide
|
|
2380
2649
|
}) {
|
|
2381
2650
|
const Official = officialTree;
|
|
2382
|
-
const [tab, setTab] = (0,
|
|
2651
|
+
const [tab, setTab] = (0, import_react6.useState)(() => {
|
|
2383
2652
|
try {
|
|
2384
2653
|
return readNativeSidebarTab(window.localStorage.getItem(NATIVE_SIDEBAR_TAB_KEY));
|
|
2385
2654
|
} catch {
|
|
2386
2655
|
return "tasks";
|
|
2387
2656
|
}
|
|
2388
2657
|
});
|
|
2389
|
-
const extraTabs = (0,
|
|
2390
|
-
tabRegistry?.subscribe ??
|
|
2391
|
-
listener();
|
|
2392
|
-
return () => void 0;
|
|
2393
|
-
}),
|
|
2658
|
+
const extraTabs = (0, import_react6.useSyncExternalStore)(
|
|
2659
|
+
tabRegistry?.subscribe ?? noopSubscribe,
|
|
2394
2660
|
() => tabRegistry?.getTabs() ?? EMPTY_EXTRA_TABS,
|
|
2395
2661
|
() => EMPTY_EXTRA_TABS
|
|
2396
2662
|
);
|
|
2397
|
-
const channelsReady = (0,
|
|
2398
|
-
subscribeChannels ??
|
|
2399
|
-
listener();
|
|
2400
|
-
return () => void 0;
|
|
2401
|
-
}),
|
|
2663
|
+
const channelsReady = (0, import_react6.useSyncExternalStore)(
|
|
2664
|
+
subscribeChannels ?? noopSubscribe,
|
|
2402
2665
|
() => {
|
|
2403
2666
|
try {
|
|
2404
2667
|
return hasChannels?.() === true;
|
|
@@ -2409,26 +2672,39 @@ function NativeScheduleShell({
|
|
|
2409
2672
|
() => false
|
|
2410
2673
|
);
|
|
2411
2674
|
const currentId = useSessions?.((state) => state?.current ?? null);
|
|
2412
|
-
const
|
|
2675
|
+
const automationState = (0, import_react6.useSyncExternalStore)(runtime.source.subscribe, runtime.source.getSnapshot, runtime.source.getSnapshot);
|
|
2676
|
+
const scheduledIds = (0, import_react6.useMemo)(() => collectScheduledSessionIds(automationState.snapshot?.runs), [automationState.snapshot]);
|
|
2677
|
+
const useFilteredSessions = (0, import_react6.useCallback)((selector, eq) => {
|
|
2413
2678
|
if (useSessions === void 0) return selector({ ids: [], byId: {}, current: null });
|
|
2414
|
-
return useSessions((state) => selector(filterTaskSessionState(state)));
|
|
2415
|
-
}, [useSessions]);
|
|
2416
|
-
const useFilteredWorkspaces = (0,
|
|
2679
|
+
return useSessions((state) => selector(filterTaskSessionState(state, scheduledIds)), eq);
|
|
2680
|
+
}, [useSessions, scheduledIds]);
|
|
2681
|
+
const useFilteredWorkspaces = (0, import_react6.useCallback)((selector, eq) => {
|
|
2417
2682
|
if (useWorkspaces === void 0) return selector({ items: [], archivedSessionIds: [] });
|
|
2418
|
-
return useWorkspaces((state) => selector(filterWorkspaceListState(state)));
|
|
2419
|
-
}, [useWorkspaces]);
|
|
2420
|
-
(0,
|
|
2683
|
+
return useWorkspaces((state) => selector(filterWorkspaceListState(state, scheduledIds)), eq);
|
|
2684
|
+
}, [useWorkspaces, scheduledIds]);
|
|
2685
|
+
(0, import_react6.useEffect)(() => {
|
|
2421
2686
|
try {
|
|
2422
2687
|
window.localStorage.setItem(NATIVE_SIDEBAR_TAB_KEY, tab);
|
|
2423
2688
|
} catch {
|
|
2424
2689
|
}
|
|
2425
2690
|
}, [tab]);
|
|
2426
|
-
(0,
|
|
2427
|
-
|
|
2428
|
-
|
|
2691
|
+
const previousCurrentId = (0, import_react6.useRef)(currentId);
|
|
2692
|
+
const tabFollowReady = (0, import_react6.useRef)(false);
|
|
2693
|
+
(0, import_react6.useEffect)(() => {
|
|
2694
|
+
if (!tabFollowReady.current) {
|
|
2695
|
+
tabFollowReady.current = true;
|
|
2696
|
+
previousCurrentId.current = currentId;
|
|
2697
|
+
return;
|
|
2698
|
+
}
|
|
2699
|
+
const previous = previousCurrentId.current;
|
|
2700
|
+
previousCurrentId.current = currentId;
|
|
2701
|
+
if (!shouldFollowSessionTab(previous, currentId)) return;
|
|
2702
|
+
const next = tabForSessionId(currentId ?? void 0, scheduledIds);
|
|
2703
|
+
const extraIds = extraTabs.map((item) => item.id);
|
|
2704
|
+
if (next === "channels" && (channelsReady || extraIds.includes("channels"))) setTab("channels");
|
|
2429
2705
|
const matched = extraTabs.find((item) => currentId !== void 0 && currentId !== null && item.matchSession?.(String(currentId)) === true);
|
|
2430
|
-
if (matched !== void 0) setTab(matched.id);
|
|
2431
|
-
}, [currentId, channelsReady, extraTabs]);
|
|
2706
|
+
if (matched !== void 0 && matched.id !== "schedule") setTab(matched.id);
|
|
2707
|
+
}, [currentId, channelsReady, extraTabs, scheduledIds]);
|
|
2432
2708
|
const rawOfficialProps = { ...hostProps ?? {}, ...wide === void 0 ? {} : { wide } };
|
|
2433
2709
|
const filteredOfficialProps = {
|
|
2434
2710
|
...rawOfficialProps,
|
|
@@ -2437,19 +2713,27 @@ function NativeScheduleShell({
|
|
|
2437
2713
|
};
|
|
2438
2714
|
const renderOfficial = (props) => {
|
|
2439
2715
|
if (Official === void 0) {
|
|
2440
|
-
return /* @__PURE__ */ (0,
|
|
2716
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(NativeTaskRail, { t, ...openSession === void 0 ? {} : { openSession }, ...useSessions === void 0 ? {} : { useSessions: useFilteredSessions }, ...useWorkspaces === void 0 ? {} : { useWorkspaces } });
|
|
2441
2717
|
}
|
|
2442
|
-
return /* @__PURE__ */ (0,
|
|
2718
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(OfficialTreeGuard, { fallback: (0, import_react6.createElement)(Official, rawOfficialProps), children: (0, import_react6.createElement)(Official, props) });
|
|
2443
2719
|
};
|
|
2444
|
-
if (wide === false) return /* @__PURE__ */ (0,
|
|
2445
|
-
const
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2720
|
+
if (wide === false) return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: renderOfficial(filteredOfficialProps) });
|
|
2721
|
+
const foreignTabs = extraTabs.filter((item) => item.id !== "schedule");
|
|
2722
|
+
const visibleTab = resolveVisibleSidebarTab({
|
|
2723
|
+
tab,
|
|
2724
|
+
channelsReady,
|
|
2725
|
+
extraTabIds: ownedSidebarTabIds({ extraTabIds: foreignTabs.map((item) => item.id), channelsReady })
|
|
2726
|
+
});
|
|
2727
|
+
const hostedSchedule = extraTabs.find((item) => item.id === "schedule");
|
|
2728
|
+
const scheduleBody = hostedSchedule === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.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 });
|
|
2729
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dsh-st-shell-rail", children: [
|
|
2730
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dsh-st-shell-tabs", role: "tablist", "aria-label": t("sidebar.tabs"), children: [
|
|
2731
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", role: "tab", "aria-selected": visibleTab === "tasks", className: visibleTab === "tasks" ? "is-on" : void 0, onClick: () => setTab("tasks"), children: t("sidebar.tasksTab") }),
|
|
2732
|
+
foreignTabs.map((item) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", role: "tab", "aria-selected": visibleTab === item.id, className: visibleTab === item.id ? "is-on" : void 0, onClick: () => setTab(item.id), children: item.label }, item.id)),
|
|
2733
|
+
channelsReady && foreignTabs.every((item) => item.id !== "channels") && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", role: "tab", "aria-selected": visibleTab === "channels", className: visibleTab === "channels" ? "is-on" : void 0, onClick: () => setTab("channels"), children: t("sidebar.channelsTab") }),
|
|
2734
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", role: "tab", "aria-selected": visibleTab === "schedule", className: visibleTab === "schedule" ? "is-on" : void 0, onClick: () => setTab("schedule"), children: t("sidebar.tab") })
|
|
2451
2735
|
] }),
|
|
2452
|
-
|
|
2736
|
+
visibleTab === "schedule" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "dsh-st-shell-body", children: scheduleBody }) : foreignTabs.find((item) => item.id === visibleTab) !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "dsh-st-shell-body", children: foreignTabs.find((item) => item.id === visibleTab)?.render({ ...hostProps ?? {}, openSession, open: openSession, useSessions, wide: true }) }) : visibleTab === "channels" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "dsh-st-shell-body", children: renderSlot?.("sidebar.channels", { ...hostProps ?? {}, openSession, open: openSession, useSessions, wide: true, skin: "native" }) }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "dsh-st-official-tree", children: renderOfficial(filteredOfficialProps) })
|
|
2453
2737
|
] });
|
|
2454
2738
|
}
|
|
2455
2739
|
function NativeTaskRail({
|
|
@@ -2461,10 +2745,10 @@ function NativeTaskRail({
|
|
|
2461
2745
|
const snap = useSessions === void 0 ? { ids: [], byId: {}, current: null } : useSessions((state) => state ?? { ids: [], byId: {}, current: null });
|
|
2462
2746
|
const workspaces = useWorkspaces === void 0 ? void 0 : useWorkspaces((state) => state ?? { items: [], archivedSessionIds: [] });
|
|
2463
2747
|
const groups = groupNativeTaskSessions(snap, workspaces, t("sidebar.ungrouped"));
|
|
2464
|
-
if (groups.length === 0) return /* @__PURE__ */ (0,
|
|
2465
|
-
return /* @__PURE__ */ (0,
|
|
2466
|
-
/* @__PURE__ */ (0,
|
|
2467
|
-
group.sessions.map((item) => /* @__PURE__ */ (0,
|
|
2748
|
+
if (groups.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "dsh-st-rail-empty", children: t("sidebar.tasksEmpty") });
|
|
2749
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "dsh-st-rail", children: groups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("section", { className: "dsh-st-rail-group", children: [
|
|
2750
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "dsh-st-rail-head is-static", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "dsh-st-rail-title", children: group.label }) }),
|
|
2751
|
+
group.sessions.map((item) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2468
2752
|
"button",
|
|
2469
2753
|
{
|
|
2470
2754
|
type: "button",
|
|
@@ -2472,7 +2756,7 @@ function NativeTaskRail({
|
|
|
2472
2756
|
onClick: () => {
|
|
2473
2757
|
if (item.id !== void 0) openSession?.(item.id);
|
|
2474
2758
|
},
|
|
2475
|
-
children: /* @__PURE__ */ (0,
|
|
2759
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: item.title || item.id })
|
|
2476
2760
|
},
|
|
2477
2761
|
item.id
|
|
2478
2762
|
))
|
|
@@ -2619,7 +2903,7 @@ var CSS_TEXT = `
|
|
|
2619
2903
|
.dsh-st-shell-body>*{min-width:0;flex:1}.dsh-st-official-tree{display:flex;min-height:0;flex:1;overflow:hidden}.dsh-st-official-tree>*{min-width:0;flex:1}
|
|
2620
2904
|
.dsh-st-rail-head.is-static{cursor:default;font-weight:600}
|
|
2621
2905
|
.dsh-st-rail-session.is-on{background:var(--dsw-alias-interactive-bg-hover,rgba(255,255,255,.06))}
|
|
2622
|
-
.dsh-st-n,.dsh-st-n *{box-sizing:border-box}.dsh-st-n{box-sizing:border-box;display:flex;flex:1;min-width:0;max-width:100%;min-height:0;flex-direction:column;padding:0;padding-right:var(--dsh-sidebar-inline-padding,12px);color:var(--dsw-alias-label-primary,inherit);font:14px/20px inherit;overflow:hidden}.dsh-st-n-
|
|
2906
|
+
.dsh-st-n,.dsh-st-n *{box-sizing:border-box}.dsh-st-n{box-sizing:border-box;display:flex;flex:1;min-width:0;max-width:100%;min-height:0;flex-direction:column;padding:0;padding-right:var(--dsh-sidebar-inline-padding,12px);color:var(--dsw-alias-label-primary,inherit);font:14px/20px inherit;overflow:hidden}.dsh-st-n-toolbar{box-sizing:border-box;flex:none;height:36px;margin:2px -4px 4px 0;padding-left:4px;display:flex;justify-content:flex-end;align-items:center;gap:4px;overflow:visible;position:relative;z-index:2;color:var(--dsw-alias-label-tertiary,#81858C);border-radius:12px}.dsh-st-n-head-label{white-space:nowrap;min-width:0;max-width:45%;flex:none;line-height:20px;font-size:14px;overflow:hidden;transition:max-width .18s var(--ds-ease-in-out,ease),margin-right .18s var(--ds-ease-in-out,ease),opacity .12s var(--ds-ease-in-out,ease),transform .18s var(--ds-ease-in-out,ease),visibility 0s linear}.dsh-st-n-toolbar.is-search .dsh-st-n-head-label{opacity:0;visibility:hidden;max-width:0;margin-right:-4px;transform:translate(-4px);transition-delay:0s,0s,0s,0s,.18s}.dsh-st-n-search-slot{box-sizing:border-box;min-width:28px;max-width:28px;transition:max-width .18s var(--ds-ease-in-out,ease);flex:none;align-items:center;margin-left:auto;display:flex;position:relative;z-index:2}.dsh-st-n-toolbar.is-search .dsh-st-n-search-slot{flex:1;min-width:0;max-width:100%}.dsh-st-n-search{box-sizing:border-box;cursor:text;width:100%;height:28px;color:var(--dsw-alias-label-secondary);transition:width .18s var(--ds-ease-in-out,ease),padding .18s var(--ds-ease-in-out,ease),border-color .18s var(--ds-ease-in-out,ease);background:transparent;border:none;border-radius:50%;flex:none;align-items:center;margin:0;padding:0;display:flex;overflow:hidden}.dsh-st-n-toolbar.is-search .dsh-st-n-search{border:1px solid var(--dsw-alias-border-l2,rgba(255,255,255,.10));width:calc(100% + 4px);height:30px;border-radius:10px;margin-inline:-2px;padding:0 4px 0 0}.dsh-st-n-search-btn,.dsh-st-n-head-btn{cursor:pointer;width:28px;height:28px;min-width:28px;min-height:28px;position:relative;z-index:1;color:var(--dsw-alias-label-secondary);background:transparent;border:none;border-radius:50%;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.dsh-st-n-toolbar.is-search .dsh-st-n-search-btn{width:28px;height:30px}.dsh-st-n-search-btn:hover,.dsh-st-n-head-btn:hover,.dsh-st-n-head-btn.is-on{background:var(--dsw-alias-interactive-bg-hover,rgba(255,255,255,.06));color:var(--dsw-alias-label-primary,inherit)}.dsh-st-n-toolbar.is-search .dsh-st-n-search-btn:hover{background:transparent}.dsh-st-n-head-acts{opacity:1;visibility:visible;max-width:32px;transition:max-width .18s var(--ds-ease-in-out,ease),opacity .12s var(--ds-ease-in-out,ease),transform .18s var(--ds-ease-in-out,ease),visibility 0s linear;flex:none;align-items:center;gap:4px;display:flex;overflow:visible;position:relative}.dsh-st-n-toolbar.is-search .dsh-st-n-head-acts{opacity:0;visibility:hidden;pointer-events:none;max-width:0;transform:translate(4px);transition-delay:0s,0s,0s,.18s}.dsh-st-n-head-filter{position:relative}.dsh-st-n-search-input{display:none;opacity:0;pointer-events:none;width:0;min-width:0;flex:none;color:var(--dsw-alias-label-primary,inherit);transition:opacity .12s var(--ds-ease-in-out,ease);background:transparent;border:none;outline:none;flex:1;font-size:13px;line-height:18px}.dsh-st-n-toolbar.is-search .dsh-st-n-search-input{display:block;opacity:1;pointer-events:auto;margin-left:-2px;width:auto;flex:1;min-width:0}.dsh-st-n-search-input::placeholder{color:var(--dsw-alias-label-tertiary,#81858C)}.dsh-st-n-search-clear{cursor:pointer;width:24px;height:24px;color:var(--dsw-alias-label-secondary);background:transparent;border:none;border-radius:50%;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.dsh-st-n-search-clear:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(255,255,255,.06))}@media (prefers-reduced-motion:reduce){.dsh-st-n-head-label,.dsh-st-n-search-slot,.dsh-st-n-search,.dsh-st-n-head-acts,.dsh-st-n-search-input{transition:none}}.dsh-st-n-filter-menu{position:absolute;right:0;top:calc(100% + 6px);z-index:30;min-width:196px;padding:8px 6px;border:1px solid var(--dsw-alias-border-inverted,rgba(255,255,255,.12));border-radius:12px;background:var(--dsw-specific-menu,#1c2128);box-shadow:var(--dsw-shadow-lv3,0 8px 24px rgba(0,0,0,.36))}.dsh-st-n-filter-label{padding:6px 10px 4px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary,#81858C)}.dsh-st-n-filter-split{height:1px;margin:6px 8px;background:var(--dsw-alias-border-l2,rgba(255,255,255,.1))}.dsh-st-n-filter-menu button{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%;min-height:36px;padding:6px 10px;border:0;border-radius:8px;background:transparent;color:var(--dsw-alias-label-primary,inherit);font:14px/20px inherit;cursor:pointer;text-align:left}.dsh-st-n-filter-menu button:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(255,255,255,.06))}.dsh-st-n-filter-tick{width:16px;height:16px;flex:none}.dsh-st-n-tree{flex:1;min-width:0;max-width:100%;min-height:0;overflow-x:hidden;overflow-y:auto;padding:0 0 16px;user-select:none}.dsh-st-n-empty{padding:14px 8px;color:var(--dsw-alias-label-tertiary,#8b8f98);font-size:12px}.dsh-st-n-group{min-width:0;max-width:100%}.dsh-st-n-row,.dsh-st-n-sess{display:flex;align-items:center;max-width:100%;border-radius:8px;padding:0 8px 0 12px;cursor:pointer;border:0;background:transparent;color:var(--dsw-alias-label-primary,inherit);text-align:left;font:14px/20px inherit}.dsh-st-n-row{height:34px;gap:6px}.dsh-st-n-sess{height:32px;gap:0;position:relative;width:100%;appearance:none}.dsh-st-n-row:hover,.dsh-st-n-sess:hover,.dsh-st-n-sess.is-on,.dsh-st-n-sess.is-menu{background:var(--dsw-alias-interactive-bg-hover,rgba(255,255,255,.06))}.dsh-st-n-slot{flex:none;width:16px;height:20px;display:inline-flex;align-items:center;justify-content:center}.dsh-st-n-folder{color:var(--dsw-alias-label-secondary,#9ca39f)}.dsh-st-n-lead{color:var(--dsw-alias-label-tertiary,#81858C)}.dsh-st-n-corner{color:var(--dsw-alias-label-caption,#ADB2B8);width:8px}.dsh-st-n-title{min-width:0;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:14px;line-height:20px}.dsh-st-n-sess .dsh-st-n-title{margin:0 6px 0 4px}.dsh-st-n-time{flex:none;font-size:12px;line-height:20px;color:var(--dsw-alias-label-tertiary,#81858C);white-space:nowrap}.dsh-st-n-acts{flex:none;display:none;align-items:center;gap:12px}.dsh-st-n-row:hover .dsh-st-n-acts,.dsh-st-n-sess:hover .dsh-st-n-acts,.dsh-st-n-row.is-menu .dsh-st-n-acts,.dsh-st-n-sess.is-menu .dsh-st-n-acts{display:inline-flex}.dsh-st-n-sess:hover .dsh-st-n-time,.dsh-st-n-sess.is-menu .dsh-st-n-time{display:none}.dsh-st-n-ico{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;border:0;border-radius:4px;background:transparent;color:var(--dsw-alias-label-tertiary,#81858C);padding:0;cursor:pointer}.dsh-st-n-ico:hover{color:var(--dsw-alias-label-primary,inherit)}.dsh-st-n-menu.is-float{position:fixed;z-index:4000;right:auto;top:auto}.dsh-st-n-menu{position:absolute;right:8px;top:calc(100% + 4px);z-index:1100;min-width:218px;max-width:360px;box-sizing:border-box;padding:4px;display:flex;flex-direction:column;border:1px solid var(--dsw-alias-border-inverted,rgba(255,255,255,.12));border-radius:12px;background:var(--dsw-specific-menu,#1c2128);box-shadow:var(--dsw-shadow-lv3,0 8px 24px rgba(0,0,0,.36))}.dsh-st-n-menu button{display:flex;align-items:center;gap:8px;width:100%;min-height:40px;padding:8px 10px;border:0;border-radius:10px;background:transparent;cursor:pointer;font-size:14px;line-height:22px;color:var(--dsw-alias-label-primary,inherit);text-align:left}.dsh-st-n-menu button:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(255,255,255,.06))}.dsh-st-n-mi{display:inline-flex;flex:none;width:16px;height:16px;align-items:center;justify-content:center;color:var(--dsw-alias-label-tertiary,#81858C)}.dsh-st-n-menu button.danger{color:var(--dsw-alias-state-error-primary,#f85149)}.dsh-st-n-menu button.danger .dsh-st-n-mi{color:inherit}.dsh-st-n-menu button.danger:hover{background:var(--dsw-alias-interactive-bg-hover-danger,rgba(248,81,73,.12))}.dsh-st-n-hover{position:fixed;z-index:4100;min-width:188px;max-width:280px;padding:12px 14px;border:1px solid var(--dsw-alias-border-inverted,rgba(255,255,255,.12));border-radius:12px;background:var(--dsw-specific-menu,#1c2128);box-shadow:var(--dsw-shadow-lv3,0 8px 24px rgba(0,0,0,.36));color:var(--dsw-alias-label-primary,inherit)}.dsh-st-n-hover-title{font-size:14px;line-height:20px;font-weight:500}.dsh-st-n-hover-time{margin-top:4px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary,#81858C)}.dsh-st-n-hover-state{display:flex;align-items:center;gap:6px;margin-top:8px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary,#9ca39f)}.dsh-st-n-hover-dot{width:8px;height:8px;border-radius:50%;background:#34c759;flex:none}.dsh-st-n-hover-dot.is-run{background:#4c8dff}.dsh-st-n-rename{flex:1;min-width:0;margin:0 6px 0 4px;border:1px solid var(--dsw-alias-border-l2);border-radius:4px;background:var(--dsw-alias-button-elevated-fill,rgba(255,255,255,.04));color:inherit;font:inherit;padding:0 2px}
|
|
2623
2907
|
`;
|
|
2624
2908
|
function installStyles() {
|
|
2625
2909
|
const existing = document.getElementById(STYLE_ID);
|
|
@@ -2673,7 +2957,8 @@ function apply(ctx) {
|
|
|
2673
2957
|
label: () => t("tab"),
|
|
2674
2958
|
icon: "schedule"
|
|
2675
2959
|
}, function ScheduledTasksSettings(props) {
|
|
2676
|
-
|
|
2960
|
+
const workspacesApi = readOptionalWorkspaces(ctx);
|
|
2961
|
+
return (0, import_react7.createElement)(AutomationView, { t, runtime, ...props.close === void 0 ? {} : { closeSettings: props.close }, ...workspacesApi === void 0 ? {} : { pickWorkspaceDirectory: () => workspacesApi.pickDirectory() } });
|
|
2677
2962
|
}));
|
|
2678
2963
|
ctx.slots.inject("sidebar.schedule", () => ctx.slots.register({
|
|
2679
2964
|
name: "sidebar.schedule",
|
|
@@ -2682,27 +2967,30 @@ function apply(ctx) {
|
|
|
2682
2967
|
locale: NS,
|
|
2683
2968
|
label: () => t("sidebar.tab")
|
|
2684
2969
|
}, function AutomationScheduleRail(props) {
|
|
2685
|
-
return (0,
|
|
2970
|
+
return (0, import_react7.createElement)(ScheduleRail, {
|
|
2686
2971
|
t,
|
|
2687
2972
|
runtime,
|
|
2688
|
-
openSession: (
|
|
2689
|
-
openScheduledSession(id, (sessionId) => {
|
|
2690
|
-
ctx.sessions?.open(sessionId);
|
|
2691
|
-
}, props.openSession);
|
|
2692
|
-
}
|
|
2973
|
+
openSession: createScheduledSessionOpener(ctx, runtime, props.openSession)
|
|
2693
2974
|
});
|
|
2694
2975
|
}));
|
|
2695
2976
|
ctx.slots.inject("sidebar.workspaces", () => {
|
|
2696
2977
|
let wrappedEntry;
|
|
2697
2978
|
let originalComp;
|
|
2698
2979
|
let removeInsertedTab = () => void 0;
|
|
2699
|
-
let
|
|
2980
|
+
let wrapped = false;
|
|
2700
2981
|
let syncing = false;
|
|
2982
|
+
let retryTimer;
|
|
2983
|
+
const listenChannels = (listener) => ctx.slots.subscribe?.("sidebar.channels", listener) ?? (() => void 0);
|
|
2984
|
+
const stopRetry = () => {
|
|
2985
|
+
if (retryTimer !== void 0) {
|
|
2986
|
+
window.clearInterval(retryTimer);
|
|
2987
|
+
retryTimer = void 0;
|
|
2988
|
+
}
|
|
2989
|
+
};
|
|
2701
2990
|
const unwrap = () => {
|
|
2991
|
+
stopRetry();
|
|
2702
2992
|
removeInsertedTab();
|
|
2703
2993
|
removeInsertedTab = () => void 0;
|
|
2704
|
-
removeFilter();
|
|
2705
|
-
removeFilter = () => void 0;
|
|
2706
2994
|
if (wrappedEntry !== void 0 && originalComp !== void 0) {
|
|
2707
2995
|
try {
|
|
2708
2996
|
wrappedEntry.component = originalComp;
|
|
@@ -2711,12 +2999,12 @@ function apply(ctx) {
|
|
|
2711
2999
|
}
|
|
2712
3000
|
wrappedEntry = void 0;
|
|
2713
3001
|
originalComp = void 0;
|
|
3002
|
+
wrapped = false;
|
|
2714
3003
|
};
|
|
2715
3004
|
const insertScheduleTab = (entry, openSession) => {
|
|
2716
3005
|
const registry = findNativeTabRegistry(entry);
|
|
2717
3006
|
if (registry === void 0) return false;
|
|
2718
3007
|
if (registry.getTabs().some((item) => item.id === "schedule")) return true;
|
|
2719
|
-
removeInsertedTab();
|
|
2720
3008
|
removeInsertedTab = registry.insert({
|
|
2721
3009
|
id: "schedule",
|
|
2722
3010
|
label: t("sidebar.tab"),
|
|
@@ -2724,12 +3012,8 @@ function apply(ctx) {
|
|
|
2724
3012
|
matchSession: (sessionId) => sessionId.startsWith(AUTOMATION_SESSION_PREFIX),
|
|
2725
3013
|
render: (props) => {
|
|
2726
3014
|
const hostOpen = typeof props.openSession === "function" ? props.openSession : typeof props.open === "function" ? props.open : openSession;
|
|
2727
|
-
const opener = (
|
|
2728
|
-
|
|
2729
|
-
ctx.sessions?.open(sessionId);
|
|
2730
|
-
}, hostOpen);
|
|
2731
|
-
};
|
|
2732
|
-
return (0, import_react6.createElement)(NativeScheduleSessionList, {
|
|
3015
|
+
const opener = createScheduledSessionOpener(ctx, runtime, hostOpen);
|
|
3016
|
+
return (0, import_react7.createElement)(NativeScheduleSessionList, {
|
|
2733
3017
|
t,
|
|
2734
3018
|
runtime,
|
|
2735
3019
|
openSession: opener,
|
|
@@ -2742,21 +3026,35 @@ function apply(ctx) {
|
|
|
2742
3026
|
});
|
|
2743
3027
|
}
|
|
2744
3028
|
});
|
|
2745
|
-
removeFilter();
|
|
2746
|
-
removeFilter = registry.addSessionFilter((id) => !id.startsWith(AUTOMATION_SESSION_PREFIX));
|
|
2747
3029
|
return true;
|
|
2748
3030
|
};
|
|
3031
|
+
const insertIntoKnownHosts = () => {
|
|
3032
|
+
const entries = readSlotEntries(ctx, "sidebar.workspaces");
|
|
3033
|
+
for (const entry of entries) {
|
|
3034
|
+
const record = entry;
|
|
3035
|
+
if (insertScheduleTab(entry) || insertScheduleTab(record.component)) return true;
|
|
3036
|
+
}
|
|
3037
|
+
return wrappedEntry !== void 0 && insertScheduleTab(wrappedEntry);
|
|
3038
|
+
};
|
|
3039
|
+
const ensureScheduleTab = () => {
|
|
3040
|
+
if (insertIntoKnownHosts()) {
|
|
3041
|
+
stopRetry();
|
|
3042
|
+
return;
|
|
3043
|
+
}
|
|
3044
|
+
if (retryTimer !== void 0) return;
|
|
3045
|
+
let tries = 0;
|
|
3046
|
+
retryTimer = window.setInterval(() => {
|
|
3047
|
+
tries += 1;
|
|
3048
|
+
if (insertIntoKnownHosts() || tries >= 20) stopRetry();
|
|
3049
|
+
}, 250);
|
|
3050
|
+
};
|
|
2749
3051
|
const sync = () => {
|
|
2750
3052
|
if (syncing) return;
|
|
2751
3053
|
syncing = true;
|
|
2752
3054
|
try {
|
|
2753
3055
|
let AutomationNativeWorkspaceShell2 = function(innerProps) {
|
|
2754
|
-
const openSession = (
|
|
2755
|
-
|
|
2756
|
-
ctx.sessions?.open(sessionId);
|
|
2757
|
-
}, innerProps.openSession ?? innerProps.open);
|
|
2758
|
-
};
|
|
2759
|
-
return (0, import_react6.createElement)(NativeScheduleShell, {
|
|
3056
|
+
const openSession = createScheduledSessionOpener(ctx, runtime, innerProps.openSession ?? innerProps.open);
|
|
3057
|
+
return (0, import_react7.createElement)(NativeScheduleShell, {
|
|
2760
3058
|
t,
|
|
2761
3059
|
runtime,
|
|
2762
3060
|
hostProps: innerProps,
|
|
@@ -2764,7 +3062,7 @@ function apply(ctx) {
|
|
|
2764
3062
|
tabRegistry: registry,
|
|
2765
3063
|
...innerProps.wide === void 0 ? {} : { wide: innerProps.wide },
|
|
2766
3064
|
hasChannels: () => slotHasEntries(ctx, "sidebar.channels"),
|
|
2767
|
-
subscribeChannels:
|
|
3065
|
+
subscribeChannels: listenChannels,
|
|
2768
3066
|
...innerProps.useSessions === void 0 ? {} : { useSessions: innerProps.useSessions },
|
|
2769
3067
|
...innerProps.useWorkspaces === void 0 ? {} : { useWorkspaces: innerProps.useWorkspaces },
|
|
2770
3068
|
...innerProps.renderSlot === void 0 ? {} : { renderSlot: innerProps.renderSlot },
|
|
@@ -2780,14 +3078,14 @@ function apply(ctx) {
|
|
|
2780
3078
|
const occupant = pickWrappableWorkspacesEntry(entries);
|
|
2781
3079
|
const current = occupant?.component;
|
|
2782
3080
|
if (current !== void 0 && isForeignSidebarHost(current)) {
|
|
2783
|
-
|
|
3081
|
+
ensureScheduleTab();
|
|
2784
3082
|
return;
|
|
2785
3083
|
}
|
|
2786
3084
|
if (wrappedEntry?.component !== void 0 && wrappedEntry.component.__dshAutomationWrapped === true) {
|
|
2787
|
-
|
|
3085
|
+
ensureScheduleTab();
|
|
2788
3086
|
return;
|
|
2789
3087
|
}
|
|
2790
|
-
if (occupant?.component === void 0) return;
|
|
3088
|
+
if (occupant?.component === void 0 || wrapped) return;
|
|
2791
3089
|
const resolved = resolveOfficialTreeComponent(occupant.component);
|
|
2792
3090
|
if (resolved === void 0) return;
|
|
2793
3091
|
originalComp = resolved;
|
|
@@ -2801,9 +3099,8 @@ function apply(ctx) {
|
|
|
2801
3099
|
attachNativeTabRegistry(marked, registry);
|
|
2802
3100
|
occupant.component = marked;
|
|
2803
3101
|
wrappedEntry = occupant;
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
});
|
|
3102
|
+
wrapped = true;
|
|
3103
|
+
ensureScheduleTab();
|
|
2807
3104
|
} catch (error) {
|
|
2808
3105
|
console.warn("[dsh-automation] \u5305\u88F9\u5B98\u65B9\u4EFB\u52A1\u6811\u5931\u8D25", error);
|
|
2809
3106
|
} finally {
|
|
@@ -2812,6 +3109,7 @@ function apply(ctx) {
|
|
|
2812
3109
|
};
|
|
2813
3110
|
sync();
|
|
2814
3111
|
const unsub = typeof ctx.slots.subscribe === "function" ? ctx.slots.subscribe("sidebar.workspaces", sync) : () => void 0;
|
|
3112
|
+
ensureScheduleTab();
|
|
2815
3113
|
return () => {
|
|
2816
3114
|
unsub();
|
|
2817
3115
|
unwrap();
|
|
@@ -2824,8 +3122,25 @@ function apply(ctx) {
|
|
|
2824
3122
|
locale: NS
|
|
2825
3123
|
}, PrefillBridge));
|
|
2826
3124
|
}
|
|
3125
|
+
function createScheduledSessionOpener(ctx, runtime, hostOpen) {
|
|
3126
|
+
return (sessionId) => {
|
|
3127
|
+
void ensureOpenScheduledSession({
|
|
3128
|
+
id: sessionId,
|
|
3129
|
+
adopt: (id) => runtime.adoptSession(id),
|
|
3130
|
+
listed: (id) => {
|
|
3131
|
+
const snap = ctx.sessions?.list?.getSnapshot();
|
|
3132
|
+
return snap?.byId?.[id] !== void 0 || (snap?.ids ?? []).some((item) => item === id);
|
|
3133
|
+
},
|
|
3134
|
+
...ctx.sessions?.refresh === void 0 ? {} : { refresh: () => ctx.sessions.refresh() },
|
|
3135
|
+
...ctx.sessions === void 0 ? {} : { openRuntime: (id) => {
|
|
3136
|
+
ctx.sessions.open(id);
|
|
3137
|
+
} },
|
|
3138
|
+
...hostOpen === void 0 ? {} : { openHost: hostOpen }
|
|
3139
|
+
});
|
|
3140
|
+
};
|
|
3141
|
+
}
|
|
2827
3142
|
function PrefillBridge(props) {
|
|
2828
|
-
(0,
|
|
3143
|
+
(0, import_react7.useEffect)(() => {
|
|
2829
3144
|
const applyPrefill = (text) => {
|
|
2830
3145
|
if (text === null || text === "") return;
|
|
2831
3146
|
if (props.inputActions !== void 0) {
|
|
@@ -2851,5 +3166,12 @@ function readSlotEntries(ctx, name2) {
|
|
|
2851
3166
|
function slotHasEntries(ctx, name2) {
|
|
2852
3167
|
return readSlotEntries(ctx, name2).length > 0;
|
|
2853
3168
|
}
|
|
3169
|
+
function readOptionalWorkspaces(ctx) {
|
|
3170
|
+
try {
|
|
3171
|
+
return ctx.workspaces;
|
|
3172
|
+
} catch {
|
|
3173
|
+
return void 0;
|
|
3174
|
+
}
|
|
3175
|
+
}
|
|
2854
3176
|
return module.exports; } });
|
|
2855
3177
|
//# sourceMappingURL=client.js.map
|