@michengai/dsh-automation 0.1.4 → 0.1.6

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 CHANGED
@@ -12,6 +12,7 @@
12
12
 
13
13
  [![License: Apache-2.0](https://img.shields.io/badge/License-Apache--2.0-blue.svg)](LICENSE)
14
14
  [![npm package](https://img.shields.io/npm/v/%40michengai%2Fdsh-automation.svg?label=npm%20package)](https://www.npmjs.com/package/@michengai/dsh-automation)
15
+ [![npm downloads](https://img.shields.io/npm/dt/%40michengai%2Fdsh-automation.svg?label=npm%20downloads)](https://www.npmjs.com/package/@michengai/dsh-automation)
15
16
  [![DSH Web Plugin](https://img.shields.io/badge/DSH%20Web-Plugin-0f766e.svg)](https://github.com/MichengAI/dsh-automation)
16
17
  [![Node.js 22 or later](https://img.shields.io/badge/Node.js-22%20or%20later-339933.svg?logo=node.js&logoColor=white)](https://nodejs.org/)
17
18
  </div>
@@ -53,6 +54,17 @@ Run history stays in Settings and can be filtered by day, week, month, task, or
53
54
 
54
55
  ![Run history](assets/screenshots/settings-runs.png)
55
56
 
57
+ ## DSH product ecosystem
58
+
59
+ This product can be installed independently or used through the desktop app or Web suite. They share the same DSH core but serve different ways of working; on stock DSH, this product does not depend on Codex UI:
60
+
61
+ | Product | Relationship to this product |
62
+ | --- | --- |
63
+ | [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) | The host runtime that provides models, sessions, tools, and the plugin system |
64
+ | [DSH Codex Desktop](https://github.com/MichengAI/dsh-codex-desktop) | A ready-to-install desktop product with this product and the other five feature products built in |
65
+ | [DSH Codex Suite](https://github.com/MichengAI/dsh-codex-ui/tree/main/packages/dsh-codex-suite) | A one-click suite for existing DSH Web environments that installs this product and the other five feature products |
66
+ | Six feature products | [Codex UI](https://github.com/MichengAI/dsh-codex-ui) · [IM Connect](https://github.com/MichengAI/dsh-im-connect) · [Automation](https://github.com/MichengAI/dsh-automation) · [Skills Manager](https://github.com/MichengAI/dsh-skills-manager) · [Archive Manager](https://github.com/MichengAI/dsh-archive-manager) · [Agency Agents](https://github.com/MichengAI/dsh-agency-agents) |
67
+
56
68
  ## Prerequisites
57
69
 
58
70
  - A working DeepSeek Harness Web installation with `dsh` available in PowerShell.
@@ -72,7 +84,7 @@ dsh plugin --profile web add @michengai/dsh-automation@latest --registry=https:/
72
84
  dsh --profile web --dump-config
73
85
  ```
74
86
 
75
- Restart DSH Web and hard-refresh the browser. Pin a version with `@0.1.4` instead of `@latest` when needed.
87
+ Restart DSH Web and hard-refresh the browser. Pin a version with `@0.1.5` instead of `@latest` when needed.
76
88
 
77
89
  ### Install from source
78
90
 
@@ -156,4 +168,4 @@ pnpm build
156
168
 
157
169
  Start from the [documentation entry](docs/00-交接入口/00-阅读导航.md) for project status, architecture, and the current iteration. Product notes live in NOTICE.
158
170
 
159
- This project uses [Apache License 2.0](LICENSE).
171
+ This project uses [Apache License 2.0](LICENSE).
package/README.zh-CN.md CHANGED
@@ -12,6 +12,7 @@
12
12
 
13
13
  [![许可证:Apache-2.0](https://img.shields.io/badge/许可证-Apache--2.0-blue.svg)](LICENSE)
14
14
  [![npm package](https://img.shields.io/npm/v/%40michengai%2Fdsh-automation.svg?label=npm%20package)](https://www.npmjs.com/package/@michengai/dsh-automation)
15
+ [![npm 下载量](https://img.shields.io/npm/dt/%40michengai%2Fdsh-automation.svg?label=npm%20%E4%B8%8B%E8%BD%BD%E9%87%8F)](https://www.npmjs.com/package/@michengai/dsh-automation)
15
16
  [![DSH Web Plugin](https://img.shields.io/badge/DSH%20Web-Plugin-0f766e.svg)](https://github.com/MichengAI/dsh-automation)
16
17
  [![Node.js 22 or later](https://img.shields.io/badge/Node.js-22%20or%20later-339933.svg?logo=node.js&logoColor=white)](https://nodejs.org/)
17
18
  </div>
@@ -53,6 +54,17 @@
53
54
 
54
55
  ![执行记录](assets/screenshots/settings-runs.png)
55
56
 
57
+ ## DSH 产品生态
58
+
59
+ 本产品既可以独立安装,也可以随桌面端或 Web 套件一起使用。它们共享同一个 DSH 核心,但面向不同的使用方式;在原生 DSH 下,本产品不依赖 Codex UI:
60
+
61
+ | 产品 | 与本产品的关系 |
62
+ | --- | --- |
63
+ | [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) | 本产品的运行宿主,提供模型、会话、工具和插件系统 |
64
+ | [DSH Codex Desktop](https://github.com/MichengAI/dsh-codex-desktop) | 下载安装即用的桌面产品,已内置本产品和其他 5 个功能产品 |
65
+ | [DSH Codex Suite](https://github.com/MichengAI/dsh-codex-ui/tree/main/packages/dsh-codex-suite) | 面向已有 DSH Web 环境的一键套件,会安装本产品和其他 5 个功能产品 |
66
+ | 6 个功能产品 | [Codex UI](https://github.com/MichengAI/dsh-codex-ui) · [IM Connect](https://github.com/MichengAI/dsh-im-connect) · [Automation](https://github.com/MichengAI/dsh-automation) · [Skills Manager](https://github.com/MichengAI/dsh-skills-manager) · [Archive Manager](https://github.com/MichengAI/dsh-archive-manager) · [Agency Agents](https://github.com/MichengAI/dsh-agency-agents) |
67
+
56
68
  ## 前置条件
57
69
 
58
70
  - 已可正常运行 DeepSeek Harness Web,且可在 PowerShell 中使用 `dsh`。
@@ -72,7 +84,7 @@ dsh plugin --profile web add @michengai/dsh-automation@latest --registry=https:/
72
84
  dsh --profile web --dump-config
73
85
  ```
74
86
 
75
- 安装后重启 DSH Web,并在浏览器硬刷新。需要钉死某一版时,把 `@latest` 换成 `@0.1.4`。
87
+ 安装后重启 DSH Web,并在浏览器硬刷新。需要钉死某一版时,把 `@latest` 换成 `@0.1.5`。
76
88
 
77
89
  ### 从源码安装
78
90
 
@@ -156,4 +168,4 @@ pnpm build
156
168
 
157
169
  项目状态、使用边界、技术架构和迭代记录从[文档交接入口](docs/00-交接入口/00-阅读导航.md)开始。补充说明见 NOTICE。
158
170
 
159
- 本项目采用 [Apache License 2.0](LICENSE)。
171
+ 本项目采用 [Apache License 2.0](LICENSE)。
package/lib/client.js CHANGED
@@ -398,6 +398,9 @@ function RunningStateDot() {
398
398
  var import_react2 = require("react");
399
399
 
400
400
  // src/client/create-modal-logic.ts
401
+ function shouldConfirmFullAccess(current, next) {
402
+ return current !== "full-access" && next === "full-access";
403
+ }
401
404
  async function adoptPickedWorkspace(input) {
402
405
  const path = await input.pick();
403
406
  if (path == null || path.trim() === "") return null;
@@ -606,6 +609,7 @@ function useMenuState() {
606
609
  }
607
610
 
608
611
  // src/client/create-modal.tsx
612
+ var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
609
613
  var import_jsx_runtime3 = require("react/jsx-runtime");
610
614
  var WEEKDAYS = [1, 2, 3, 4, 5, 6, 7];
611
615
  var KINDS = ["once", "interval", "hourly", "daily", "weekly", "monthly", "custom"];
@@ -628,10 +632,29 @@ function CreateModal({
628
632
  }) {
629
633
  const [form, setForm] = (0, import_react2.useState)(() => ({ ...defaultFormState(/* @__PURE__ */ new Date(), workspaces, defaultModel), ...draft }));
630
634
  const [validationError, setValidationError] = (0, import_react2.useState)();
635
+ const [confirmingFullAccess, setConfirmingFullAccess] = (0, import_react2.useState)(false);
636
+ const [fullAccessAcknowledged, setFullAccessAcknowledged] = (0, import_react2.useState)(false);
631
637
  const update = (patch) => {
632
638
  setForm((current) => ({ ...current, ...patch }));
633
639
  setValidationError(void 0);
634
640
  };
641
+ const choosePermission = (permission) => {
642
+ if (shouldConfirmFullAccess(form.permission, permission)) {
643
+ setFullAccessAcknowledged(false);
644
+ setConfirmingFullAccess(true);
645
+ return;
646
+ }
647
+ update({ permission });
648
+ };
649
+ const cancelFullAccessConfirmation = () => {
650
+ setFullAccessAcknowledged(false);
651
+ setConfirmingFullAccess(false);
652
+ };
653
+ const confirmFullAccess = () => {
654
+ if (!fullAccessAcknowledged) return;
655
+ update({ permission: "full-access" });
656
+ cancelFullAccessConfirmation();
657
+ };
635
658
  (0, import_react2.useEffect)(() => {
636
659
  const onKey = (event) => {
637
660
  if (event.key !== "Escape") return;
@@ -825,7 +848,7 @@ function CreateModal({
825
848
  { value: "workspace-write", label: t("form.workspaceWrite"), icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ShieldIcon, { width: 14, height: 14 }) },
826
849
  { value: "full-access", label: t("form.fullAccess"), icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ShieldIcon, { width: 14, height: 14 }) }
827
850
  ],
828
- onChange: (value) => update({ permission: value })
851
+ onChange: choosePermission
829
852
  }
830
853
  )
831
854
  ] }),
@@ -849,7 +872,22 @@ function CreateModal({
849
872
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "submit", className: "dsh-st-btn dsh-st-btn--primary", disabled: busy, children: t("modal.save") })
850
873
  ] })
851
874
  ] }),
852
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-st-flyout-root", ref: setMenuHost })
875
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-st-flyout-root", ref: setMenuHost }),
876
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
877
+ import_dsh_client_ui_primitives.RiskConfirmation,
878
+ {
879
+ open: confirmingFullAccess,
880
+ title: t("access.confirm.title"),
881
+ description: t("access.confirm.description"),
882
+ acknowledgeLabel: t("access.confirm.acknowledge"),
883
+ cancelLabel: t("access.confirm.cancel"),
884
+ confirmLabel: t("access.confirm.enable"),
885
+ acknowledged: fullAccessAcknowledged,
886
+ onAcknowledgedChange: setFullAccessAcknowledged,
887
+ onCancel: cancelFullAccessConfirmation,
888
+ onConfirm: confirmFullAccess
889
+ }
890
+ )
853
891
  ] }) });
854
892
  }
