@michengai/dsh-automation 0.1.31 → 0.1.34
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/CHANGELOG.md +15 -0
- package/CHANGELOG.zh-CN.md +15 -0
- package/README.md +5 -0
- package/README.zh-CN.md +5 -0
- package/lib/client.js +325 -0
- package/lib/client.js.map +4 -4
- package/lib/index.js +412 -182
- package/lib/types/client/plugin-update-ui.d.ts +20 -0
- package/lib/types/executor.d.ts +0 -1
- package/lib/types/plugin-updater.d.ts +21 -0
- package/package.json +6 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,21 @@
|
|
|
4
4
|
|
|
5
5
|
The five most recent published versions are listed below. Git tags and GitHub Releases now mirror these entries; historical sections retain links to their original release commits.
|
|
6
6
|
|
|
7
|
+
## Unreleased
|
|
8
|
+
|
|
9
|
+
## 0.1.34 - 2026-09-07
|
|
10
|
+
|
|
11
|
+
- Aligned the release workflow's pnpm version with the package-declared version so tag publishing can start its checks.
|
|
12
|
+
|
|
13
|
+
## 0.1.33 - 2026-09-07
|
|
14
|
+
|
|
15
|
+
- Added independent in-product update checks with automatic updates when a verified DSH update service is available and a profile-specific manual fallback otherwise.
|
|
16
|
+
- Removed the update-button dependency on `react-dom/client` so the client can load on Hosts that do not register that module id.
|
|
17
|
+
|
|
18
|
+
## 0.1.32 — 2026-09-06
|
|
19
|
+
|
|
20
|
+
- Removed the fixed unattended tool allowlist and background-shell ban so tool calls and background process management follow DSH. Retained automatic rejection of approval requests and task timeout cancellation.
|
|
21
|
+
|
|
7
22
|
## 0.1.31 — 2026-09-05
|
|
8
23
|
|
|
9
24
|
- Aligned the scheduled-task editor with the Host modal surface, elevation, themed mask, and borderless close icon while preserving its existing dismissal behavior.
|
package/CHANGELOG.zh-CN.md
CHANGED
|
@@ -4,6 +4,21 @@
|
|
|
4
4
|
|
|
5
5
|
以下记录最近发布的五个版本。Git 标签与 GitHub Release 现已和这些条目同步;历史条目继续保留原始发布提交链接。
|
|
6
6
|
|
|
7
|
+
## 未发布
|
|
8
|
+
|
|
9
|
+
## 0.1.34 - 2026-09-07
|
|
10
|
+
|
|
11
|
+
- 将发布工作流的 pnpm 版本与包内声明对齐,使标签发布能够进入完整校验。
|
|
12
|
+
|
|
13
|
+
## 0.1.33 - 2026-09-07
|
|
14
|
+
|
|
15
|
+
- 新增独立的插件内检查更新能力:仅在已验证的 DSH 更新服务可用时自动更新,其余环境提供与 Profile 对应的手工更新命令。
|
|
16
|
+
- 更新按钮图标不再依赖 `react-dom/client`,避免宿主未注册该模块 id 时客户端无法加载。
|
|
17
|
+
|
|
18
|
+
## 0.1.32 — 2026-09-06
|
|
19
|
+
|
|
20
|
+
- 移除无人值守自动化的固定工具白名单和后台 shell 禁令,工具调用及后台进程管理统一遵循 DSH;保留需要审批即拒绝和任务超时取消约束。
|
|
21
|
+
|
|
7
22
|
## 0.1.31 — 2026-09-05
|
|
8
23
|
|
|
9
24
|
- 将定时任务编辑器的浮层背景、阴影、主题遮罩和无边框关闭图标与宿主统一,同时保留原有关闭行为。
|
package/README.md
CHANGED
|
@@ -104,6 +104,10 @@ dsh --profile web --dump-config
|
|
|
104
104
|
|
|
105
105
|
Restart DSH Web and hard-refresh the browser. Local installation reads and applies `cordis.patch.yml`; do not copy `lib` files manually.
|
|
106
106
|
|
|
107
|
+
## Updates
|
|
108
|
+
|
|
109
|
+
The settings title shows the installed version and a **Check for updates** button. When a newer release is available, **Update automatically** runs only when the DSH CLI or Desktop update service is available; otherwise, the dialog provides a profile-specific manual command to copy and run.
|
|
110
|
+
|
|
107
111
|
## Usage
|
|
108
112
|
|
|
109
113
|
Open **Settings → Scheduled Tasks**, then use the panel as follows:
|
|
@@ -124,6 +128,7 @@ Each dispatched run uses the saved prompt, workspace, model, and permission boun
|
|
|
124
128
|
| Item | Behavior |
|
|
125
129
|
| --- | --- |
|
|
126
130
|
| Permission | Options and the default come directly from the Host `permissionPresets` service, including custom presets. |
|
|
131
|
+
| Tool calls | Follow Host tool availability, permission, and approval checks without an additional fixed tool allowlist or a background-shell ban. The Host manages background processes. |
|
|
127
132
|
| Full access | The official `danger-full-access` option uses the same risk confirmation and orange warning as Chat. |
|
|
128
133
|
| 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`. |
|
|
129
134
|
| Retry | No automatic retry after a started run. |
|
package/README.zh-CN.md
CHANGED
|
@@ -104,6 +104,10 @@ dsh --profile web --dump-config
|
|
|
104
104
|
|
|
105
105
|
完成后重启 DSH Web 并硬刷新浏览器。`dsh plugin ... add .` 会自动读取并应用 `cordis.patch.yml`;不要手工复制 `lib` 文件。
|
|
106
106
|
|
|
107
|
+
## 在线更新
|
|
108
|
+
|
|
109
|
+
设置标题会显示当前版本和“检查更新”按钮。发现新版后,只有检测到 DSH CLI 或 Desktop 更新服务时才可使用“自动更新”;其他环境会在弹窗中提供可复制、与当前 Profile 对应的手工更新命令。
|
|
110
|
+
|
|
107
111
|
## 使用
|
|
108
112
|
|
|
109
113
|
打开「设置 → 定时任务」,再按下表操作:
|
|
@@ -124,6 +128,7 @@ dsh --profile web --dump-config
|
|
|
124
128
|
| 项目 | 行为 |
|
|
125
129
|
| --- | --- |
|
|
126
130
|
| 权限 | 列表和默认值直接来自 Host 官方 `permissionPresets` 服务;支持 Host 注册的自定义预设。 |
|
|
131
|
+
| 工具调用 | 遵循 Host 的工具可用性、权限和审批检查,不额外维护固定工具白名单或禁止后台 shell;后台进程由 Host 管理。 |
|
|
127
132
|
| 完全访问 | 选择官方 `danger-full-access` 时显示与 Chat 一致的风险确认和橙色提示。 |
|
|
128
133
|
| 审批 | 对话创建跟随当前会话策略。Full access(`never`)直接创建;Workspace Write / Read Only(`ask`)走官方授权卡。无人值守运行仍是 fail-closed 的 `never`。 |
|
|
129
134
|
| 重试 | 已经开始的运行不会自动重试。 |
|
package/lib/client.js
CHANGED
|
@@ -4223,9 +4223,325 @@ function openSettingsSection(labels, onSelected, onMissing) {
|
|
|
4223
4223
|
schedule();
|
|
4224
4224
|
}
|
|
4225
4225
|
|
|
4226
|
+
// src/client/plugin-update-ui.ts
|
|
4227
|
+
var UPDATE_HEADER = "x-michengai-plugin-update";
|
|
4228
|
+
var STYLE_ID2 = "michengai-plugin-update-ui";
|
|
4229
|
+
var CSS = `
|
|
4230
|
+
.mpi-version{margin-left:8px;color:var(--dsw-alias-label-tertiary,#9da1aa);font-family:inherit;font-size:12px;font-weight:500;line-height:18px;letter-spacing:0;white-space:nowrap;vertical-align:baseline}.mpi-check{display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:28px;padding:0 8px;border:1px solid var(--dsw-alias-border-l2,#4b4d52);border-radius:7px;background:transparent;color:var(--dsw-alias-label-secondary,#b8bbc2);font:inherit;font-size:12px;font-weight:500;line-height:18px;white-space:nowrap;cursor:pointer}.mpi-check:hover{background:var(--dsw-alias-interactive-bg-hover,#3a3b3f);color:var(--dsw-alias-label-primary,#fff)}.mpi-check:focus-visible,.mpi-action:focus-visible,.mpi-dialog-close:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4f8cff);outline-offset:2px}.mpi-icon{display:inline-flex;flex:0 0 auto;width:16px;height:16px;align-items:center;justify-content:center;pointer-events:none}.mpi-icon svg{display:block;width:16px;height:16px}
|
|
4231
|
+
.mpi-overlay{position:fixed;inset:0;z-index:2147483647;display:flex;align-items:center;justify-content:center;padding:24px;background:rgba(0,0,0,.62)}.mpi-dialog{position:relative;box-sizing:border-box;width:min(680px,100%);max-height:calc(100vh - 48px);overflow:auto;border:1px solid var(--dsw-alias-border-l2,#4b4d52);border-radius:14px;padding:22px;background:var(--dsw-alias-bg-layer-2,var(--dsw-specific-menu,#202124));color:var(--dsw-alias-label-primary,#fff);box-shadow:var(--dsw-shadow-lv3,0 16px 48px rgba(0,0,0,.24));font-family:inherit}.mpi-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.mpi-dialog h2{margin:0;font-size:18px;line-height:26px}.mpi-dialog-close{display:inline-flex;flex:0 0 28px;width:28px;height:28px;align-items:center;justify-content:center;padding:0;border:0;border-radius:8px;background:transparent;color:var(--dsw-alias-label-secondary,#b8bbc2);cursor:pointer}.mpi-dialog-close:hover{background:var(--dsw-alias-interactive-bg-hover,#3a3b3f);color:var(--dsw-alias-label-primary,#fff)}.mpi-intro{margin:8px 0 18px;color:var(--dsw-alias-label-secondary,#c2c4ca);font-size:13px;line-height:20px}.mpi-meta{display:grid;grid-template-columns:max-content minmax(0,1fr);gap:8px 18px;margin:0 0 16px;font-size:12px;line-height:18px}.mpi-meta dt{color:var(--dsw-alias-label-secondary,#c2c4ca)}.mpi-meta dd{margin:0;font-family:ui-monospace,SFMono-Regular,Consolas,monospace}.mpi-status{margin:0 0 18px;border-radius:7px;padding:12px 14px;background:var(--dsw-alias-bg-layer-3,var(--dsw-specific-menu-item-hover,#252527));font-size:13px;font-weight:600;line-height:20px}.mpi-status[data-kind=error]{color:var(--dsw-alias-state-error-primary,#ff6464)}.mpi-status[data-kind=success]{color:var(--dsw-alias-state-success-primary,#36d67a)}.mpi-manual{border-top:1px solid var(--dsw-alias-border-l2,#4b4d52);padding-top:16px}.mpi-manual h3{margin:0 0 6px;font-size:14px;line-height:20px}.mpi-manual p{margin:0 0 10px;color:var(--dsw-alias-label-secondary,#c2c4ca);font-size:12px;line-height:18px}.mpi-command{display:flex;align-items:center;gap:8px;border:1px solid var(--dsw-alias-border-l2,#4b4d52);border-radius:7px;padding:10px;background:var(--dsw-alias-bg-layer-3,var(--dsw-specific-menu-item-hover,#252527))}.mpi-command code{min-width:0;flex:1;overflow:auto;font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:12px;line-height:18px;white-space:nowrap}.mpi-actions{display:flex;align-items:center;justify-content:flex-end;gap:12px;margin-top:18px}.mpi-actions-group{display:flex;gap:8px}.mpi-action{display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:32px;border:1px solid var(--dsw-alias-border-l2,#4b4d52);border-radius:7px;padding:6px 10px;background:transparent;color:inherit;font:inherit;font-size:12px;cursor:pointer}.mpi-action:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,#414247)}.mpi-action:disabled{cursor:not-allowed;opacity:.55}.mpi-primary{border-color:var(--dsw-alias-state-business-primary,#4f8cff);background:var(--dsw-alias-state-business-primary,#4f8cff);color:#fff}.mpi-progress{height:4px;margin-top:10px;overflow:hidden;border-radius:99px;background:var(--dsw-alias-border-l2,#4b4d52)}.mpi-progress::after{display:block;width:32%;height:100%;background:var(--dsw-alias-state-business-primary,#4f8cff);content:'';animation:mpi-wave 1.15s ease-in-out infinite}@keyframes mpi-wave{from{transform:translateX(-110%)}to{transform:translateX(330%)}}@media(max-width:560px){.mpi-overlay{padding:10px}.mpi-dialog{max-height:calc(100vh - 20px);padding:16px}.mpi-actions{align-items:stretch}.mpi-actions-group{justify-content:flex-end;flex-wrap:wrap}.mpi-meta{grid-template-columns:1fr;gap:2px}.mpi-meta dd{margin-bottom:6px}}
|
|
4232
|
+
`;
|
|
4233
|
+
var ZH = {
|
|
4234
|
+
check: "\u68C0\u67E5\u66F4\u65B0",
|
|
4235
|
+
update: "\u66F4\u65B0",
|
|
4236
|
+
close: "\u5173\u95ED",
|
|
4237
|
+
recheck: "\u91CD\u65B0\u68C0\u67E5",
|
|
4238
|
+
auto: "\u81EA\u52A8\u66F4\u65B0",
|
|
4239
|
+
updating: "\u6B63\u5728\u66F4\u65B0\u2026",
|
|
4240
|
+
copy: "\u590D\u5236\u547D\u4EE4",
|
|
4241
|
+
copied: "\u5DF2\u590D\u5236",
|
|
4242
|
+
copyFailed: "\u590D\u5236\u5931\u8D25",
|
|
4243
|
+
checking: "\u6B63\u5728\u68C0\u67E5\u66F4\u65B0\u2026",
|
|
4244
|
+
latest: "\u5DF2\u662F\u6700\u65B0\u7248\u672C",
|
|
4245
|
+
found: "\u53D1\u73B0\u65B0\u7248\u672C",
|
|
4246
|
+
failed: "\u68C0\u67E5\u66F4\u65B0\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",
|
|
4247
|
+
current: "\u8FD0\u884C\u7248\u672C",
|
|
4248
|
+
latestLabel: "\u6700\u65B0\u7248\u672C",
|
|
4249
|
+
profile: "\u76EE\u6807 profile",
|
|
4250
|
+
unknown: "\u672A\u77E5",
|
|
4251
|
+
manual: "\u624B\u5DE5\u66F4\u65B0",
|
|
4252
|
+
manualHint: "\u81EA\u52A8\u66F4\u65B0\u5931\u8D25\u65F6\uFF0C\u53EF\u5728\u5F53\u524D DSH \u7EC8\u7AEF\u6267\u884C\u4EE5\u4E0B\u547D\u4EE4\uFF0C\u5B8C\u6210\u540E\u91CD\u542F DSH Web\u3002",
|
|
4253
|
+
intro: "\u4EC5\u68C0\u67E5\u5E76\u66F4\u65B0\u5F53\u524D\u63D2\u4EF6\uFF0C\u4E0D\u4F1A\u8054\u52A8\u5B89\u88C5\u5176\u4ED6\u63D2\u4EF6\u3002",
|
|
4254
|
+
restart: "\u66F4\u65B0\u5B8C\u6210\uFF0C\u8BF7\u91CD\u542F DSH Web\u3002",
|
|
4255
|
+
restarting: "\u66F4\u65B0\u5B8C\u6210\uFF0C\u6B63\u5728\u91CD\u542F DSH Desktop\u2026",
|
|
4256
|
+
unavailable: "\u5F53\u524D\u73AF\u5883\u4E0D\u652F\u6301\u81EA\u52A8\u66F4\u65B0\uFF0C\u8BF7\u4F7F\u7528\u624B\u5DE5\u66F4\u65B0\u547D\u4EE4\u3002"
|
|
4257
|
+
};
|
|
4258
|
+
var EN = {
|
|
4259
|
+
check: "Check for updates",
|
|
4260
|
+
update: "Update",
|
|
4261
|
+
close: "Close",
|
|
4262
|
+
recheck: "Check again",
|
|
4263
|
+
auto: "Update automatically",
|
|
4264
|
+
updating: "Updating\u2026",
|
|
4265
|
+
copy: "Copy command",
|
|
4266
|
+
copied: "Copied",
|
|
4267
|
+
copyFailed: "Copy failed",
|
|
4268
|
+
checking: "Checking for updates\u2026",
|
|
4269
|
+
latest: "You are up to date",
|
|
4270
|
+
found: "New version available",
|
|
4271
|
+
failed: "Could not check for updates. Try again later.",
|
|
4272
|
+
current: "Running version",
|
|
4273
|
+
latestLabel: "Latest version",
|
|
4274
|
+
profile: "Target profile",
|
|
4275
|
+
unknown: "Unknown",
|
|
4276
|
+
manual: "Manual update",
|
|
4277
|
+
manualHint: "If automatic update fails, run this command in the current DSH terminal, then restart DSH Web.",
|
|
4278
|
+
intro: "Only this plugin is checked and updated. Other plugins are not changed.",
|
|
4279
|
+
restart: "Update complete. Restart DSH Web.",
|
|
4280
|
+
restarting: "Update complete. Restarting DSH Desktop\u2026",
|
|
4281
|
+
unavailable: "Automatic update is unavailable. Use the manual command."
|
|
4282
|
+
};
|
|
4283
|
+
function strings() {
|
|
4284
|
+
const lang = document.documentElement.lang.toLowerCase();
|
|
4285
|
+
const settings = document.querySelector('[role="dialog"]')?.textContent ?? "";
|
|
4286
|
+
return lang.startsWith("en") || settings.includes("Settings") && !settings.includes("\u8BBE\u7F6E") ? EN : ZH;
|
|
4287
|
+
}
|
|
4288
|
+
function ensureStyle() {
|
|
4289
|
+
if (document.getElementById(STYLE_ID2) !== null) return;
|
|
4290
|
+
const style = document.createElement("style");
|
|
4291
|
+
style.id = STYLE_ID2;
|
|
4292
|
+
style.textContent = CSS;
|
|
4293
|
+
(document.head ?? document.documentElement).append(style);
|
|
4294
|
+
}
|
|
4295
|
+
function validPayload(value) {
|
|
4296
|
+
if (value === null || typeof value !== "object") return false;
|
|
4297
|
+
const item = value;
|
|
4298
|
+
return typeof item.packageName === "string" && typeof item.currentVersion === "string" && typeof item.updateAvailable === "boolean" && typeof item.profileName === "string" && typeof item.canAutoUpdate === "boolean" && typeof item.latestCheckFailed === "boolean" && (item.latestVersion === void 0 || typeof item.latestVersion === "string");
|
|
4299
|
+
}
|
|
4300
|
+
async function requestStatus(endpoint, method, signal) {
|
|
4301
|
+
const signalOption = signal === void 0 ? {} : { signal };
|
|
4302
|
+
const response = await fetch(endpoint, method === "GET" ? { cache: "no-store", ...signalOption } : {
|
|
4303
|
+
method: "POST",
|
|
4304
|
+
headers: { "content-type": "application/json", [UPDATE_HEADER]: "1" },
|
|
4305
|
+
body: "{}",
|
|
4306
|
+
...signalOption
|
|
4307
|
+
});
|
|
4308
|
+
const value = await response.json();
|
|
4309
|
+
if (!response.ok || !validPayload(value)) throw new Error(typeof value.error === "string" ? value.error : strings().failed);
|
|
4310
|
+
return value;
|
|
4311
|
+
}
|
|
4312
|
+
function manualPluginUpdateCommand(profileName, packageName, version) {
|
|
4313
|
+
const profile = profileName.trim() === "" ? "" : ` --profile ${profileName.trim()}`;
|
|
4314
|
+
return `dsh plugin${profile} add ${packageName}@${version} --registry=https://registry.npmjs.org/`;
|
|
4315
|
+
}
|
|
4316
|
+
function handlePluginUpdateEscape(event, close) {
|
|
4317
|
+
if (event.key !== "Escape") return false;
|
|
4318
|
+
event.preventDefault();
|
|
4319
|
+
event.stopPropagation();
|
|
4320
|
+
event.stopImmediatePropagation();
|
|
4321
|
+
close();
|
|
4322
|
+
return true;
|
|
4323
|
+
}
|
|
4324
|
+
function observePluginUpdate(options) {
|
|
4325
|
+
if (typeof document === "undefined" || document.body === null) return () => {
|
|
4326
|
+
};
|
|
4327
|
+
ensureStyle();
|
|
4328
|
+
const controller = new AbortController();
|
|
4329
|
+
let payload;
|
|
4330
|
+
let overlay;
|
|
4331
|
+
let frame;
|
|
4332
|
+
const setButtonContent = (button, label, iconName) => {
|
|
4333
|
+
const icon = options.createIcon(iconName);
|
|
4334
|
+
icon.classList.add("mpi-icon");
|
|
4335
|
+
icon.setAttribute("aria-hidden", "true");
|
|
4336
|
+
const text = document.createElement("span");
|
|
4337
|
+
text.dataset.mpiLabel = "";
|
|
4338
|
+
text.textContent = label;
|
|
4339
|
+
button.replaceChildren(icon, text);
|
|
4340
|
+
};
|
|
4341
|
+
const setButtonLabel = (button, label) => {
|
|
4342
|
+
const text = button.querySelector("[data-mpi-label]");
|
|
4343
|
+
if (text === null) button.textContent = label;
|
|
4344
|
+
else text.textContent = label;
|
|
4345
|
+
};
|
|
4346
|
+
const applyControls = () => {
|
|
4347
|
+
const row = document.querySelector(options.titleRowSelector);
|
|
4348
|
+
if (row === null) return;
|
|
4349
|
+
const heading = row.querySelector("h1,h2");
|
|
4350
|
+
if (heading !== null && payload !== void 0) {
|
|
4351
|
+
let version = heading.querySelector(`.mpi-version[data-package="${options.packageName}"]`);
|
|
4352
|
+
if (version === null) {
|
|
4353
|
+
version = document.createElement("span");
|
|
4354
|
+
version.className = "mpi-version";
|
|
4355
|
+
version.dataset.package = options.packageName;
|
|
4356
|
+
heading.append(version);
|
|
4357
|
+
}
|
|
4358
|
+
const versionLabel = `v${payload.currentVersion}`;
|
|
4359
|
+
if (version.textContent !== versionLabel) version.textContent = versionLabel;
|
|
4360
|
+
}
|
|
4361
|
+
const links = row.querySelector(options.linksSelector);
|
|
4362
|
+
if (links === null || links.querySelector(`[data-mpi-check="${options.packageName}"]`) !== null) return;
|
|
4363
|
+
const button = document.createElement("button");
|
|
4364
|
+
button.type = "button";
|
|
4365
|
+
button.className = "mpi-check";
|
|
4366
|
+
button.dataset.mpiCheck = options.packageName;
|
|
4367
|
+
setButtonContent(button, strings().check, "refresh");
|
|
4368
|
+
button.addEventListener("click", openDialog);
|
|
4369
|
+
links.append(button);
|
|
4370
|
+
};
|
|
4371
|
+
const load = async () => {
|
|
4372
|
+
payload = await requestStatus(options.endpoint, "GET", controller.signal);
|
|
4373
|
+
applyControls();
|
|
4374
|
+
return payload;
|
|
4375
|
+
};
|
|
4376
|
+
const closeDialog = () => {
|
|
4377
|
+
overlay?.remove();
|
|
4378
|
+
overlay = void 0;
|
|
4379
|
+
};
|
|
4380
|
+
function openDialog() {
|
|
4381
|
+
closeDialog();
|
|
4382
|
+
const text = strings();
|
|
4383
|
+
overlay = document.createElement("div");
|
|
4384
|
+
overlay.className = "mpi-overlay";
|
|
4385
|
+
const dialog = document.createElement("section");
|
|
4386
|
+
dialog.className = "mpi-dialog";
|
|
4387
|
+
dialog.setAttribute("role", "dialog");
|
|
4388
|
+
dialog.setAttribute("aria-modal", "true");
|
|
4389
|
+
dialog.innerHTML = `<header class="mpi-head"><h2></h2><button type="button" class="mpi-dialog-close" data-action="close"></button></header><p class="mpi-intro"></p><dl class="mpi-meta"><dt></dt><dd data-role="current"></dd><dt></dt><dd data-role="latest"></dd><dt></dt><dd data-role="profile"></dd></dl><div class="mpi-status" role="status"></div><div class="mpi-progress" hidden></div><section class="mpi-manual"><h3></h3><p></p><div class="mpi-command"><code></code><button type="button" class="mpi-action" data-action="copy"></button></div></section><footer class="mpi-actions"><div class="mpi-actions-group"><button type="button" class="mpi-action" data-action="check"></button><button type="button" class="mpi-action mpi-primary" data-action="update"></button></div></footer>`;
|
|
4390
|
+
const name2 = document.documentElement.lang.toLowerCase().startsWith("en") ? options.enName : options.zhName;
|
|
4391
|
+
dialog.querySelector("h2").textContent = `${name2} ${text.update}`;
|
|
4392
|
+
dialog.querySelector(".mpi-intro").textContent = text.intro;
|
|
4393
|
+
const terms = dialog.querySelectorAll("dt");
|
|
4394
|
+
terms[0].textContent = text.current;
|
|
4395
|
+
terms[1].textContent = text.latestLabel;
|
|
4396
|
+
terms[2].textContent = text.profile;
|
|
4397
|
+
dialog.querySelector(".mpi-manual h3").textContent = text.manual;
|
|
4398
|
+
dialog.querySelector(".mpi-manual p").textContent = text.manualHint;
|
|
4399
|
+
const status = dialog.querySelector(".mpi-status");
|
|
4400
|
+
const progress = dialog.querySelector(".mpi-progress");
|
|
4401
|
+
const command = dialog.querySelector(".mpi-command code");
|
|
4402
|
+
const close = dialog.querySelector("[data-action=close]");
|
|
4403
|
+
const check = dialog.querySelector("[data-action=check]");
|
|
4404
|
+
const update = dialog.querySelector("[data-action=update]");
|
|
4405
|
+
const copy = dialog.querySelector("[data-action=copy]");
|
|
4406
|
+
setButtonContent(close, text.close, "close");
|
|
4407
|
+
close.querySelector("[data-mpi-label]")?.remove();
|
|
4408
|
+
close.setAttribute("aria-label", text.close);
|
|
4409
|
+
close.title = text.close;
|
|
4410
|
+
setButtonContent(check, text.recheck, "refresh");
|
|
4411
|
+
setButtonContent(update, text.auto, "download");
|
|
4412
|
+
setButtonContent(copy, text.copy, "copy");
|
|
4413
|
+
let busy = false;
|
|
4414
|
+
const setMessage = (message, kind = "") => {
|
|
4415
|
+
status.textContent = message;
|
|
4416
|
+
status.dataset.kind = kind;
|
|
4417
|
+
};
|
|
4418
|
+
const setBusy = (value) => {
|
|
4419
|
+
busy = value;
|
|
4420
|
+
check.disabled = value;
|
|
4421
|
+
copy.disabled = value;
|
|
4422
|
+
update.disabled = value || payload?.canAutoUpdate !== true || payload.updateAvailable !== true;
|
|
4423
|
+
progress.hidden = !value;
|
|
4424
|
+
};
|
|
4425
|
+
const render = () => {
|
|
4426
|
+
dialog.querySelector("[data-role=current]").textContent = payload === void 0 ? text.unknown : `v${payload.currentVersion}`;
|
|
4427
|
+
dialog.querySelector("[data-role=latest]").textContent = payload?.latestVersion === void 0 ? text.unknown : `v${payload.latestVersion}`;
|
|
4428
|
+
dialog.querySelector("[data-role=profile]").textContent = payload?.profileName ?? text.unknown;
|
|
4429
|
+
command.textContent = manualPluginUpdateCommand(payload?.profileName ?? "", options.packageName, payload?.latestVersion ?? "latest");
|
|
4430
|
+
update.disabled = busy || payload?.canAutoUpdate !== true || payload.updateAvailable !== true;
|
|
4431
|
+
if (payload === void 0) setMessage(text.checking);
|
|
4432
|
+
else if (payload.latestCheckFailed) setMessage(text.failed, "error");
|
|
4433
|
+
else if (payload.updateAvailable) setMessage(`${text.found}: v${payload.latestVersion ?? text.unknown}`);
|
|
4434
|
+
else setMessage(text.latest, "success");
|
|
4435
|
+
if (payload !== void 0 && !payload.canAutoUpdate && payload.updateAvailable) setMessage(text.unavailable);
|
|
4436
|
+
};
|
|
4437
|
+
const checkNow = async () => {
|
|
4438
|
+
if (busy) return;
|
|
4439
|
+
setBusy(true);
|
|
4440
|
+
setMessage(text.checking);
|
|
4441
|
+
try {
|
|
4442
|
+
await load();
|
|
4443
|
+
setBusy(false);
|
|
4444
|
+
render();
|
|
4445
|
+
} catch (error) {
|
|
4446
|
+
setBusy(false);
|
|
4447
|
+
setMessage(error instanceof Error ? error.message : text.failed, "error");
|
|
4448
|
+
}
|
|
4449
|
+
};
|
|
4450
|
+
const updateNow = async () => {
|
|
4451
|
+
if (busy) return;
|
|
4452
|
+
setBusy(true);
|
|
4453
|
+
setButtonLabel(update, text.updating);
|
|
4454
|
+
setMessage(text.updating);
|
|
4455
|
+
try {
|
|
4456
|
+
payload = await requestStatus(options.endpoint, "POST", controller.signal);
|
|
4457
|
+
applyControls();
|
|
4458
|
+
render();
|
|
4459
|
+
setMessage(payload.autoReload === true ? text.restarting : text.restart, "success");
|
|
4460
|
+
} catch (error) {
|
|
4461
|
+
setMessage(error instanceof Error ? error.message : text.failed, "error");
|
|
4462
|
+
} finally {
|
|
4463
|
+
setButtonLabel(update, text.auto);
|
|
4464
|
+
setBusy(false);
|
|
4465
|
+
}
|
|
4466
|
+
};
|
|
4467
|
+
close.addEventListener("click", closeDialog);
|
|
4468
|
+
check.addEventListener("click", () => {
|
|
4469
|
+
void checkNow();
|
|
4470
|
+
});
|
|
4471
|
+
update.addEventListener("click", () => {
|
|
4472
|
+
void updateNow();
|
|
4473
|
+
});
|
|
4474
|
+
copy.addEventListener("click", () => {
|
|
4475
|
+
void navigator.clipboard?.writeText(command.textContent ?? "").then(() => {
|
|
4476
|
+
setButtonLabel(copy, text.copied);
|
|
4477
|
+
setTimeout(() => {
|
|
4478
|
+
setButtonLabel(copy, text.copy);
|
|
4479
|
+
}, 1400);
|
|
4480
|
+
}).catch(() => {
|
|
4481
|
+
setButtonLabel(copy, text.copyFailed);
|
|
4482
|
+
});
|
|
4483
|
+
});
|
|
4484
|
+
overlay.addEventListener("click", (event) => {
|
|
4485
|
+
if (event.target === overlay) closeDialog();
|
|
4486
|
+
});
|
|
4487
|
+
overlay.addEventListener("keydown", (event) => {
|
|
4488
|
+
handlePluginUpdateEscape(event, closeDialog);
|
|
4489
|
+
}, true);
|
|
4490
|
+
overlay.append(dialog);
|
|
4491
|
+
document.body.append(overlay);
|
|
4492
|
+
render();
|
|
4493
|
+
close.focus();
|
|
4494
|
+
void checkNow();
|
|
4495
|
+
}
|
|
4496
|
+
const observer = new MutationObserver(() => {
|
|
4497
|
+
if (frame !== void 0) return;
|
|
4498
|
+
frame = window.requestAnimationFrame(() => {
|
|
4499
|
+
frame = void 0;
|
|
4500
|
+
applyControls();
|
|
4501
|
+
});
|
|
4502
|
+
});
|
|
4503
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
4504
|
+
applyControls();
|
|
4505
|
+
void load().catch(() => {
|
|
4506
|
+
});
|
|
4507
|
+
return () => {
|
|
4508
|
+
controller.abort();
|
|
4509
|
+
observer.disconnect();
|
|
4510
|
+
closeDialog();
|
|
4511
|
+
if (frame !== void 0) window.cancelAnimationFrame(frame);
|
|
4512
|
+
document.querySelectorAll(`[data-mpi-check="${options.packageName}"],.mpi-version[data-package="${options.packageName}"]`).forEach((node) => node.remove());
|
|
4513
|
+
};
|
|
4514
|
+
}
|
|
4515
|
+
|
|
4226
4516
|
// src/client/index.ts
|
|
4227
4517
|
var name = "dsh-automation-client";
|
|
4228
4518
|
var inject = ["slots", "locale", "connection", "sessions"];
|
|
4519
|
+
var UPDATE_ICON_PATHS = {
|
|
4520
|
+
refresh: ["M13.5 5.5V2.5m0 0h-3m3 0-2.1 2.1A5.5 5.5 0 1 0 13.2 12"],
|
|
4521
|
+
download: ["M8 2v8m0 0 3-3m-3 3-3-3M3 13v2h10v-2"],
|
|
4522
|
+
copy: ["M5 5h8v8H5z", "M3 3h8"],
|
|
4523
|
+
close: ["m4 4 8 8M12 4 4 12"]
|
|
4524
|
+
};
|
|
4525
|
+
function createPluginUpdateIcon(name2) {
|
|
4526
|
+
const element = document.createElement("span");
|
|
4527
|
+
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
4528
|
+
svg.setAttribute("viewBox", "0 0 16 16");
|
|
4529
|
+
svg.setAttribute("width", "16");
|
|
4530
|
+
svg.setAttribute("height", "16");
|
|
4531
|
+
svg.setAttribute("fill", "none");
|
|
4532
|
+
svg.setAttribute("stroke", "currentColor");
|
|
4533
|
+
svg.setAttribute("stroke-width", "1.5");
|
|
4534
|
+
svg.setAttribute("stroke-linecap", "round");
|
|
4535
|
+
svg.setAttribute("stroke-linejoin", "round");
|
|
4536
|
+
svg.setAttribute("aria-hidden", "true");
|
|
4537
|
+
for (const d of UPDATE_ICON_PATHS[name2]) {
|
|
4538
|
+
const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
4539
|
+
path.setAttribute("d", d);
|
|
4540
|
+
svg.append(path);
|
|
4541
|
+
}
|
|
4542
|
+
element.append(svg);
|
|
4543
|
+
return element;
|
|
4544
|
+
}
|
|
4229
4545
|
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>';
|
|
4230
4546
|
function isSessionSelector(value) {
|
|
4231
4547
|
return typeof value === "function";
|
|
@@ -4265,6 +4581,15 @@ function installSettingsNavIcon(labels) {
|
|
|
4265
4581
|
function apply(ctx) {
|
|
4266
4582
|
ctx.effect(() => installStyles(), "dsh-automation: styles");
|
|
4267
4583
|
ctx.effect(() => ctx.locale.register(NS, { zh, en }), "dsh-automation: locale");
|
|
4584
|
+
ctx.effect(() => observePluginUpdate({
|
|
4585
|
+
endpoint: "/api/michengai/dsh-automation/update",
|
|
4586
|
+
packageName: "@michengai/dsh-automation",
|
|
4587
|
+
titleRowSelector: ".dsh-st-heading-row",
|
|
4588
|
+
linksSelector: ".dsh-st-heading-links",
|
|
4589
|
+
zhName: "\u5B9A\u65F6\u4EFB\u52A1",
|
|
4590
|
+
enName: "Scheduled tasks",
|
|
4591
|
+
createIcon: createPluginUpdateIcon
|
|
4592
|
+
}), "dsh-automation: plugin update ui");
|
|
4268
4593
|
const t = ctx.locale.bind(NS);
|
|
4269
4594
|
const permissionT = ctx.locale.bind("permission.access");
|
|
4270
4595
|
const modelT = ctx.locale.bind("model");
|