@michengai/dsh-automation 0.1.9 → 0.1.11
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/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 +2 -2
- package/lib/client.js +182 -166
- package/lib/client.js.map +4 -4
- package/lib/index.js +461 -338
- package/lib/types/client/AutomationView.d.ts +1 -1
- package/lib/types/client/contracts.d.ts +2 -4
- package/lib/types/client/create-modal-logic.d.ts +0 -8
- package/lib/types/client/create-modal.d.ts +7 -15
- package/lib/types/client/locales.d.ts +0 -1
- package/lib/types/client/menu.d.ts +2 -1
- package/lib/types/client/protocol.d.ts +16 -4
- package/lib/types/client/runtime.d.ts +0 -3
- package/lib/types/executor.d.ts +3 -1
- package/lib/types/permission-presets.d.ts +6 -0
- package/lib/types/rpc.d.ts +1 -1
- package/lib/types/service.d.ts +22 -1
- package/package.json +8 -8
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
- [x] 原生侧栏定时页签:包裹官方任务树,不依赖 dsh-codex-ui
|
|
18
18
|
- [x] 单测与包契约
|
|
19
19
|
- [x] 定时侧栏会话菜单互斥,避免点第二条时与第一条重叠
|
|
20
|
-
- [x]
|
|
20
|
+
- [x] 新建弹窗只允许选择 Host 已注册工作区,新增目录统一从 Host 工作区入口完成
|
|
21
21
|
- [x] 修复任务树过滤导致的 Loading plugins / 点任务卡死
|
|
22
22
|
- [x] 会话创建定时任务按官方审批策略分流,并补系统提示避免走 crontab
|
|
23
23
|
- [x] 工作区标题栏对齐官方位置与搜索点击
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
|
|
37
37
|
## 已完成内容
|
|
38
38
|
|
|
39
|
-
仓库内已落地 Host 插件、Web
|
|
39
|
+
仓库内已落地 Host 插件、Web 客户端、原生侧栏定时页签、文档和单测。定时会话更多菜单改为列表级互斥,并用固定定位弹出,避免两条菜单叠在一起。新建弹窗只消费 Host 已注册工作区,避免插件 RPC 自行扩大目录边界;点遮罩不再关闭。
|
|
40
40
|
|
|
41
41
|
## 待处理事项
|
|
42
42
|
|
package/lib/client.js
CHANGED
|
@@ -79,7 +79,7 @@ function defaultFormState(now = /* @__PURE__ */ new Date(), workspaces = [], def
|
|
|
79
79
|
permission: defaultPermission,
|
|
80
80
|
workspaceId: workspaces[0]?.id ?? "",
|
|
81
81
|
modelKey: defaultModel === void 0 || defaultModel === null ? "default" : `${defaultModel.provider}::${defaultModel.model}`,
|
|
82
|
-
reasoningEffort: "
|
|
82
|
+
reasoningEffort: defaultModel?.reasoning?.defaultEffort ?? "none",
|
|
83
83
|
skills: []
|
|
84
84
|
};
|
|
85
85
|
}
|
|
@@ -193,19 +193,13 @@ function groupHistory(runs, range, now, t) {
|
|
|
193
193
|
const at = new Date(run.finishedAt ?? run.startedAt ?? run.scheduledFor);
|
|
194
194
|
if (Number.isNaN(at.getTime())) continue;
|
|
195
195
|
let key;
|
|
196
|
-
let label;
|
|
197
196
|
if (range === "month") {
|
|
198
197
|
key = `${at.getFullYear()}-${String(at.getMonth() + 1).padStart(2, "0")}`;
|
|
199
|
-
label = t("history.month", { month: `${at.getFullYear()}/${at.getMonth() + 1}` });
|
|
200
198
|
} else if (range === "week") {
|
|
201
199
|
const start = startOfWeek(at);
|
|
202
|
-
key = start
|
|
203
|
-
label = t("history.week", { date: `${start.getMonth() + 1}/${start.getDate()}` });
|
|
200
|
+
key = localDayKey(start);
|
|
204
201
|
} else {
|
|
205
202
|
key = localDayKey(at);
|
|
206
|
-
const today = localDayKey(now);
|
|
207
|
-
const yesterday = localDayKey(new Date(now.getTime() - 864e5));
|
|
208
|
-
label = key === today ? t("history.today") : key === yesterday ? t("history.yesterday") : t("history.date", { date: `${at.getMonth() + 1}/${at.getDate()}` });
|
|
209
203
|
}
|
|
210
204
|
const existing = buckets.get(key) ?? [];
|
|
211
205
|
existing.push(run);
|
|
@@ -239,7 +233,7 @@ function formFromAutomation(item, workspaces = [], defaultModel, defaultPermissi
|
|
|
239
233
|
permission: item.permission,
|
|
240
234
|
workspaceId: item.workspaceId ?? base.workspaceId,
|
|
241
235
|
modelKey,
|
|
242
|
-
reasoningEffort: item.reasoningEffort ?? "
|
|
236
|
+
reasoningEffort: item.reasoningEffort ?? "none"
|
|
243
237
|
};
|
|
244
238
|
switch (schedule.kind) {
|
|
245
239
|
case "once":
|
|
@@ -411,16 +405,6 @@ function permissionLabel(option, t) {
|
|
|
411
405
|
return option.name || option.value;
|
|
412
406
|
}
|
|
413
407
|
|
|
414
|
-
// src/client/create-modal-logic.ts
|
|
415
|
-
function shouldConfirmFullAccess(current, next) {
|
|
416
|
-
return current !== next && next === "danger-full-access";
|
|
417
|
-
}
|
|
418
|
-
async function adoptPickedWorkspace(input) {
|
|
419
|
-
const path = await input.pick();
|
|
420
|
-
if (path == null || path.trim() === "") return null;
|
|
421
|
-
return input.add(path.trim());
|
|
422
|
-
}
|
|
423
|
-
|
|
424
408
|
// src/client/menu.tsx
|
|
425
409
|
var import_react = require("react");
|
|
426
410
|
var import_react_dom = require("react-dom");
|
|
@@ -465,6 +449,7 @@ function MenuPopup({
|
|
|
465
449
|
up,
|
|
466
450
|
end,
|
|
467
451
|
className,
|
|
452
|
+
ariaLabel,
|
|
468
453
|
children,
|
|
469
454
|
onClick
|
|
470
455
|
}) {
|
|
@@ -489,6 +474,8 @@ function MenuPopup({
|
|
|
489
474
|
{
|
|
490
475
|
ref: menuRef,
|
|
491
476
|
className: `${className}${host !== null ? " is-float" : ""}`,
|
|
477
|
+
role: "menu",
|
|
478
|
+
"aria-label": ariaLabel,
|
|
492
479
|
style: host !== null ? style : void 0,
|
|
493
480
|
onMouseDown: (event) => event.stopPropagation(),
|
|
494
481
|
onClick: (event) => {
|
|
@@ -632,9 +619,11 @@ var MINUTES = Array.from({ length: 60 }, (_, index) => String(index).padStart(2,
|
|
|
632
619
|
function CreateModal({
|
|
633
620
|
t,
|
|
634
621
|
permissionT,
|
|
622
|
+
modelT,
|
|
635
623
|
busy,
|
|
636
624
|
workspaces,
|
|
637
625
|
models,
|
|
626
|
+
modelFailures,
|
|
638
627
|
defaultModel,
|
|
639
628
|
skills,
|
|
640
629
|
permissions,
|
|
@@ -642,39 +631,21 @@ function CreateModal({
|
|
|
642
631
|
draft,
|
|
643
632
|
editing,
|
|
644
633
|
onClose,
|
|
645
|
-
onSubmit
|
|
646
|
-
onAddWorkspace,
|
|
647
|
-
pickWorkspaceDirectory
|
|
634
|
+
onSubmit
|
|
648
635
|
}) {
|
|
649
636
|
const [form, setForm] = (0, import_react2.useState)(() => ({ ...defaultFormState(/* @__PURE__ */ new Date(), workspaces, defaultModel, defaultPermission), ...draft }));
|
|
650
637
|
const [validationError, setValidationError] = (0, import_react2.useState)();
|
|
651
|
-
const [confirmingPermission, setConfirmingPermission] = (0, import_react2.useState)();
|
|
652
|
-
const [fullAccessAcknowledged, setFullAccessAcknowledged] = (0, import_react2.useState)(false);
|
|
653
638
|
const update = (patch) => {
|
|
654
639
|
setForm((current) => ({ ...current, ...patch }));
|
|
655
640
|
setValidationError(void 0);
|
|
656
641
|
};
|
|
657
642
|
const choosePermission = (permission) => {
|
|
658
|
-
if (shouldConfirmFullAccess(form.permission, permission)) {
|
|
659
|
-
setFullAccessAcknowledged(false);
|
|
660
|
-
setConfirmingPermission(permission);
|
|
661
|
-
return;
|
|
662
|
-
}
|
|
663
643
|
update({ permission });
|
|
664
644
|
};
|
|
665
|
-
const cancelFullAccessConfirmation = () => {
|
|
666
|
-
setFullAccessAcknowledged(false);
|
|
667
|
-
setConfirmingPermission(void 0);
|
|
668
|
-
};
|
|
669
|
-
const confirmFullAccess = () => {
|
|
670
|
-
if (!fullAccessAcknowledged) return;
|
|
671
|
-
if (confirmingPermission === void 0) return;
|
|
672
|
-
update({ permission: confirmingPermission });
|
|
673
|
-
cancelFullAccessConfirmation();
|
|
674
|
-
};
|
|
675
645
|
(0, import_react2.useEffect)(() => {
|
|
676
646
|
const onKey = (event) => {
|
|
677
647
|
if (event.key !== "Escape") return;
|
|
648
|
+
if (document.querySelector(".dsh-st-model-select-menu") !== null) return;
|
|
678
649
|
event.preventDefault();
|
|
679
650
|
event.stopPropagation();
|
|
680
651
|
event.stopImmediatePropagation();
|
|
@@ -813,30 +784,7 @@ function CreateModal({
|
|
|
813
784
|
onClick: () => update({ workspaceId: item.id })
|
|
814
785
|
},
|
|
815
786
|
item.id
|
|
816
|
-
))
|
|
817
|
-
pickWorkspaceDirectory !== void 0 && onAddWorkspace !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
818
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-st-menu-split" }),
|
|
819
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
820
|
-
MenuRow,
|
|
821
|
-
{
|
|
822
|
-
icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PlusIcon, { width: 14, height: 14 }),
|
|
823
|
-
label: t("form.addWorkspace"),
|
|
824
|
-
onClick: () => {
|
|
825
|
-
void (async () => {
|
|
826
|
-
try {
|
|
827
|
-
const id = await adoptPickedWorkspace({
|
|
828
|
-
pick: pickWorkspaceDirectory,
|
|
829
|
-
add: onAddWorkspace
|
|
830
|
-
});
|
|
831
|
-
if (id !== null) update({ workspaceId: id });
|
|
832
|
-
} catch (caught) {
|
|
833
|
-
setValidationError(caught instanceof Error ? caught.message : t("error.action"));
|
|
834
|
-
}
|
|
835
|
-
})();
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
)
|
|
839
|
-
] })
|
|
787
|
+
))
|
|
840
788
|
] }),
|
|
841
789
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(MenuPanel, { ghost: true, up: true, label: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
842
790
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SparkleIcon, { width: 14, height: 14 }),
|
|
@@ -872,10 +820,12 @@ function CreateModal({
|
|
|
872
820
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-st-composer-right", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
873
821
|
ModelPicker,
|
|
874
822
|
{
|
|
875
|
-
|
|
823
|
+
modelT,
|
|
876
824
|
models,
|
|
825
|
+
failures: modelFailures,
|
|
877
826
|
modelKey: form.modelKey,
|
|
878
|
-
|
|
827
|
+
reasoningEffort: form.reasoningEffort,
|
|
828
|
+
onSelection: (modelKey, reasoningEffort) => update({ modelKey, reasoningEffort })
|
|
879
829
|
}
|
|
880
830
|
) })
|
|
881
831
|
] })
|
|
@@ -887,84 +837,169 @@ function CreateModal({
|
|
|
887
837
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "submit", className: "dsh-st-btn dsh-st-btn--primary", disabled: busy, children: t("modal.save") })
|
|
888
838
|
] })
|
|
889
839
|
] }),
|
|
890
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-st-flyout-root", ref: setMenuHost })
|
|
891
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
892
|
-
import_dsh_client_ui_primitives.RiskConfirmation,
|
|
893
|
-
{
|
|
894
|
-
open: confirmingPermission !== void 0,
|
|
895
|
-
title: permissionT("confirm.title"),
|
|
896
|
-
description: permissionT("confirm.description"),
|
|
897
|
-
acknowledgeLabel: permissionT("confirm.acknowledge"),
|
|
898
|
-
cancelLabel: permissionT("confirm.cancel"),
|
|
899
|
-
confirmLabel: permissionT("confirm.enable"),
|
|
900
|
-
acknowledged: fullAccessAcknowledged,
|
|
901
|
-
onAcknowledgedChange: setFullAccessAcknowledged,
|
|
902
|
-
onCancel: cancelFullAccessConfirmation,
|
|
903
|
-
onConfirm: confirmFullAccess
|
|
904
|
-
}
|
|
905
|
-
)
|
|
840
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-st-flyout-root", ref: setMenuHost })
|
|
906
841
|
] }) });
|
|
907
842
|
}
|
|
908
843
|
function ModelPicker({
|
|
909
|
-
|
|
844
|
+
modelT,
|
|
910
845
|
models,
|
|
846
|
+
failures,
|
|
911
847
|
modelKey,
|
|
912
|
-
|
|
848
|
+
reasoningEffort,
|
|
849
|
+
onSelection
|
|
913
850
|
}) {
|
|
914
851
|
const menu = useMenuState();
|
|
852
|
+
const [pane, setPane] = (0, import_react2.useState)("root");
|
|
915
853
|
const selected = models.find((item) => `${item.provider}::${item.model}` === modelKey);
|
|
916
|
-
const
|
|
854
|
+
const reasoning = selected?.reasoning;
|
|
855
|
+
const effectiveEffort = reasoningEffort === "none" ? reasoning?.defaultEffort : reasoningEffort;
|
|
856
|
+
const effortLabel = reasoning === void 0 ? void 0 : effectiveEffort === void 0 ? modelT("effort.providerDefault") : reasoning.efforts.find((item) => item.id === effectiveEffort)?.name ?? effectiveEffort;
|
|
857
|
+
const trigger = selected?.label ?? modelT("trigger.fallback");
|
|
917
858
|
const modelGroups = Array.from(models.reduce((groups, item) => {
|
|
918
|
-
const group = groups.get(item.provider) ?? [];
|
|
919
|
-
group.push(item);
|
|
859
|
+
const group = groups.get(item.provider) ?? { label: item.providerLabel, models: [] };
|
|
860
|
+
group.models.push(item);
|
|
920
861
|
groups.set(item.provider, group);
|
|
921
862
|
return groups;
|
|
922
863
|
}, /* @__PURE__ */ new Map()));
|
|
864
|
+
(0, import_react2.useEffect)(() => {
|
|
865
|
+
if (!menu.open) return;
|
|
866
|
+
const onKey = (event) => {
|
|
867
|
+
if (event.key !== "Escape") return;
|
|
868
|
+
event.preventDefault();
|
|
869
|
+
event.stopPropagation();
|
|
870
|
+
event.stopImmediatePropagation();
|
|
871
|
+
if (pane !== "root") setPane("root");
|
|
872
|
+
else menu.setOpen(false);
|
|
873
|
+
};
|
|
874
|
+
window.addEventListener("keydown", onKey, true);
|
|
875
|
+
return () => {
|
|
876
|
+
window.removeEventListener("keydown", onKey, true);
|
|
877
|
+
};
|
|
878
|
+
}, [menu.open, menu.setOpen, pane]);
|
|
879
|
+
const selectModel = (item) => {
|
|
880
|
+
onSelection(
|
|
881
|
+
`${item.provider}::${item.model}`,
|
|
882
|
+
item.reasoning?.defaultEffort ?? "none"
|
|
883
|
+
);
|
|
884
|
+
menu.setOpen(false);
|
|
885
|
+
setPane("root");
|
|
886
|
+
};
|
|
887
|
+
const selectEffort = (effort) => {
|
|
888
|
+
onSelection(modelKey, effort);
|
|
889
|
+
menu.setOpen(false);
|
|
890
|
+
setPane("root");
|
|
891
|
+
};
|
|
923
892
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: `dsh-st-model-select${menu.open ? " is-open" : ""}`, ref: menu.root, children: [
|
|
924
893
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
925
894
|
"button",
|
|
926
895
|
{
|
|
927
896
|
type: "button",
|
|
928
897
|
className: "dsh-st-model-select-trigger",
|
|
898
|
+
"aria-label": selected === void 0 ? modelT("trigger.selectAria") : effortLabel === void 0 ? modelT("trigger.aria", { model: selected.label }) : modelT("trigger.ariaEffort", { model: selected.label, effort: effortLabel }),
|
|
929
899
|
onMouseDown: (event) => event.stopPropagation(),
|
|
930
900
|
onClick: () => {
|
|
931
901
|
if (menu.open) {
|
|
932
902
|
menu.setOpen(false);
|
|
933
903
|
return;
|
|
934
904
|
}
|
|
905
|
+
setPane("root");
|
|
935
906
|
menu.setOpen(true);
|
|
936
907
|
},
|
|
937
908
|
children: [
|
|
938
909
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: trigger }),
|
|
939
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("
|
|
910
|
+
effortLabel !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-st-model-trigger-effort", children: effortLabel }),
|
|
911
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives.IconChevronDownOutline14, { className: `dsh-st-model-trigger-chevron${menu.open ? " is-open" : ""}` })
|
|
940
912
|
]
|
|
941
913
|
}
|
|
942
914
|
),
|
|
943
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.
|
|
944
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
915
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(MenuPopup, { open: menu.open, anchor: menu.root, menuRef: menu.menu, up: true, end: true, className: "dsh-st-model-select-menu is-up is-end", ariaLabel: modelT("menu.aria"), children: [
|
|
916
|
+
pane === "root" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
917
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
918
|
+
MenuRow,
|
|
919
|
+
{
|
|
920
|
+
kv: true,
|
|
921
|
+
label: modelT("menu.model"),
|
|
922
|
+
hint: selected?.label ?? modelT("trigger.fallback"),
|
|
923
|
+
chevron: true,
|
|
924
|
+
onClick: () => setPane("model")
|
|
925
|
+
}
|
|
926
|
+
),
|
|
927
|
+
reasoning !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
928
|
+
MenuRow,
|
|
929
|
+
{
|
|
930
|
+
kv: true,
|
|
931
|
+
label: modelT("menu.effort"),
|
|
932
|
+
hint: effortLabel ?? modelT("effort.providerDefault"),
|
|
933
|
+
chevron: true,
|
|
934
|
+
onClick: () => setPane("effort")
|
|
935
|
+
}
|
|
936
|
+
)
|
|
937
|
+
] }),
|
|
938
|
+
pane === "model" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
939
|
+
failures.map((failure) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-st-model-warning", children: modelT("warning.groupLoad", { name: failure.providerLabel, message: failure.message }) }, failure.provider)),
|
|
940
|
+
modelGroups.map(([provider, group]) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { role: "group", "aria-label": group.label, className: "dsh-st-model-group", children: [
|
|
941
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-st-model-group-title", children: group.label }),
|
|
942
|
+
group.models.map((item) => {
|
|
943
|
+
const value = `${item.provider}::${item.model}`;
|
|
944
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
945
|
+
"button",
|
|
946
|
+
{
|
|
947
|
+
type: "button",
|
|
948
|
+
role: "menuitemradio",
|
|
949
|
+
"aria-checked": value === modelKey,
|
|
950
|
+
className: "dsh-st-model-option",
|
|
951
|
+
title: item.label,
|
|
952
|
+
onClick: () => selectModel(item),
|
|
953
|
+
children: [
|
|
954
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "dsh-st-model-option-copy", children: [
|
|
955
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-st-model-name", children: item.label }),
|
|
956
|
+
item.description !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-st-model-description", children: item.description })
|
|
957
|
+
] }),
|
|
958
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-st-model-check", children: value === modelKey && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives.IconCheckOutline16, {}) })
|
|
959
|
+
]
|
|
960
|
+
},
|
|
961
|
+
value
|
|
962
|
+
);
|
|
963
|
+
})
|
|
964
|
+
] }, provider)),
|
|
965
|
+
modelGroups.length === 0 && failures.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-st-model-empty", children: modelT("empty.models") })
|
|
966
|
+
] }),
|
|
967
|
+
pane === "effort" && reasoning !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
968
|
+
reasoning.defaultEffort === void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
948
969
|
"button",
|
|
949
970
|
{
|
|
950
971
|
type: "button",
|
|
951
972
|
role: "menuitemradio",
|
|
952
|
-
"aria-checked":
|
|
973
|
+
"aria-checked": reasoningEffort === "none",
|
|
953
974
|
className: "dsh-st-model-option",
|
|
954
|
-
|
|
955
|
-
onClick: () => {
|
|
956
|
-
onModelKey(value);
|
|
957
|
-
menu.setOpen(false);
|
|
958
|
-
},
|
|
975
|
+
onClick: () => selectEffort("none"),
|
|
959
976
|
children: [
|
|
960
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-st-model-option-copy", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-st-model-name", children:
|
|
961
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-st-model-check", children:
|
|
977
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-st-model-option-copy", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-st-model-name", children: modelT("effort.providerDefault") }) }),
|
|
978
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-st-model-check", children: reasoningEffort === "none" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives.IconCheckOutline16, {}) })
|
|
979
|
+
]
|
|
980
|
+
}
|
|
981
|
+
),
|
|
982
|
+
reasoning.efforts.map((item) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
983
|
+
"button",
|
|
984
|
+
{
|
|
985
|
+
type: "button",
|
|
986
|
+
role: "menuitemradio",
|
|
987
|
+
"aria-checked": effectiveEffort === item.id,
|
|
988
|
+
className: "dsh-st-model-option",
|
|
989
|
+
onClick: () => selectEffort(item.id),
|
|
990
|
+
children: [
|
|
991
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "dsh-st-model-option-copy", children: [
|
|
992
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-st-model-name", children: item.name }),
|
|
993
|
+
item.description !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-st-model-description", children: item.description })
|
|
994
|
+
] }),
|
|
995
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-st-model-check", children: effectiveEffort === item.id && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives.IconCheckOutline16, {}) })
|
|
962
996
|
]
|
|
963
997
|
},
|
|
964
|
-
|
|
965
|
-
)
|
|
966
|
-
|
|
967
|
-
|
|
998
|
+
item.id
|
|
999
|
+
)),
|
|
1000
|
+
reasoning.efforts.length === 0 && reasoning.defaultEffort !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-st-model-empty", children: modelT("empty.efforts") })
|
|
1001
|
+
] })
|
|
1002
|
+
] })
|
|
968
1003
|
] });
|
|
969
1004
|
}
|
|
970
1005
|
function TimeSelect({
|
|
@@ -1049,6 +1084,7 @@ function unwrapRpcResult(value) {
|
|
|
1049
1084
|
|
|
1050
1085
|
// src/client/runtime.ts
|
|
1051
1086
|
var CHANNEL = "/dsh-automation";
|
|
1087
|
+
var POLL_INTERVAL_MS = 15e3;
|
|
1052
1088
|
function isTransportError(error) {
|
|
1053
1089
|
const message = error instanceof Error ? error.message : String(error);
|
|
1054
1090
|
return /failed to fetch|networkerror|load failed|network request failed/i.test(message);
|
|
@@ -1056,6 +1092,7 @@ function isTransportError(error) {
|
|
|
1056
1092
|
function createAutomationRuntime(rpc) {
|
|
1057
1093
|
let state = { phase: "idle" };
|
|
1058
1094
|
let refreshPromise;
|
|
1095
|
+
let pollTimer;
|
|
1059
1096
|
const listeners2 = /* @__PURE__ */ new Set();
|
|
1060
1097
|
const publish = (next) => {
|
|
1061
1098
|
state = next;
|
|
@@ -1065,8 +1102,20 @@ function createAutomationRuntime(rpc) {
|
|
|
1065
1102
|
getSnapshot: () => state,
|
|
1066
1103
|
subscribe: (listener) => {
|
|
1067
1104
|
listeners2.add(listener);
|
|
1105
|
+
if (listeners2.size === 1) {
|
|
1106
|
+
queueMicrotask(() => {
|
|
1107
|
+
if (listeners2.size > 0) void refresh().catch(() => void 0);
|
|
1108
|
+
});
|
|
1109
|
+
pollTimer = setInterval(() => {
|
|
1110
|
+
void refresh().catch(() => void 0);
|
|
1111
|
+
}, POLL_INTERVAL_MS);
|
|
1112
|
+
}
|
|
1068
1113
|
return () => {
|
|
1069
1114
|
listeners2.delete(listener);
|
|
1115
|
+
if (listeners2.size === 0 && pollTimer !== void 0) {
|
|
1116
|
+
clearInterval(pollTimer);
|
|
1117
|
+
pollTimer = void 0;
|
|
1118
|
+
}
|
|
1070
1119
|
};
|
|
1071
1120
|
}
|
|
1072
1121
|
};
|
|
@@ -1166,25 +1215,18 @@ function createAutomationRuntime(rpc) {
|
|
|
1166
1215
|
return rest;
|
|
1167
1216
|
})
|
|
1168
1217
|
}));
|
|
1169
|
-
},
|
|
1170
|
-
async addWorkspace(path) {
|
|
1171
|
-
const payload = { sessionId: "settings", path };
|
|
1172
|
-
const value = unwrapRpcResult(await rpc.call(CHANNEL, "add-workspace", payload));
|
|
1173
|
-
await refresh();
|
|
1174
|
-
return value;
|
|
1175
1218
|
}
|
|
1176
1219
|
};
|
|
1177
1220
|
}
|
|
1178
1221
|
|
|
1179
1222
|
// src/client/AutomationView.tsx
|
|
1180
1223
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1181
|
-
var POLL_INTERVAL_MS = 15e3;
|
|
1182
1224
|
var EXAMPLES = [
|
|
1183
1225
|
{ name: "\u6BCF\u65E5\u56DE\u5F52\u68C0\u67E5", scheduleKind: "daily", time: "09:00", weekdays: [1, 2, 3, 4, 5] },
|
|
1184
1226
|
{ name: "\u6BCF\u5468\u4F9D\u8D56\u5DE1\u68C0", scheduleKind: "weekly", time: "10:00", weekdays: [1] },
|
|
1185
1227
|
{ name: "\u5DE5\u4F5C\u65E5\u65E9\u62A5", scheduleKind: "weekly", time: "08:00", weekdays: [1, 2, 3, 4, 5] }
|
|
1186
1228
|
];
|
|
1187
|
-
function AutomationView({ t, permissionT, runtime, closeSettings
|
|
1229
|
+
function AutomationView({ t, permissionT, modelT, runtime, closeSettings }) {
|
|
1188
1230
|
const state = (0, import_react3.useSyncExternalStore)(runtime.source.subscribe, runtime.source.getSnapshot, runtime.source.getSnapshot);
|
|
1189
1231
|
const [tab, setTab] = (0, import_react3.useState)("mine");
|
|
1190
1232
|
const [query, setQuery] = (0, import_react3.useState)("");
|
|
@@ -1197,15 +1239,6 @@ function AutomationView({ t, permissionT, runtime, closeSettings, pickWorkspaceD
|
|
|
1197
1239
|
const [historyTask, setHistoryTask] = (0, import_react3.useState)("all");
|
|
1198
1240
|
const [historyStatus, setHistoryStatus] = (0, import_react3.useState)("all");
|
|
1199
1241
|
const now = (0, import_react3.useMemo)(() => new Date(state.snapshot?.serverNow ?? Date.now()), [state.snapshot?.serverNow, state.refreshedAt]);
|
|
1200
|
-
(0, import_react3.useEffect)(() => {
|
|
1201
|
-
void runtime.refresh().catch(() => void 0);
|
|
1202
|
-
const timer = window.setInterval(() => {
|
|
1203
|
-
void runtime.refresh().catch(() => void 0);
|
|
1204
|
-
}, POLL_INTERVAL_MS);
|
|
1205
|
-
return () => {
|
|
1206
|
-
window.clearInterval(timer);
|
|
1207
|
-
};
|
|
1208
|
-
}, [runtime]);
|
|
1209
1242
|
const snapshot = state.snapshot;
|
|
1210
1243
|
const workspaces = snapshot?.workspaces ?? [];
|
|
1211
1244
|
const models = snapshot?.models ?? [];
|
|
@@ -1357,15 +1390,15 @@ function AutomationView({ t, permissionT, runtime, closeSettings, pickWorkspaceD
|
|
|
1357
1390
|
{
|
|
1358
1391
|
t,
|
|
1359
1392
|
permissionT,
|
|
1393
|
+
modelT,
|
|
1360
1394
|
busy,
|
|
1361
1395
|
workspaces,
|
|
1362
1396
|
models,
|
|
1397
|
+
modelFailures: snapshot?.modelFailures ?? [],
|
|
1363
1398
|
defaultModel: snapshot?.defaultModel ?? null,
|
|
1364
1399
|
skills: snapshot?.skills ?? [],
|
|
1365
1400
|
permissions,
|
|
1366
1401
|
defaultPermission,
|
|
1367
|
-
onAddWorkspace: async (path) => runtime.addWorkspace(path).then((value) => value.id),
|
|
1368
|
-
...pickWorkspaceDirectory === void 0 ? {} : { pickWorkspaceDirectory },
|
|
1369
1402
|
editing: editingId !== void 0,
|
|
1370
1403
|
...draft === void 0 ? {} : { draft },
|
|
1371
1404
|
onClose: closeModal,
|
|
@@ -1527,7 +1560,6 @@ var en = {
|
|
|
1527
1560
|
"tabs.runs": "Run history",
|
|
1528
1561
|
"sort.created": "Newest first",
|
|
1529
1562
|
"form.workspace": "Workspace",
|
|
1530
|
-
"form.addWorkspace": "Add workspace...",
|
|
1531
1563
|
"form.workspacePath": "Folder path",
|
|
1532
1564
|
"form.workspacePathPlaceholder": "D:\\work\\project",
|
|
1533
1565
|
"form.model": "Model",
|
|
@@ -1719,7 +1751,6 @@ var zh = {
|
|
|
1719
1751
|
"tabs.runs": "\u6267\u884C\u8BB0\u5F55",
|
|
1720
1752
|
"sort.created": "\u6309\u521B\u5EFA\u65F6\u95F4\u5012\u5E8F",
|
|
1721
1753
|
"form.workspace": "\u5DE5\u4F5C\u76EE\u5F55",
|
|
1722
|
-
"form.addWorkspace": "\u6DFB\u52A0\u5DE5\u4F5C\u533A...",
|
|
1723
1754
|
"form.workspacePath": "\u76EE\u5F55\u8DEF\u5F84",
|
|
1724
1755
|
"form.workspacePathPlaceholder": "D:\\work\\project",
|
|
1725
1756
|
"form.model": "\u6A21\u578B",
|
|
@@ -2376,15 +2407,6 @@ function NativeScheduleSessionList(props) {
|
|
|
2376
2407
|
const [query, setQuery] = (0, import_react5.useState)("");
|
|
2377
2408
|
const [sort, setSort] = (0, import_react5.useState)("time");
|
|
2378
2409
|
const [groupMode, setGroupMode] = (0, import_react5.useState)("workspace");
|
|
2379
|
-
(0, import_react5.useEffect)(() => {
|
|
2380
|
-
void runtime.refresh().catch(() => void 0);
|
|
2381
|
-
const timer = window.setInterval(() => {
|
|
2382
|
-
void runtime.refresh().catch(() => void 0);
|
|
2383
|
-
}, 15e3);
|
|
2384
|
-
return () => {
|
|
2385
|
-
window.clearInterval(timer);
|
|
2386
|
-
};
|
|
2387
|
-
}, [runtime]);
|
|
2388
2410
|
const archived = (0, import_react5.useMemo)(() => new Set(archivedIds), [archivedIds]);
|
|
2389
2411
|
const listedIds = useSessions ? useSessions((snap) => Array.isArray(snap?.ids) ? snap.ids : void 0) : void 0;
|
|
2390
2412
|
const presentIds = (0, import_react5.useMemo)(() => {
|
|
@@ -2619,15 +2641,6 @@ function ScheduleRail({
|
|
|
2619
2641
|
}) {
|
|
2620
2642
|
const state = (0, import_react6.useSyncExternalStore)(runtime.source.subscribe, runtime.source.getSnapshot, runtime.source.getSnapshot);
|
|
2621
2643
|
const [folded, setFolded] = (0, import_react6.useState)({});
|
|
2622
|
-
(0, import_react6.useEffect)(() => {
|
|
2623
|
-
void runtime.refresh().catch(() => void 0);
|
|
2624
|
-
const timer = window.setInterval(() => {
|
|
2625
|
-
void runtime.refresh().catch(() => void 0);
|
|
2626
|
-
}, 15e3);
|
|
2627
|
-
return () => {
|
|
2628
|
-
window.clearInterval(timer);
|
|
2629
|
-
};
|
|
2630
|
-
}, [runtime]);
|
|
2631
2644
|
const groups = (0, import_react6.useMemo)(() => {
|
|
2632
2645
|
const snapshot = state.snapshot;
|
|
2633
2646
|
if (snapshot === void 0) return [];
|
|
@@ -2897,7 +2910,7 @@ var CSS_TEXT = `
|
|
|
2897
2910
|
.dsh-st-chip-btn:hover{background:rgba(255,255,255,.06);color:var(--dsw-alias-label-primary)}
|
|
2898
2911
|
.dsh-st-chip-btn.is-static{cursor:default;opacity:.78}
|
|
2899
2912
|
.dsh-st-chip-btn em,.dsh-st-select.is-pill .dsh-st-select-btn em{width:6px;height:6px;margin-left:2px;opacity:.55}
|
|
2900
|
-
.dsh-st-model-select{position:relative;z-index:1;min-width:0;flex:none}.dsh-st-model-select.is-open{z-index:30}.dsh-st-model-select-trigger{display:flex;align-items:center;gap:4px;min-width:0;max-width:
|
|
2913
|
+
.dsh-st-model-select{position:relative;z-index:1;min-width:0;flex:none}.dsh-st-model-select.is-open{z-index:30}.dsh-st-model-select-trigger{display:flex;align-items:center;gap:4px;min-width:0;max-width:260px;height:28px;padding:0 4px 0 8px;border:0;border-radius:24px;background:transparent;color:var(--dsw-alias-label-secondary);font-size:13px;font-weight:500;line-height:20px;cursor:pointer}.dsh-st-model-select-trigger:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.dsh-st-model-select-trigger>span:first-child{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dsh-st-model-trigger-effort{flex:none;color:var(--dsw-alias-label-tertiary);white-space:nowrap}.dsh-st-model-trigger-chevron{flex:none;transition:transform .16s ease}.dsh-st-model-trigger-chevron.is-open{transform:rotate(180deg)}.dsh-st-model-select-menu{z-index:30;width:min(240px,calc(100vw - 32px));max-height:min(360px,calc(100vh - 96px));overflow-y:auto;padding:4px;border:1px solid var(--dsw-alias-border-inverted,var(--dsw-alias-border-l2));border-radius:12px;background:var(--dsw-specific-menu,var(--dsw-alias-bg-base));box-shadow:var(--dsw-shadow-lv3)}.dsh-st-model-select-menu.is-float{position:absolute;z-index:1200;box-sizing:border-box}.dsh-st-model-select-menu .dsh-st-menu-row{min-height:40px;padding:0 10px;border-radius:10px;font-size:14px}.dsh-st-model-select-menu .dsh-st-menu-row.is-kv .dsh-st-menu-row-side{font-size:13px;color:var(--dsw-alias-label-tertiary)}.dsh-st-model-group+.dsh-st-model-group{margin-top:4px}.dsh-st-model-group-title{position:sticky;top:0;z-index:1;padding:5px 8px 3px;background:var(--dsw-specific-menu,var(--dsw-alias-bg-base));color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:500;line-height:18px}.dsh-st-model-option{display:flex;width:100%;min-height:38px;align-items:center;gap:8px;padding:6px 8px;border:0;border-radius:10px;background:transparent;color:var(--dsw-alias-label-primary);text-align:left;cursor:pointer}.dsh-st-model-option:hover,.dsh-st-model-option:focus-visible{background:var(--dsw-alias-interactive-bg-hover);outline:none}.dsh-st-model-option-copy{display:flex;min-width:0;flex:1;flex-direction:column}.dsh-st-model-name{overflow:hidden;font-size:14px;font-weight:500;line-height:20px;text-overflow:ellipsis;white-space:nowrap}.dsh-st-model-description{overflow:hidden;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;text-overflow:ellipsis;white-space:nowrap}.dsh-st-model-check{display:grid;flex:0 0 18px;place-items:center;color:var(--dsw-alias-label-primary)}.dsh-st-model-warning{margin:4px;padding:8px;border-radius:8px;background:var(--dsw-alias-interactive-bg-hover-danger,rgba(248,81,73,.1));color:var(--dsw-alias-state-error-primary,#f85149);font-size:12px;line-height:18px}.dsh-st-model-empty{padding:14px 12px;color:var(--dsw-alias-label-tertiary);font-size:12px;text-align:center}
|
|
2901
2914
|
.dsh-st-suffix{color:var(--dsw-alias-label-secondary);font-size:13px}
|
|
2902
2915
|
.dsh-st-inline input.is-narrow{width:72px;flex:none}
|
|
2903
2916
|
.dsh-st-time{display:inline-flex;align-items:center;gap:2px;min-height:36px;padding:0 8px;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:rgba(255,255,255,.04)}
|
|
@@ -2958,20 +2971,30 @@ var name = "dsh-automation-client";
|
|
|
2958
2971
|
var inject = ["slots", "locale", "connection", "sessions"];
|
|
2959
2972
|
var SETTINGS_CLOCK_SVG = '<svg viewBox="0 0 16 16" width="16" height="16" fill="none" aria-hidden="true" data-dsh-schedule-icon="1"><path fill="currentColor" d="M8 1.15A6.85 6.85 0 1 0 8 14.85 6.85 6.85 0 0 0 8 1.15Zm0 1.4a5.45 5.45 0 1 1 0 10.9 5.45 5.45 0 0 1 0-10.9Z"/><path fill="currentColor" d="M8.62 4.35H7.28v4.2l3.02 1.78.67-1.13-2.35-1.39V4.35Z"/></svg>';
|
|
2960
2973
|
function installSettingsNavIcon(labels) {
|
|
2961
|
-
const
|
|
2962
|
-
|
|
2963
|
-
const
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2974
|
+
const wanted = new Set(labels().map((item) => item.trim()).filter((item) => item !== ""));
|
|
2975
|
+
const applyButton = (button) => {
|
|
2976
|
+
const text = (button.textContent ?? "").replace(/\s+/g, " ").trim();
|
|
2977
|
+
if (!wanted.has(text)) return;
|
|
2978
|
+
const svg = button.querySelector("svg");
|
|
2979
|
+
if (svg === null || svg.getAttribute("data-dsh-schedule-icon") === "1") return;
|
|
2980
|
+
svg.outerHTML = SETTINGS_CLOCK_SVG;
|
|
2981
|
+
};
|
|
2982
|
+
const scan = (root) => {
|
|
2983
|
+
if (root instanceof HTMLButtonElement) applyButton(root);
|
|
2984
|
+
for (const button of root.querySelectorAll?.("button") ?? []) applyButton(button);
|
|
2971
2985
|
};
|
|
2972
|
-
|
|
2973
|
-
const observer = new MutationObserver(
|
|
2974
|
-
|
|
2986
|
+
scan(document);
|
|
2987
|
+
const observer = new MutationObserver((mutations) => {
|
|
2988
|
+
for (const mutation of mutations) {
|
|
2989
|
+
const target = mutation.target instanceof Element ? mutation.target : mutation.target.parentElement;
|
|
2990
|
+
const owner = target?.closest("button");
|
|
2991
|
+
if (owner instanceof HTMLButtonElement) applyButton(owner);
|
|
2992
|
+
for (const node of mutation.addedNodes) {
|
|
2993
|
+
if (node instanceof Element) scan(node);
|
|
2994
|
+
}
|
|
2995
|
+
}
|
|
2996
|
+
});
|
|
2997
|
+
observer.observe(document.documentElement, { childList: true, characterData: true, subtree: true });
|
|
2975
2998
|
return () => {
|
|
2976
2999
|
observer.disconnect();
|
|
2977
3000
|
};
|
|
@@ -2981,6 +3004,7 @@ function apply(ctx) {
|
|
|
2981
3004
|
ctx.effect(() => ctx.locale.register(NS, { zh, en }), "dsh-automation: locale");
|
|
2982
3005
|
const t = ctx.locale.bind(NS);
|
|
2983
3006
|
const permissionT = ctx.locale.bind("permission.access");
|
|
3007
|
+
const modelT = ctx.locale.bind("model");
|
|
2984
3008
|
const runtime = createAutomationRuntime(ctx.connection.rpc);
|
|
2985
3009
|
ctx.effect(() => installSettingsNavIcon(() => [t("tab"), "Scheduled tasks", "\u5B9A\u65F6\u4EFB\u52A1"]), "dsh-automation: settings icon");
|
|
2986
3010
|
ctx.slots.inject("settings.section", () => ctx.slots.register({
|
|
@@ -2991,8 +3015,7 @@ function apply(ctx) {
|
|
|
2991
3015
|
label: () => t("tab"),
|
|
2992
3016
|
icon: "schedule"
|
|
2993
3017
|
}, function ScheduledTasksSettings(props) {
|
|
2994
|
-
|
|
2995
|
-
return (0, import_react7.createElement)(AutomationView, { t, permissionT, runtime, ...props.close === void 0 ? {} : { closeSettings: props.close }, ...workspacesApi === void 0 ? {} : { pickWorkspaceDirectory: () => workspacesApi.pickDirectory() } });
|
|
3018
|
+
return (0, import_react7.createElement)(AutomationView, { t, permissionT, modelT, runtime, ...props.close === void 0 ? {} : { closeSettings: props.close } });
|
|
2996
3019
|
}));
|
|
2997
3020
|
ctx.slots.inject("sidebar.schedule", () => ctx.slots.register({
|
|
2998
3021
|
name: "sidebar.schedule",
|
|
@@ -3200,12 +3223,5 @@ function readSlotEntries(ctx, name2) {
|
|
|
3200
3223
|
function slotHasEntries(ctx, name2) {
|
|
3201
3224
|
return readSlotEntries(ctx, name2).length > 0;
|
|
3202
3225
|
}
|
|
3203
|
-
function readOptionalWorkspaces(ctx) {
|
|
3204
|
-
try {
|
|
3205
|
-
return ctx.workspaces;
|
|
3206
|
-
} catch {
|
|
3207
|
-
return void 0;
|
|
3208
|
-
}
|
|
3209
|
-
}
|
|
3210
3226
|
return module.exports; } });
|
|
3211
3227
|
//# sourceMappingURL=client.js.map
|