855
893
  function ModelPicker({
@@ -1562,6 +1600,11 @@ var en = {
1562
1600
  "form.workspaceWrite": "Workspace Write",
1563
1601
  "form.fullAccess": "Full access",
1564
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",
1565
1608
  "form.cancel": "Cancel",
1566
1609
  "form.submit": "Create automation",
1567
1610
  "form.submitting": "Creating\u2026",
@@ -1762,6 +1805,11 @@ var zh = {
1762
1805
  "form.workspaceWrite": "Workspace Write",
1763
1806
  "form.fullAccess": "Full access",
1764
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",
1765
1813
  "form.cancel": "\u53D6\u6D88",
1766
1814
  "form.submit": "\u521B\u5EFA\u81EA\u52A8\u5316",
1767
1815
  "form.submitting": "\u521B\u5EFA\u4E2D\u2026",
@@ -2021,6 +2069,12 @@ function groupScheduledSessions(automations, runs) {
2021
2069
  };
2022
2070
  }).filter((group) => group.sessions.length > 0);
2023
2071
  }
2072
+ function keepScheduledSessionLink(sessionId, archived, presentIds) {
2073
+ if (sessionId === void 0 || sessionId === "") return false;
2074
+ if (archived.has(sessionId)) return false;
2075
+ if (presentIds === void 0) return true;
2076
+ return presentIds.has(sessionId);
2077
+ }
2024
2078
  function collectScheduledSessionIds(runs) {
2025
2079
  const ids = /* @__PURE__ */ new Set();
2026
2080
  for (const run of runs ?? []) {
@@ -2360,12 +2414,18 @@ function NativeScheduleSessionList(props) {
2360
2414
  };
2361
2415
  }, [runtime]);
2362
2416
  const archived = (0, import_react5.useMemo)(() => new Set(archivedIds), [archivedIds]);
2417
+ const listedIds = useSessions ? useSessions((snap) => Array.isArray(snap?.ids) ? snap.ids : void 0) : void 0;
2418
+ const presentIds = (0, import_react5.useMemo)(() => {
2419
+ if (listedIds !== void 0) return new Set(listedIds);
2420
+ const keys = Object.keys(sessionById);
2421
+ return keys.length > 0 ? new Set(keys) : void 0;
2422
+ }, [listedIds, sessionById]);
2363
2423
  const groups = (0, import_react5.useMemo)(() => {
2364
2424
  const snapshot = state.snapshot;
2365
2425
  if (snapshot === void 0) return [];
2366
2426
  return groupScheduledSessions(snapshot.automations, snapshot.runs).map((group) => ({
2367
2427
  ...group,
2368
- sessions: group.sessions.filter((session) => !archived.has(session.id)).map((session) => {
2428
+ sessions: group.sessions.filter((session) => keepScheduledSessionLink(session.id, archived, presentIds)).map((session) => {
2369
2429
  const run = snapshot.runs.find((item) => item.sessionId === session.id);
2370
2430
  return {
2371
2431
  ...session,
@@ -2375,7 +2435,7 @@ function NativeScheduleSessionList(props) {
2375
2435
  };
2376
2436
  })
2377
2437
  })).filter((group) => group.sessions.length > 0);
2378
- }, [archived, sessionById, state.snapshot]);
2438
+ }, [archived, presentIds, sessionById, state.snapshot]);
2379
2439
  const visibleGroups = (0, import_react5.useMemo)(() => applyWorkspaceBrowserQuery(groups.map((group) => ({ ...group, name: group.name })), query, sort, groupMode), [groups, query, sort, groupMode]);
2380
2440
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-st-n", children: [
2381
2441
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(WorkspaceToolbar, { t, query, sort, groupMode, onQueryChange: setQuery, onSortChange: setSort, onGroupModeChange: setGroupMode }),