@michengai/dsh-automation 0.1.6 → 0.1.8
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 +3 -3
- package/README.zh-CN.md +3 -3
- package/lib/client.js +97 -74
- package/lib/client.js.map +3 -3
- package/lib/index.js +67 -10
- package/lib/types/client/AutomationView.d.ts +1 -1
- package/lib/types/client/contracts.d.ts +3 -1
- package/lib/types/client/create-modal.d.ts +6 -1
- package/lib/types/client/helpers.d.ts +2 -2
- package/lib/types/client/locales.d.ts +0 -13
- package/lib/types/client/permissions.d.ts +4 -0
- package/lib/types/client/protocol.d.ts +8 -1
- package/lib/types/executor.d.ts +3 -2
- package/lib/types/index.d.ts +2 -6
- package/lib/types/permission-presets.d.ts +14 -0
- package/lib/types/service.d.ts +10 -0
- package/lib/types/types.d.ts +2 -1
- package/package.json +9 -10
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
- Create, pause, resume, run now, and delete rules from the Web UI or Agent tools.
|
|
26
26
|
- Start each occurrence in a fresh root Agent and Session. Source-chat history is not inherited.
|
|
27
27
|
- Support once, interval, hourly, daily, weekly, monthly, and custom-every-N-days schedules.
|
|
28
|
-
- Pick workspace, model, skills, and
|
|
28
|
+
- Pick workspace, model, skills, and any permission preset exposed by the Host.
|
|
29
29
|
- Create from chat: describe the schedule in any conversation, then confirm with the official approval card.
|
|
30
30
|
- Keep durable run history: `queued`, `running`, `succeeded`, `failed`, `skipped`, `cancelled`.
|
|
31
31
|
- Add a sidebar **Scheduled** tab. Folders are task names and child sessions are run times. On stock DSH it wraps the official workspace tree and does not depend on `dsh-codex-ui`.
|
|
@@ -124,8 +124,8 @@ Each dispatched run uses the saved prompt, workspace, model, and permission boun
|
|
|
124
124
|
|
|
125
125
|
| Item | Behavior |
|
|
126
126
|
| --- | --- |
|
|
127
|
-
| Permission |
|
|
128
|
-
| Full access |
|
|
127
|
+
| Permission | Options and the default come directly from the Host `permissionPresets` service, including custom presets. |
|
|
128
|
+
| Full access | The official `danger-full-access` option uses the same risk confirmation and orange warning as Chat. |
|
|
129
129
|
| Approval | Chat create follows the session policy. Full access (`never`) proceeds; Workspace Write / Read Only (`ask`) shows the official card. Unattended runs stay fail-closed `never`. |
|
|
130
130
|
| Retry | No automatic retry after a started run. |
|
|
131
131
|
| Host restart | Leftover `queued` / `running` records become `failed(host_interrupted)`. |
|
package/README.zh-CN.md
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
- 支持 Web 设置页和 Agent 工具创建、暂停、恢复、立即运行和删除。
|
|
26
26
|
- 每次到期都启动全新 root Agent 和 Session,不继承来源对话。
|
|
27
27
|
- 计划类型包括不重复、间隔、每小时、每天、每周、每月和自定义间隔天数。
|
|
28
|
-
- 新建弹窗可选择工作目录、模型、技能,以及
|
|
28
|
+
- 新建弹窗可选择工作目录、模型、技能,以及 Host 官方提供的权限预设。
|
|
29
29
|
- 在任意对话里描述定时任务即可创建;Full access 直接执行,其他权限走官方授权卡。
|
|
30
30
|
- 运行状态包含 `queued`、`running`、`succeeded`、`failed`、`skipped`、`cancelled`。
|
|
31
31
|
- 侧栏提供「定时」页签:文件夹是任务名称,子会话是执行时间。原生下只包裹官方任务树,不依赖 `dsh-codex-ui`。
|
|
@@ -124,8 +124,8 @@ dsh --profile web --dump-config
|
|
|
124
124
|
|
|
125
125
|
| 项目 | 行为 |
|
|
126
126
|
| --- | --- |
|
|
127
|
-
| 权限 |
|
|
128
|
-
| 完全访问 |
|
|
127
|
+
| 权限 | 列表和默认值直接来自 Host 官方 `permissionPresets` 服务;支持 Host 注册的自定义预设。 |
|
|
128
|
+
| 完全访问 | 选择官方 `danger-full-access` 时显示与 Chat 一致的风险确认和橙色提示。 |
|
|
129
129
|
| 审批 | 对话创建跟随当前会话策略。Full access(`never`)直接创建;Workspace Write / Read Only(`ask`)走官方授权卡。无人值守运行仍是 fail-closed 的 `never`。 |
|
|
130
130
|
| 重试 | 已经开始的运行不会自动重试。 |
|
|
131
131
|
| Host 重启 | 遗留的 `queued` / `running` 会变成 `failed(host_interrupted)`。 |
|
package/lib/client.js
CHANGED
|
@@ -63,7 +63,7 @@ function localDateTimeValue(date = /* @__PURE__ */ new Date()) {
|
|
|
63
63
|
const offset = future.getTimezoneOffset() * 6e4;
|
|
64
64
|
return new Date(future.getTime() - offset).toISOString().slice(0, 16);
|
|
65
65
|
}
|
|
66
|
-
function defaultFormState(now = /* @__PURE__ */ new Date(), workspaces = [], defaultModel) {
|
|
66
|
+
function defaultFormState(now = /* @__PURE__ */ new Date(), workspaces = [], defaultModel, defaultPermission = "") {
|
|
67
67
|
return {
|
|
68
68
|
name: "",
|
|
69
69
|
prompt: "",
|
|
@@ -76,7 +76,7 @@ function defaultFormState(now = /* @__PURE__ */ new Date(), workspaces = [], def
|
|
|
76
76
|
monthDay: "1",
|
|
77
77
|
customDays: "2",
|
|
78
78
|
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone || "Asia/Shanghai",
|
|
79
|
-
permission:
|
|
79
|
+
permission: defaultPermission,
|
|
80
80
|
workspaceId: workspaces[0]?.id ?? "",
|
|
81
81
|
modelKey: defaultModel === void 0 || defaultModel === null ? "default" : `${defaultModel.provider}::${defaultModel.model}`,
|
|
82
82
|
reasoningEffort: "high",
|
|
@@ -228,8 +228,8 @@ function startOfWeek(value) {
|
|
|
228
228
|
next.setDate(next.getDate() - offset);
|
|
229
229
|
return next;
|
|
230
230
|
}
|
|
231
|
-
function formFromAutomation(item, workspaces = [], defaultModel) {
|
|
232
|
-
const base = defaultFormState(/* @__PURE__ */ new Date(), workspaces, defaultModel);
|
|
231
|
+
function formFromAutomation(item, workspaces = [], defaultModel, defaultPermission = item.permission) {
|
|
232
|
+
const base = defaultFormState(/* @__PURE__ */ new Date(), workspaces, defaultModel, defaultPermission);
|
|
233
233
|
const schedule = item.schedule;
|
|
234
234
|
const modelKey = item.provider && item.model ? `${item.provider}::${item.model}` : "default";
|
|
235
235
|
const common = {
|
|
@@ -397,9 +397,23 @@ function RunningStateDot() {
|
|
|
397
397
|
// src/client/create-modal.tsx
|
|
398
398
|
var import_react2 = require("react");
|
|
399
399
|
|
|
400
|
+
// src/client/permissions.ts
|
|
401
|
+
var BUILT_IN_PERMISSION_LABELS = /* @__PURE__ */ new Map([
|
|
402
|
+
["read-only", ["preset.readOnly", "Read Only"]],
|
|
403
|
+
["workspace-write", ["preset.workspaceWrite", "Workspace Write"]],
|
|
404
|
+
["danger-full-access", ["preset.fullAccess", "Full access"]]
|
|
405
|
+
]);
|
|
406
|
+
function permissionLabel(option, t) {
|
|
407
|
+
const builtIn = BUILT_IN_PERMISSION_LABELS.get(option.value);
|
|
408
|
+
if (builtIn !== void 0 && (option.name === option.value || option.name === builtIn[1])) {
|
|
409
|
+
return t(builtIn[0]);
|
|
410
|
+
}
|
|
411
|
+
return option.name || option.value;
|
|
412
|
+
}
|
|
413
|
+
|
|
400
414
|
// src/client/create-modal-logic.ts
|
|
401
415
|
function shouldConfirmFullAccess(current, next) {
|
|
402
|
-
return current !==
|
|
416
|
+
return current !== next && next === "danger-full-access";
|
|
403
417
|
}
|
|
404
418
|
async function adoptPickedWorkspace(input) {
|
|
405
419
|
const path = await input.pick();
|
|
@@ -618,11 +632,14 @@ var MINUTES = Array.from({ length: 60 }, (_, index) => String(index).padStart(2,
|
|
|
618
632
|
var EFFORTS = ["none", "low", "medium", "high"];
|
|
619
633
|
function CreateModal({
|
|
620
634
|
t,
|
|
635
|
+
permissionT,
|
|
621
636
|
busy,
|
|
622
637
|
workspaces,
|
|
623
638
|
models,
|
|
624
639
|
defaultModel,
|
|
625
640
|
skills,
|
|
641
|
+
permissions,
|
|
642
|
+
defaultPermission,
|
|
626
643
|
draft,
|
|
627
644
|
editing,
|
|
628
645
|
onClose,
|
|
@@ -630,9 +647,9 @@ function CreateModal({
|
|
|
630
647
|
onAddWorkspace,
|
|
631
648
|
pickWorkspaceDirectory
|
|
632
649
|
}) {
|
|
633
|
-
const [form, setForm] = (0, import_react2.useState)(() => ({ ...defaultFormState(/* @__PURE__ */ new Date(), workspaces, defaultModel), ...draft }));
|
|
650
|
+
const [form, setForm] = (0, import_react2.useState)(() => ({ ...defaultFormState(/* @__PURE__ */ new Date(), workspaces, defaultModel, defaultPermission), ...draft }));
|
|
634
651
|
const [validationError, setValidationError] = (0, import_react2.useState)();
|
|
635
|
-
const [
|
|
652
|
+
const [confirmingPermission, setConfirmingPermission] = (0, import_react2.useState)();
|
|
636
653
|
const [fullAccessAcknowledged, setFullAccessAcknowledged] = (0, import_react2.useState)(false);
|
|
637
654
|
const update = (patch) => {
|
|
638
655
|
setForm((current) => ({ ...current, ...patch }));
|
|
@@ -641,18 +658,19 @@ function CreateModal({
|
|
|
641
658
|
const choosePermission = (permission) => {
|
|
642
659
|
if (shouldConfirmFullAccess(form.permission, permission)) {
|
|
643
660
|
setFullAccessAcknowledged(false);
|
|
644
|
-
|
|
661
|
+
setConfirmingPermission(permission);
|
|
645
662
|
return;
|
|
646
663
|
}
|
|
647
664
|
update({ permission });
|
|
648
665
|
};
|
|
649
666
|
const cancelFullAccessConfirmation = () => {
|
|
650
667
|
setFullAccessAcknowledged(false);
|
|
651
|
-
|
|
668
|
+
setConfirmingPermission(void 0);
|
|
652
669
|
};
|
|
653
670
|
const confirmFullAccess = () => {
|
|
654
671
|
if (!fullAccessAcknowledged) return;
|
|
655
|
-
|
|
672
|
+
if (confirmingPermission === void 0) return;
|
|
673
|
+
update({ permission: confirmingPermission });
|
|
656
674
|
cancelFullAccessConfirmation();
|
|
657
675
|
};
|
|
658
676
|
(0, import_react2.useEffect)(() => {
|
|
@@ -843,11 +861,11 @@ function CreateModal({
|
|
|
843
861
|
up: true,
|
|
844
862
|
icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ShieldIcon, { width: 14, height: 14 }),
|
|
845
863
|
value: form.permission,
|
|
846
|
-
options:
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
864
|
+
options: permissions.map((option) => ({
|
|
865
|
+
value: option.value,
|
|
866
|
+
label: permissionLabel(option, permissionT),
|
|
867
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ShieldIcon, { width: 14, height: 14 })
|
|
868
|
+
})),
|
|
851
869
|
onChange: choosePermission
|
|
852
870
|
}
|
|
853
871
|
)
|
|
@@ -876,12 +894,12 @@ function CreateModal({
|
|
|
876
894
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
877
895
|
import_dsh_client_ui_primitives.RiskConfirmation,
|
|
878
896
|
{
|
|
879
|
-
open:
|
|
880
|
-
title:
|
|
881
|
-
description:
|
|
882
|
-
acknowledgeLabel:
|
|
883
|
-
cancelLabel:
|
|
884
|
-
confirmLabel:
|
|
897
|
+
open: confirmingPermission !== void 0,
|
|
898
|
+
title: permissionT("confirm.title"),
|
|
899
|
+
description: permissionT("confirm.description"),
|
|
900
|
+
acknowledgeLabel: permissionT("confirm.acknowledge"),
|
|
901
|
+
cancelLabel: permissionT("confirm.cancel"),
|
|
902
|
+
confirmLabel: permissionT("confirm.enable"),
|
|
885
903
|
acknowledged: fullAccessAcknowledged,
|
|
886
904
|
onAcknowledgedChange: setFullAccessAcknowledged,
|
|
887
905
|
onCancel: cancelFullAccessConfirmation,
|
|
@@ -904,16 +922,22 @@ function ModelPicker({
|
|
|
904
922
|
const modelLabel = selected === void 0 ? t("form.modelDefault") : selected.label;
|
|
905
923
|
const effortLabel = t(`form.effort.${effort}`);
|
|
906
924
|
const trigger = effort === "none" ? modelLabel : `${modelLabel} ${effortLabel}`;
|
|
925
|
+
const modelGroups = Array.from(models.reduce((groups, item) => {
|
|
926
|
+
const group = groups.get(item.provider) ?? [];
|
|
927
|
+
group.push(item);
|
|
928
|
+
groups.set(item.provider, group);
|
|
929
|
+
return groups;
|
|
930
|
+
}, /* @__PURE__ */ new Map()));
|
|
907
931
|
const open = (next) => {
|
|
908
932
|
setPane(next);
|
|
909
933
|
menu.setOpen(true);
|
|
910
934
|
};
|
|
911
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: `dsh-st-select
|
|
935
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: `dsh-st-model-select${menu.open ? " is-open" : ""}`, ref: menu.root, children: [
|
|
912
936
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
913
937
|
"button",
|
|
914
938
|
{
|
|
915
939
|
type: "button",
|
|
916
|
-
className: "dsh-st-select-
|
|
940
|
+
className: "dsh-st-model-select-trigger",
|
|
917
941
|
onMouseDown: (event) => event.stopPropagation(),
|
|
918
942
|
onClick: () => {
|
|
919
943
|
if (menu.open) {
|
|
@@ -928,38 +952,54 @@ function ModelPicker({
|
|
|
928
952
|
]
|
|
929
953
|
}
|
|
930
954
|
),
|
|
931
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(MenuPopup, { open: menu.open, anchor: menu.root, menuRef: menu.menu, up: true, end: true, className: "dsh-st-select-menu is-
|
|
955
|
+
/* @__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", children: [
|
|
932
956
|
pane === "root" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
933
957
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MenuRow, { kv: true, label: t("form.model"), hint: modelLabel, chevron: true, onClick: () => setPane("model") }),
|
|
934
958
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MenuRow, { kv: true, label: t("form.effort"), hint: effortLabel, chevron: true, onClick: () => setPane("effort") })
|
|
935
959
|
] }),
|
|
936
960
|
pane === "model" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
937
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.
|
|
938
|
-
|
|
961
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
962
|
+
"button",
|
|
939
963
|
{
|
|
940
|
-
|
|
941
|
-
|
|
964
|
+
type: "button",
|
|
965
|
+
role: "menuitemradio",
|
|
966
|
+
"aria-checked": modelKey === "default",
|
|
967
|
+
className: "dsh-st-model-option",
|
|
942
968
|
onClick: () => {
|
|
943
969
|
onModelKey("default");
|
|
944
970
|
menu.setOpen(false);
|
|
945
|
-
}
|
|
971
|
+
},
|
|
972
|
+
children: [
|
|
973
|
+
/* @__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: t("form.modelDefault") }) }),
|
|
974
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-st-model-check", children: modelKey === "default" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(CheckOutlineIcon, { width: 16, height: 16 }) })
|
|
975
|
+
]
|
|
946
976
|
}
|
|
947
977
|
),
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
978
|
+
modelGroups.map(([provider, group]) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { role: "group", "aria-label": provider, className: "dsh-st-model-group", children: [
|
|
979
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-st-model-group-title", children: provider }),
|
|
980
|
+
group.map((item) => {
|
|
981
|
+
const value = `${item.provider}::${item.model}`;
|
|
982
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
983
|
+
"button",
|
|
984
|
+
{
|
|
985
|
+
type: "button",
|
|
986
|
+
role: "menuitemradio",
|
|
987
|
+
"aria-checked": value === modelKey,
|
|
988
|
+
className: "dsh-st-model-option",
|
|
989
|
+
title: item.label,
|
|
990
|
+
onClick: () => {
|
|
991
|
+
onModelKey(value);
|
|
992
|
+
menu.setOpen(false);
|
|
993
|
+
},
|
|
994
|
+
children: [
|
|
995
|
+
/* @__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: item.label }) }),
|
|
996
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-st-model-check", children: value === modelKey && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(CheckOutlineIcon, { width: 16, height: 16 }) })
|
|
997
|
+
]
|
|
998
|
+
},
|
|
999
|
+
value
|
|
1000
|
+
);
|
|
1001
|
+
})
|
|
1002
|
+
] }, provider))
|
|
963
1003
|
] }),
|
|
964
1004
|
pane === "effort" && EFFORTS.map((item) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
965
1005
|
MenuRow,
|
|
@@ -1193,7 +1233,7 @@ var EXAMPLES = [
|
|
|
1193
1233
|
{ name: "\u6BCF\u5468\u4F9D\u8D56\u5DE1\u68C0", scheduleKind: "weekly", time: "10:00", weekdays: [1] },
|
|
1194
1234
|
{ name: "\u5DE5\u4F5C\u65E5\u65E9\u62A5", scheduleKind: "weekly", time: "08:00", weekdays: [1, 2, 3, 4, 5] }
|
|
1195
1235
|
];
|
|
1196
|
-
function AutomationView({ t, runtime, closeSettings, pickWorkspaceDirectory }) {
|
|
1236
|
+
function AutomationView({ t, permissionT, runtime, closeSettings, pickWorkspaceDirectory }) {
|
|
1197
1237
|
const state = (0, import_react3.useSyncExternalStore)(runtime.source.subscribe, runtime.source.getSnapshot, runtime.source.getSnapshot);
|
|
1198
1238
|
const [tab, setTab] = (0, import_react3.useState)("mine");
|
|
1199
1239
|
const [query, setQuery] = (0, import_react3.useState)("");
|
|
@@ -1218,6 +1258,8 @@ function AutomationView({ t, runtime, closeSettings, pickWorkspaceDirectory }) {
|
|
|
1218
1258
|
const snapshot = state.snapshot;
|
|
1219
1259
|
const workspaces = snapshot?.workspaces ?? [];
|
|
1220
1260
|
const models = snapshot?.models ?? [];
|
|
1261
|
+
const permissions = snapshot?.permissions ?? [];
|
|
1262
|
+
const defaultPermission = snapshot?.defaultPermission ?? "";
|
|
1221
1263
|
const automations = (snapshot?.automations ?? []).filter((item) => query.trim() === "" || `${item.name} ${item.prompt}`.toLowerCase().includes(query.trim().toLowerCase())).slice().sort((left, right) => Date.parse(right.createdAt) - Date.parse(left.createdAt));
|
|
1222
1264
|
const runs = (snapshot?.runs ?? []).filter((run) => {
|
|
1223
1265
|
if (historyTask !== "all" && run.automationId !== historyTask) return false;
|
|
@@ -1242,13 +1284,14 @@ function AutomationView({ t, runtime, closeSettings, pickWorkspaceDirectory }) {
|
|
|
1242
1284
|
setEditingId(void 0);
|
|
1243
1285
|
};
|
|
1244
1286
|
const openCreate = (partial) => {
|
|
1287
|
+
if (defaultPermission === "" || permissions.length === 0) return;
|
|
1245
1288
|
setEditingId(void 0);
|
|
1246
1289
|
setDraft(partial);
|
|
1247
1290
|
setCreating(true);
|
|
1248
1291
|
};
|
|
1249
1292
|
const openEdit = (item) => {
|
|
1250
1293
|
setEditingId(item.id);
|
|
1251
|
-
setDraft(formFromAutomation(item, workspaces, snapshot?.defaultModel ?? null));
|
|
1294
|
+
setDraft(formFromAutomation(item, workspaces, snapshot?.defaultModel ?? null, snapshot?.defaultPermission ?? item.permission));
|
|
1252
1295
|
setCreating(true);
|
|
1253
1296
|
};
|
|
1254
1297
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dsh-st-shell", children: [
|
|
@@ -1266,7 +1309,7 @@ function AutomationView({ t, runtime, closeSettings, pickWorkspaceDirectory }) {
|
|
|
1266
1309
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChatIcon, {}),
|
|
1267
1310
|
t("action.chatCreate")
|
|
1268
1311
|
] }),
|
|
1269
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("button", { type: "button", className: "dsh-st-btn dsh-st-btn--primary", onClick: () => openCreate(), children: [
|
|
1312
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("button", { type: "button", className: "dsh-st-btn dsh-st-btn--primary", disabled: defaultPermission === "" || permissions.length === 0, onClick: () => openCreate(), children: [
|
|
1270
1313
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PlusIcon, {}),
|
|
1271
1314
|
t("action.create")
|
|
1272
1315
|
] }),
|
|
@@ -1286,6 +1329,7 @@ function AutomationView({ t, runtime, closeSettings, pickWorkspaceDirectory }) {
|
|
|
1286
1329
|
{
|
|
1287
1330
|
type: "button",
|
|
1288
1331
|
className: "dsh-st-example",
|
|
1332
|
+
disabled: defaultPermission === "" || permissions.length === 0,
|
|
1289
1333
|
onClick: () => openCreate({
|
|
1290
1334
|
name: t(`examples.${index + 1}.title`),
|
|
1291
1335
|
prompt: t(`examples.${index + 1}.body`),
|
|
@@ -1361,11 +1405,14 @@ function AutomationView({ t, runtime, closeSettings, pickWorkspaceDirectory }) {
|
|
|
1361
1405
|
CreateModal,
|
|
1362
1406
|
{
|
|
1363
1407
|
t,
|
|
1408
|
+
permissionT,
|
|
1364
1409
|
busy,
|
|
1365
1410
|
workspaces,
|
|
1366
1411
|
models,
|
|
1367
1412
|
defaultModel: snapshot?.defaultModel ?? null,
|
|
1368
1413
|
skills: snapshot?.skills ?? [],
|
|
1414
|
+
permissions,
|
|
1415
|
+
defaultPermission,
|
|
1369
1416
|
onAddWorkspace: async (path) => runtime.addWorkspace(path).then((value) => value.id),
|
|
1370
1417
|
...pickWorkspaceDirectory === void 0 ? {} : { pickWorkspaceDirectory },
|
|
1371
1418
|
editing: editingId !== void 0,
|
|
@@ -1595,16 +1642,6 @@ var en = {
|
|
|
1595
1642
|
"form.days": "Weekdays",
|
|
1596
1643
|
"form.timeZone": "Time zone",
|
|
1597
1644
|
"form.permission": "Permission boundary",
|
|
1598
|
-
"form.readOnly": "Read Only",
|
|
1599
|
-
"form.readOnlyHint": "Inspect the workspace without changing files.",
|
|
1600
|
-
"form.workspaceWrite": "Workspace Write",
|
|
1601
|
-
"form.fullAccess": "Full access",
|
|
1602
|
-
"form.workspaceWriteHint": "May change files in this workspace; past approvals are not reused.",
|
|
1603
|
-
"access.confirm.title": "Enable Full access?",
|
|
1604
|
-
"access.confirm.description": "Full access reduces confirmation steps and allows the Agent to directly perform more operations, including sensitive operations, file changes, or external commands. Use it only when you trust this task.",
|
|
1605
|
-
"access.confirm.acknowledge": "I understand the risks and want to continue",
|
|
1606
|
-
"access.confirm.cancel": "Cancel",
|
|
1607
|
-
"access.confirm.enable": "Enable Full access",
|
|
1608
1645
|
"form.cancel": "Cancel",
|
|
1609
1646
|
"form.submit": "Create automation",
|
|
1610
1647
|
"form.submitting": "Creating\u2026",
|
|
@@ -1632,9 +1669,6 @@ var en = {
|
|
|
1632
1669
|
"card.nextRun": "Next",
|
|
1633
1670
|
"card.lastRun": "Last",
|
|
1634
1671
|
"card.never": "Not yet run",
|
|
1635
|
-
"card.permission.read-only": "Read-only",
|
|
1636
|
-
"card.permission.workspace-write": "Workspace write",
|
|
1637
|
-
"card.permission.full-access": "Full access",
|
|
1638
1672
|
"schedule.onceAt": "Once \xB7 {time}",
|
|
1639
1673
|
"schedule.everyMinutes": "Every {count} minutes",
|
|
1640
1674
|
"schedule.dailyAt": "Daily \xB7 {time}",
|
|
@@ -1800,16 +1834,6 @@ var zh = {
|
|
|
1800
1834
|
"form.days": "\u661F\u671F",
|
|
1801
1835
|
"form.timeZone": "\u65F6\u533A",
|
|
1802
1836
|
"form.permission": "\u6743\u9650\u8FB9\u754C",
|
|
1803
|
-
"form.readOnly": "Read Only",
|
|
1804
|
-
"form.readOnlyHint": "\u53EF\u4EE5\u68C0\u67E5\u5DE5\u4F5C\u533A\uFF0C\u4F46\u4E0D\u4F1A\u4FEE\u6539\u6587\u4EF6\u3002",
|
|
1805
|
-
"form.workspaceWrite": "Workspace Write",
|
|
1806
|
-
"form.fullAccess": "Full access",
|
|
1807
|
-
"form.workspaceWriteHint": "\u53EF\u4EE5\u4FEE\u6539\u5F53\u524D\u5DE5\u4F5C\u533A\u6587\u4EF6\uFF1B\u4E0D\u4F1A\u7EE7\u627F\u5386\u53F2\u6279\u51C6\u3002",
|
|
1808
|
-
"access.confirm.title": "\u786E\u8BA4\u542F\u7528 \u5B8C\u5168\u8BBF\u95EE\uFF1F",
|
|
1809
|
-
"access.confirm.description": "\u542F\u7528 \u5B8C\u5168\u8BBF\u95EE \u540E\uFF0Cagent \u5C06\u51CF\u5C11\u786E\u8BA4\u6B65\u9AA4\uFF0C\u5E76\u4E14\u53EF\u4EE5\u76F4\u63A5\u6267\u884C\u66F4\u591A\u64CD\u4F5C\uFF0C\u5305\u62EC\u654F\u611F\u64CD\u4F5C\u3001\u6587\u4EF6\u4FEE\u6539\u6216\u5916\u90E8\u547D\u4EE4\u3002\u4EC5\u5EFA\u8BAE\u5728\u4F60\u4FE1\u4EFB\u5F53\u524D\u4EFB\u52A1\u65F6\u4F7F\u7528\u3002",
|
|
1810
|
-
"access.confirm.acknowledge": "\u6211\u5DF2\u4E86\u89E3\u98CE\u9669\uFF0C\u5E76\u613F\u610F\u7EE7\u7EED",
|
|
1811
|
-
"access.confirm.cancel": "\u53D6\u6D88",
|
|
1812
|
-
"access.confirm.enable": "\u542F\u7528 \u5B8C\u5168\u8BBF\u95EE",
|
|
1813
1837
|
"form.cancel": "\u53D6\u6D88",
|
|
1814
1838
|
"form.submit": "\u521B\u5EFA\u81EA\u52A8\u5316",
|
|
1815
1839
|
"form.submitting": "\u521B\u5EFA\u4E2D\u2026",
|
|
@@ -1837,9 +1861,6 @@ var zh = {
|
|
|
1837
1861
|
"card.nextRun": "\u4E0B\u6B21",
|
|
1838
1862
|
"card.lastRun": "\u6700\u8FD1",
|
|
1839
1863
|
"card.never": "\u5C1A\u672A\u8FD0\u884C",
|
|
1840
|
-
"card.permission.read-only": "\u53EA\u8BFB",
|
|
1841
|
-
"card.permission.workspace-write": "\u53EF\u5199\u5DE5\u4F5C\u533A",
|
|
1842
|
-
"card.permission.full-access": "Full access",
|
|
1843
1864
|
"schedule.onceAt": "\u5355\u6B21 \xB7 {time}",
|
|
1844
1865
|
"schedule.everyMinutes": "\u6BCF {count} \u5206\u949F",
|
|
1845
1866
|
"schedule.dailyAt": "\u6BCF\u5929 \xB7 {time}",
|
|
@@ -2925,6 +2946,7 @@ var CSS_TEXT = `
|
|
|
2925
2946
|
.dsh-st-chip-btn:hover{background:rgba(255,255,255,.06);color:var(--dsw-alias-label-primary)}
|
|
2926
2947
|
.dsh-st-chip-btn.is-static{cursor:default;opacity:.78}
|
|
2927
2948
|
.dsh-st-chip-btn em,.dsh-st-select.is-pill .dsh-st-select-btn em{width:6px;height:6px;margin-left:2px;opacity:.55}
|
|
2949
|
+
.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:220px;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{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dsh-st-model-select-trigger em{width:6px;height:6px;margin-left:2px;border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;transform:rotate(45deg) translateY(-2px);opacity:.55;flex:none}.dsh-st-model-select-menu{z-index:30;width:min(240px,calc(100vw - 32px));max-height:min(360px,calc(100vh - 96px));overflow:hidden;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-check{display:grid;flex:0 0 18px;place-items:center;color:var(--dsw-alias-label-primary)}
|
|
2928
2950
|
.dsh-st-suffix{color:var(--dsw-alias-label-secondary);font-size:13px}
|
|
2929
2951
|
.dsh-st-inline input.is-narrow{width:72px;flex:none}
|
|
2930
2952
|
.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)}
|
|
@@ -3007,6 +3029,7 @@ function apply(ctx) {
|
|
|
3007
3029
|
ctx.effect(() => installStyles(), "dsh-automation: styles");
|
|
3008
3030
|
ctx.effect(() => ctx.locale.register(NS, { zh, en }), "dsh-automation: locale");
|
|
3009
3031
|
const t = ctx.locale.bind(NS);
|
|
3032
|
+
const permissionT = ctx.locale.bind("permission.access");
|
|
3010
3033
|
const runtime = createAutomationRuntime(ctx.connection.rpc);
|
|
3011
3034
|
ctx.effect(() => installSettingsNavIcon(() => [t("tab"), "Scheduled tasks", "\u5B9A\u65F6\u4EFB\u52A1"]), "dsh-automation: settings icon");
|
|
3012
3035
|
ctx.slots.inject("settings.section", () => ctx.slots.register({
|
|
@@ -3018,7 +3041,7 @@ function apply(ctx) {
|
|
|
3018
3041
|
icon: "schedule"
|
|
3019
3042
|
}, function ScheduledTasksSettings(props) {
|
|
3020
3043
|
const workspacesApi = readOptionalWorkspaces(ctx);
|
|
3021
|
-
return (0, import_react7.createElement)(AutomationView, { t, runtime, ...props.close === void 0 ? {} : { closeSettings: props.close }, ...workspacesApi === void 0 ? {} : { pickWorkspaceDirectory: () => workspacesApi.pickDirectory() } });
|
|
3044
|
+
return (0, import_react7.createElement)(AutomationView, { t, permissionT, runtime, ...props.close === void 0 ? {} : { closeSettings: props.close }, ...workspacesApi === void 0 ? {} : { pickWorkspaceDirectory: () => workspacesApi.pickDirectory() } });
|
|
3022
3045
|
}));
|
|
3023
3046
|
ctx.slots.inject("sidebar.schedule", () => ctx.slots.register({
|
|
3024
3047
|
name: "sidebar.schedule",
|