@michengai/dsh-codex-pet 0.1.12 → 0.1.15
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 +13 -0
- package/CHANGELOG.zh-CN.md +13 -0
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/lib/client.js +14 -6
- package/lib/index.js +153 -21
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## [0.1.15] - 2026-10-07
|
|
6
|
+
|
|
7
|
+
- Official Desktop can update this plugin in place. It no longer targets the web profile by mistake.
|
|
8
|
+
- A new version is marked with a warning color. Version numbers keep their normal color.
|
|
9
|
+
- After updating, fully quit and reopen DSH Desktop.
|
|
10
|
+
|
|
11
|
+
## [0.1.13] - 2026-10-06
|
|
12
|
+
|
|
13
|
+
- The installed-plugin list shows “Codex Pet” and a localized description instead of the package name. Titles and descriptions come from `meta.title` and `meta.description` in `locale/zh.json` and `locale/en.json`.
|
|
14
|
+
- Installing from GitHub now includes the compiled runtime, so no manual build is required.
|
|
15
|
+
|
|
3
16
|
## [0.1.12] - 2026-09-30
|
|
4
17
|
|
|
5
18
|
- Add compatibility with DSH `0.2.0-rc.2` without dropping the existing supported hosts. Pin development types and the default end-to-end host to this release. Cordis stays `4.0.4`.
|
package/CHANGELOG.zh-CN.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# 更新日志
|
|
2
2
|
|
|
3
|
+
## 未发布
|
|
4
|
+
|
|
5
|
+
## [0.1.15] - 2026-10-07
|
|
6
|
+
|
|
7
|
+
- 官方桌面版可以在线更新这个插件,不再误装到 web profile。
|
|
8
|
+
- 发现新版本时,提示文字会标成提醒色;版本号颜色不变。
|
|
9
|
+
- 更新完成后需要完全退出并重新打开 DSH Desktop。
|
|
10
|
+
|
|
11
|
+
## [0.1.13] - 2026-10-06
|
|
12
|
+
|
|
13
|
+
- 已安装插件列表显示「Codex Pet」和中文简介,不再只用包名。显示名来自 `locale/zh.json` 和 `locale/en.json` 的 `meta.title`、`meta.description`。
|
|
14
|
+
- 从 GitHub 安装时已包含编译后的运行文件,不必再手动构建。
|
|
15
|
+
|
|
3
16
|
## [0.1.12] - 2026-09-30
|
|
4
17
|
|
|
5
18
|
- 新增 DSH `0.2.0-rc.2` 兼容,不移除已支持的旧宿主。开发类型和默认端到端宿主固定到该版本。Cordis 仍为 `4.0.4`。
|
package/README.md
CHANGED
|
@@ -130,7 +130,7 @@ Custom pets are stored in `.dsh/codex-pet/pets` under your user directory by def
|
|
|
130
130
|
|
|
131
131
|
## Contributing
|
|
132
132
|
|
|
133
|
-
See the [development and validation guide (Chinese)](https://github.com/MichengAI/dsh-codex-pet/blob/main/CONTRIBUTING.md) for local development, testing, and release procedures.
|
|
133
|
+
See the [development and validation guide (Chinese)](https://github.com/MichengAI/dsh-codex-pet/blob/main/CONTRIBUTING.md) for local development, testing, and release procedures. GitHub and npm both include a ready-to-run `lib`; after changing source, run `npm run build` before committing.
|
|
134
134
|
|
|
135
135
|
## License
|
|
136
136
|
|
package/README.zh-CN.md
CHANGED
|
@@ -130,7 +130,7 @@ dsh plugin --profile web remove @michengai/dsh-codex-pet
|
|
|
130
130
|
|
|
131
131
|
## 参与开发
|
|
132
132
|
|
|
133
|
-
本地开发、测试与发布流程见 [开发与验证指南](https://github.com/MichengAI/dsh-codex-pet/blob/main/CONTRIBUTING.md)。
|
|
133
|
+
本地开发、测试与发布流程见 [开发与验证指南](https://github.com/MichengAI/dsh-codex-pet/blob/main/CONTRIBUTING.md)。GitHub 与 npm 都包含可直接运行的 `lib`;修改源码后,提交前运行 `npm run build`。
|
|
134
134
|
|
|
135
135
|
## 许可证
|
|
136
136
|
|
package/lib/client.js
CHANGED
|
@@ -518,7 +518,7 @@ var UPDATE_HEADER = "x-michengai-plugin-update";
|
|
|
518
518
|
var STYLE_ID = "michengai-plugin-update-ui";
|
|
519
519
|
var CSS = `
|
|
520
520
|
.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-dialog .mpi-action:focus-visible,.mpi-dialog .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}
|
|
521
|
-
.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 .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 .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-dialog .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-dialog .mpi-action:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,#414247)}.mpi-dialog .mpi-action:disabled{cursor:not-allowed;opacity:.55}.mpi-dialog .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}}
|
|
521
|
+
.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 .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 .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-status[data-kind=update]{color:#e8b15a !important}.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-dialog .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-dialog .mpi-action:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,#414247)}.mpi-dialog .mpi-action:disabled{cursor:not-allowed;opacity:.55}.mpi-dialog .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}}
|
|
522
522
|
`;
|
|
523
523
|
var ZH = {
|
|
524
524
|
unpublished: "\u5C1A\u672A\u53D1\u5E03\u5230 npm\uFF0C\u53D1\u5E03\u540E\u5373\u53EF\u68C0\u67E5\u5E76\u5B89\u88C5\u66F4\u65B0\u3002",
|
|
@@ -541,8 +541,10 @@ var ZH = {
|
|
|
541
541
|
unknown: "\u672A\u77E5",
|
|
542
542
|
manual: "\u624B\u5DE5\u66F4\u65B0",
|
|
543
543
|
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",
|
|
544
|
+
manualHintDesktop: "\u81EA\u52A8\u66F4\u65B0\u5931\u8D25\u65F6\uFF0C\u8BF7\u5148\u5B8C\u5168\u9000\u51FA DSH Desktop\uFF0C\u518D\u7528 Desktop \u81EA\u5E26\u7684 dsh \u6267\u884C\u4EE5\u4E0B\u547D\u4EE4\u3002\u666E\u901A dsh \u4F1A\u62D2\u7EDD desktop profile\u3002",
|
|
544
545
|
intro: "\u4EC5\u68C0\u67E5\u5E76\u66F4\u65B0\u5F53\u524D\u63D2\u4EF6\uFF0C\u4E0D\u4F1A\u8054\u52A8\u5B89\u88C5\u5176\u4ED6\u63D2\u4EF6\u3002",
|
|
545
546
|
restart: "\u66F4\u65B0\u5B8C\u6210\uFF0C\u8BF7\u91CD\u542F DSH Web\u3002",
|
|
547
|
+
restartDesktop: "\u66F4\u65B0\u5B8C\u6210\uFF0C\u8BF7\u5B8C\u5168\u9000\u51FA\u5E76\u91CD\u65B0\u6253\u5F00 DSH Desktop\u3002",
|
|
546
548
|
restarting: "\u66F4\u65B0\u5B8C\u6210\uFF0C\u6B63\u5728\u91CD\u65B0\u52A0\u8F7D DSH\u2026",
|
|
547
549
|
unavailable: "\u5F53\u524D\u73AF\u5883\u4E0D\u652F\u6301\u81EA\u52A8\u66F4\u65B0\uFF0C\u8BF7\u4F7F\u7528\u624B\u5DE5\u66F4\u65B0\u547D\u4EE4\u3002"
|
|
548
550
|
};
|
|
@@ -567,8 +569,10 @@ var EN = {
|
|
|
567
569
|
unknown: "Unknown",
|
|
568
570
|
manual: "Manual update",
|
|
569
571
|
manualHint: "If automatic update fails, run this command in the current DSH terminal, then restart DSH Web.",
|
|
572
|
+
manualHintDesktop: "If automatic update fails, fully quit DSH Desktop, then run this command with Desktop's own dsh. A regular dsh rejects the desktop profile.",
|
|
570
573
|
intro: "Only this plugin is checked and updated. Other plugins are not changed.",
|
|
571
574
|
restart: "Update complete. Restart DSH Web.",
|
|
575
|
+
restartDesktop: "Update complete. Fully quit and reopen DSH Desktop.",
|
|
572
576
|
restarting: "Update complete. Reloading DSH\u2026",
|
|
573
577
|
unavailable: "Automatic update is unavailable. Use the manual command."
|
|
574
578
|
};
|
|
@@ -684,7 +688,7 @@ function observePluginUpdate(options) {
|
|
|
684
688
|
terms[1].textContent = text.latestLabel;
|
|
685
689
|
terms[2].textContent = text.profile;
|
|
686
690
|
dialog.querySelector(".mpi-manual h3").textContent = text.manual;
|
|
687
|
-
dialog.querySelector(".mpi-manual p").textContent = text.manualHint;
|
|
691
|
+
dialog.querySelector(".mpi-manual p").textContent = payload?.profileName === "desktop" ? text.manualHintDesktop : text.manualHint;
|
|
688
692
|
const status = dialog.querySelector(".mpi-status");
|
|
689
693
|
const progress = dialog.querySelector(".mpi-progress");
|
|
690
694
|
const command = dialog.querySelector(".mpi-command code");
|
|
@@ -709,6 +713,7 @@ function observePluginUpdate(options) {
|
|
|
709
713
|
const setMessage = (message, kind = "") => {
|
|
710
714
|
status.textContent = message;
|
|
711
715
|
status.dataset.kind = kind;
|
|
716
|
+
status.style.color = kind === "update" ? "#e8b15a" : "";
|
|
712
717
|
};
|
|
713
718
|
const setBusy = (value) => {
|
|
714
719
|
busy = value;
|
|
@@ -721,6 +726,9 @@ function observePluginUpdate(options) {
|
|
|
721
726
|
dialog.querySelector("[data-role=current]").textContent = payload === void 0 ? text.unknown : `v${payload.currentVersion}`;
|
|
722
727
|
dialog.querySelector("[data-role=latest]").textContent = payload?.latestVersion === void 0 ? text.unknown : `v${payload.latestVersion}`;
|
|
723
728
|
dialog.querySelector("[data-role=profile]").textContent = payload?.profileName ?? text.unknown;
|
|
729
|
+
const hint = dialog.querySelector(".mpi-manual p");
|
|
730
|
+
if (hint !== null)
|
|
731
|
+
hint.textContent = payload?.profileName === "desktop" ? text.manualHintDesktop : text.manualHint;
|
|
724
732
|
command.textContent = manualPluginUpdateCommand(
|
|
725
733
|
payload?.profileName ?? "",
|
|
726
734
|
options.packageName,
|
|
@@ -731,10 +739,10 @@ function observePluginUpdate(options) {
|
|
|
731
739
|
else if (payload.notPublished) setMessage(text.unpublished);
|
|
732
740
|
else if (payload.latestCheckFailed) setMessage(text.failed, "error");
|
|
733
741
|
else if (payload.updateAvailable)
|
|
734
|
-
setMessage(`${text.found}: v${payload.latestVersion ?? text.unknown}
|
|
742
|
+
setMessage(`${text.found}: v${payload.latestVersion ?? text.unknown}`, "update");
|
|
735
743
|
else setMessage(text.latest, "success");
|
|
736
744
|
if (payload !== void 0 && !payload.canAutoUpdate && payload.updateAvailable)
|
|
737
|
-
setMessage(text.unavailable);
|
|
745
|
+
setMessage(text.unavailable, "update");
|
|
738
746
|
};
|
|
739
747
|
const checkNow = async () => {
|
|
740
748
|
if (busy) return;
|
|
@@ -768,7 +776,7 @@ function observePluginUpdate(options) {
|
|
|
768
776
|
applyControls();
|
|
769
777
|
render();
|
|
770
778
|
setMessage(
|
|
771
|
-
payload.autoReload === true ? text.restarting : text.restart,
|
|
779
|
+
payload.autoReload === true ? text.restarting : payload.profileName === "desktop" || payload.restartDesktop === true ? text.restartDesktop : text.restart,
|
|
772
780
|
"success"
|
|
773
781
|
);
|
|
774
782
|
} catch (error) {
|
|
@@ -948,7 +956,7 @@ function PluginUpdateHeader({ locale }) {
|
|
|
948
956
|
zh2 ? "\u5BA0\u7269" : "Pets",
|
|
949
957
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dcp-version", children: [
|
|
950
958
|
"v",
|
|
951
|
-
"0.1.
|
|
959
|
+
"0.1.15"
|
|
952
960
|
] })
|
|
953
961
|
] }),
|
|
954
962
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("nav", { className: "dcp-project-links", children: [
|
package/lib/index.js
CHANGED
|
@@ -52,7 +52,7 @@ import { spawn } from "node:child_process";
|
|
|
52
52
|
import { existsSync, readFileSync } from "node:fs";
|
|
53
53
|
import { readFile } from "node:fs/promises";
|
|
54
54
|
import { homedir } from "node:os";
|
|
55
|
-
import { basename, dirname, isAbsolute, resolve } from "node:path";
|
|
55
|
+
import { basename, delimiter, dirname, isAbsolute, resolve } from "node:path";
|
|
56
56
|
import { fileURLToPath } from "node:url";
|
|
57
57
|
var PLUGIN_UPDATE_HEADER = "x-michengai-plugin-update";
|
|
58
58
|
function header(request, name2) {
|
|
@@ -68,9 +68,16 @@ function isTrustedUpdateRequest(request) {
|
|
|
68
68
|
if (!isLoopbackAddress(request.socket?.remoteAddress)) return false;
|
|
69
69
|
const site = header(request, "sec-fetch-site");
|
|
70
70
|
if (site !== void 0 && site !== "same-origin") return false;
|
|
71
|
-
const origin = header(request, "origin");
|
|
72
71
|
const host = header(request, "host");
|
|
73
|
-
if (
|
|
72
|
+
if (host === void 0 || host === "") return false;
|
|
73
|
+
const origin = header(request, "origin");
|
|
74
|
+
if (origin === void 0 || origin === "") {
|
|
75
|
+
try {
|
|
76
|
+
return isLoopbackAddress(new URL(`http://${host}`).hostname);
|
|
77
|
+
} catch {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
74
81
|
try {
|
|
75
82
|
const url = new URL(origin);
|
|
76
83
|
return (url.protocol === "http:" || url.protocol === "https:") && isLoopbackAddress(url.hostname) && url.host === host;
|
|
@@ -96,14 +103,14 @@ function isDshCliEntry(entry, manifest, packageRoot2) {
|
|
|
96
103
|
const bin = typeof value.bin === "string" ? value.bin : typeof value.bin === "object" && value.bin !== null ? value.bin.dsh : void 0;
|
|
97
104
|
return typeof bin === "string" && bin !== "" && !isAbsolute(bin) && resolve(packageRoot2, bin) === resolve(entry);
|
|
98
105
|
}
|
|
99
|
-
function cliEntry() {
|
|
100
|
-
const value =
|
|
106
|
+
function cliEntry(argv = process.argv, cwd = process.cwd(), exists = existsSync) {
|
|
107
|
+
const value = argv[1];
|
|
101
108
|
if (value === void 0 || value === "") return void 0;
|
|
102
|
-
const entry = value.startsWith("file:") ? fileURLToPath(value) : resolve(
|
|
103
|
-
if (!
|
|
109
|
+
const entry = value.startsWith("file:") ? fileURLToPath(value) : resolve(cwd, value);
|
|
110
|
+
if (!exists(entry)) return void 0;
|
|
104
111
|
for (let directory = dirname(entry); ; ) {
|
|
105
112
|
const manifestPath = resolve(directory, "package.json");
|
|
106
|
-
if (
|
|
113
|
+
if (exists(manifestPath)) {
|
|
107
114
|
try {
|
|
108
115
|
if (isDshCliEntry(
|
|
109
116
|
entry,
|
|
@@ -119,19 +126,88 @@ function cliEntry() {
|
|
|
119
126
|
directory = parent;
|
|
120
127
|
}
|
|
121
128
|
}
|
|
122
|
-
function
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
+
function optionalService(ctx, name2) {
|
|
130
|
+
try {
|
|
131
|
+
return typeof ctx.get === "function" ? ctx.get(name2) : void 0;
|
|
132
|
+
} catch {
|
|
133
|
+
return void 0;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
function isOfficialDesktopHostEntry(entry) {
|
|
137
|
+
return entry !== void 0 && entry !== "" && entry.replaceAll("\\", "/").includes("/dsh-desktop-host/");
|
|
138
|
+
}
|
|
139
|
+
function stringEnvironment(value) {
|
|
140
|
+
if (value === null || typeof value !== "object") return void 0;
|
|
141
|
+
const env = {};
|
|
142
|
+
for (const [key, item] of Object.entries(value))
|
|
143
|
+
if (typeof item === "string") env[key] = item;
|
|
144
|
+
return Object.keys(env).length === 0 ? void 0 : env;
|
|
145
|
+
}
|
|
146
|
+
function packageManagerFrom(value) {
|
|
147
|
+
if (value === null || typeof value !== "object") return void 0;
|
|
148
|
+
const item = value;
|
|
149
|
+
if (typeof item.command !== "string" || item.command === "") return void 0;
|
|
150
|
+
if (!Array.isArray(item.args) || !item.args.every((arg) => typeof arg === "string"))
|
|
151
|
+
return void 0;
|
|
152
|
+
const env = stringEnvironment(item.env);
|
|
153
|
+
return {
|
|
154
|
+
command: item.command,
|
|
155
|
+
args: item.args,
|
|
156
|
+
...env === void 0 ? {} : { env }
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function packageManagerFromArgv(argv, exists, execPath, pathEnv) {
|
|
160
|
+
if (!isOfficialDesktopHostEntry(argv[1])) return void 0;
|
|
161
|
+
const pnpm = argv[5];
|
|
162
|
+
if (typeof pnpm !== "string" || !isAbsolute(pnpm) || !exists(pnpm))
|
|
163
|
+
return void 0;
|
|
164
|
+
const bin = argv[6];
|
|
165
|
+
const path = typeof bin === "string" && bin !== "" ? `${bin}${delimiter}${pathEnv ?? ""}` : pathEnv;
|
|
166
|
+
return {
|
|
167
|
+
command: execPath,
|
|
168
|
+
args: ["--expose-internals", pnpm],
|
|
169
|
+
env: {
|
|
170
|
+
ELECTRON_RUN_AS_NODE: "1",
|
|
171
|
+
...typeof path === "string" && path !== "" ? { PATH: path } : {}
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
function pluginManagerFrom(value) {
|
|
176
|
+
if (value === null || typeof value !== "object" || typeof value.installBundle !== "function")
|
|
177
|
+
return void 0;
|
|
178
|
+
return value;
|
|
179
|
+
}
|
|
180
|
+
function resolveUpdateRuntime(ctx, options = {}) {
|
|
181
|
+
const argv = options.argv ?? process.argv;
|
|
182
|
+
const env = options.env ?? process.env;
|
|
183
|
+
const cwd = options.cwd ?? process.cwd();
|
|
184
|
+
const home = options.homeDir ?? homedir();
|
|
185
|
+
const exists = options.exists ?? existsSync;
|
|
186
|
+
const execPath = options.execPath ?? process.execPath;
|
|
187
|
+
const launched = optionalService(ctx, "profileContext");
|
|
188
|
+
const official = isOfficialDesktopHostEntry(argv[1]) || launched?.name === "desktop";
|
|
189
|
+
const launchedDir = typeof launched?.dir === "string" && isAbsolute(launched.dir) ? resolve(launched.dir) : void 0;
|
|
190
|
+
const projectDir = official && typeof argv[3] === "string" && isAbsolute(argv[3]) ? resolve(argv[3]) : void 0;
|
|
191
|
+
const cwdProfile = official && exists(resolve(cwd, "package.json")) ? resolve(cwd) : void 0;
|
|
192
|
+
const profileDir = launchedDir ?? projectDir ?? cwdProfile ?? resolve(env.DSH_PROFILE_DIR ?? resolve(home, ".dsh", "profiles", "web"));
|
|
193
|
+
const selected = profileNameFromArgv(argv);
|
|
194
|
+
const profileName = validProfileName(launched?.name) ? launched.name : official ? "desktop" : validProfileName(selected) ? selected : validProfileName(basename(profileDir)) ? basename(profileDir) : "web";
|
|
195
|
+
const packageManager = official ? packageManagerFrom(launched?.packageManager) ?? packageManagerFromArgv(argv, exists, execPath, env.PATH) : void 0;
|
|
196
|
+
const pluginManager = official && packageManager === void 0 ? pluginManagerFrom(optionalService(ctx, "pluginManager")) : void 0;
|
|
197
|
+
const entry = official ? void 0 : cliEntry(argv, cwd, exists);
|
|
129
198
|
return {
|
|
130
199
|
profileName,
|
|
131
200
|
profileDir,
|
|
201
|
+
officialDesktop: official,
|
|
202
|
+
canAutoUpdate: packageManager !== void 0 || pluginManager !== void 0 || entry !== void 0,
|
|
203
|
+
...packageManager === void 0 ? {} : { packageManager },
|
|
204
|
+
...pluginManager === void 0 ? {} : { pluginManager },
|
|
132
205
|
...entry === void 0 ? {} : { cliEntry: entry }
|
|
133
206
|
};
|
|
134
207
|
}
|
|
208
|
+
function runtime(ctx) {
|
|
209
|
+
return resolveUpdateRuntime(ctx);
|
|
210
|
+
}
|
|
135
211
|
function parseSemver(value) {
|
|
136
212
|
const match = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/.exec(
|
|
137
213
|
value
|
|
@@ -216,10 +292,64 @@ async function status(options, target) {
|
|
|
216
292
|
latestCheckFailed: latest === void 0,
|
|
217
293
|
updateAvailable: latest != null && isNewerVersion(current, latest),
|
|
218
294
|
profileName: target.profileName,
|
|
219
|
-
canAutoUpdate: target.
|
|
295
|
+
canAutoUpdate: target.canAutoUpdate
|
|
220
296
|
};
|
|
221
297
|
}
|
|
222
298
|
async function install(target, packageSpec, track) {
|
|
299
|
+
if (target.packageManager !== void 0) {
|
|
300
|
+
const manager = target.packageManager;
|
|
301
|
+
const child2 = spawn(
|
|
302
|
+
manager.command,
|
|
303
|
+
[
|
|
304
|
+
...manager.args,
|
|
305
|
+
"add",
|
|
306
|
+
"--config.minimumReleaseAge=0",
|
|
307
|
+
packageSpec,
|
|
308
|
+
"--registry=https://registry.npmjs.org/"
|
|
309
|
+
],
|
|
310
|
+
{
|
|
311
|
+
cwd: target.profileDir,
|
|
312
|
+
windowsHide: true,
|
|
313
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
314
|
+
env: { ...process.env, ...manager.env, NO_COLOR: "1" }
|
|
315
|
+
}
|
|
316
|
+
);
|
|
317
|
+
let detail2 = "";
|
|
318
|
+
child2.stdout.on("data", (chunk) => {
|
|
319
|
+
detail2 = (detail2 + String(chunk)).slice(-4e3);
|
|
320
|
+
});
|
|
321
|
+
child2.stderr.on("data", (chunk) => {
|
|
322
|
+
detail2 = (detail2 + String(chunk)).slice(-4e3);
|
|
323
|
+
});
|
|
324
|
+
const done2 = new Promise((resolve3, reject) => {
|
|
325
|
+
child2.once("error", reject);
|
|
326
|
+
child2.once(
|
|
327
|
+
"close",
|
|
328
|
+
(code) => code === 0 ? resolve3() : reject(
|
|
329
|
+
new UpdateFailure(
|
|
330
|
+
"UPDATE_FAILED",
|
|
331
|
+
detail2.trim() || `\u66F4\u65B0\u8FDB\u7A0B\u9000\u51FA\u7801 ${code}`
|
|
332
|
+
)
|
|
333
|
+
)
|
|
334
|
+
);
|
|
335
|
+
});
|
|
336
|
+
track(done2);
|
|
337
|
+
let timer2;
|
|
338
|
+
try {
|
|
339
|
+
await Promise.race([
|
|
340
|
+
done2,
|
|
341
|
+
new Promise((_, reject) => {
|
|
342
|
+
timer2 = setTimeout(() => {
|
|
343
|
+
child2.kill();
|
|
344
|
+
reject(new UpdateFailure("UPDATE_TIMEOUT"));
|
|
345
|
+
}, 10 * 6e4);
|
|
346
|
+
})
|
|
347
|
+
]);
|
|
348
|
+
} finally {
|
|
349
|
+
clearTimeout(timer2);
|
|
350
|
+
}
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
223
353
|
if (!target.cliEntry) throw new UpdateFailure("AUTO_UPDATE_UNAVAILABLE");
|
|
224
354
|
const child = spawn(
|
|
225
355
|
process.execPath,
|
|
@@ -290,7 +420,7 @@ function registerPluginUpdater(ctx, options) {
|
|
|
290
420
|
path: options.endpoint,
|
|
291
421
|
handler: async (request, response) => {
|
|
292
422
|
try {
|
|
293
|
-
const target = runtime();
|
|
423
|
+
const target = runtime(ctx);
|
|
294
424
|
if (request.method === "GET" || request.method === "HEAD") {
|
|
295
425
|
const payload = await status(options, target);
|
|
296
426
|
response.writeHead(200, {
|
|
@@ -345,7 +475,8 @@ function registerPluginUpdater(ctx, options) {
|
|
|
345
475
|
...before,
|
|
346
476
|
updatedVersion: before.latestVersion,
|
|
347
477
|
restartRequired: true,
|
|
348
|
-
autoReload: false
|
|
478
|
+
autoReload: false,
|
|
479
|
+
...target.officialDesktop ? { restartDesktop: true } : {}
|
|
349
480
|
});
|
|
350
481
|
} finally {
|
|
351
482
|
if (pendingInstall)
|
|
@@ -590,7 +721,7 @@ async function body(req) {
|
|
|
590
721
|
throw new Error("\u8BF7\u6C42\u5FC5\u987B\u662F JSON \u5BF9\u8C61");
|
|
591
722
|
return value;
|
|
592
723
|
}
|
|
593
|
-
async function createHost(options = {}) {
|
|
724
|
+
async function createHost(options = {}, host) {
|
|
594
725
|
const root = options.root ?? packageRoot;
|
|
595
726
|
const library = new PetLibrary(
|
|
596
727
|
join2(root, "assets", "codex"),
|
|
@@ -611,7 +742,8 @@ async function createHost(options = {}) {
|
|
|
611
742
|
updateHandler = void 0;
|
|
612
743
|
};
|
|
613
744
|
}
|
|
614
|
-
}
|
|
745
|
+
},
|
|
746
|
+
get: (name2) => host?.get?.(name2)
|
|
615
747
|
},
|
|
616
748
|
{
|
|
617
749
|
endpoint: `${BASE}/api/update`,
|
|
@@ -744,7 +876,7 @@ async function createHost(options = {}) {
|
|
|
744
876
|
function apply(ctx) {
|
|
745
877
|
ctx.effect(() => {
|
|
746
878
|
let disposed = false, remove, host;
|
|
747
|
-
void createHost().then((value) => {
|
|
879
|
+
void createHost({}, ctx).then((value) => {
|
|
748
880
|
host = value;
|
|
749
881
|
if (disposed) {
|
|
750
882
|
host.dispose();
|
package/locale/en.json
ADDED
package/locale/zh.json
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@michengai/dsh-codex-pet",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "DSH Codex Pet — 为 DeepSeek Harness 提供宠物陪伴、多任务提醒与交互,以及 Skill 自定义宠物 · A pet companion with multi-task notifications, interactions, and Skill-based custom pets for DeepSeek Harness",
|
|
6
6
|
"type": "module",
|
|
@@ -20,9 +20,11 @@
|
|
|
20
20
|
"exports": {
|
|
21
21
|
".": "./lib/index.js",
|
|
22
22
|
"./client": "./lib/client.js",
|
|
23
|
-
"./package.json": "./package.json"
|
|
23
|
+
"./package.json": "./package.json",
|
|
24
|
+
"./locale/*.json": "./locale/*.json"
|
|
24
25
|
},
|
|
25
26
|
"files": [
|
|
27
|
+
"locale",
|
|
26
28
|
"LICENSE",
|
|
27
29
|
"NOTICE",
|
|
28
30
|
"lib",
|