@michengai/dsh-codex-pet 0.1.3 → 0.1.4

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 CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.4] - 2026-09-11
4
+
5
+ - Restore compatibility with DSH `0.1.0-rc.8`, `0.1.1-rc.2`, `0.1.2-rc.1`, and `0.1.5-rc.1` while retaining `0.1.5-rc.2`. Adapt legacy session requests so pet notifications can answer questions and approvals on older hosts.
6
+
3
7
  ## [0.1.3] - 2026-09-11
4
8
 
5
9
  - Support DSH Web `0.1.5-rc.2` and correct client service injection so the plugin loads with the updated host. Older DSH versions are outside the supported range.
@@ -1,5 +1,9 @@
1
1
  # 更新日志
2
2
 
3
+ ## [0.1.4] - 2026-09-11
4
+
5
+ - 恢复 DSH `0.1.0-rc.8`、`0.1.1-rc.2`、`0.1.2-rc.1`、`0.1.5-rc.1` 兼容,同时保留 `0.1.5-rc.2`;适配旧版会话请求,使宠物通知可处理旧宿主的提问和审批。
6
+
3
7
  ## [0.1.3] - 2026-09-11
4
8
 
5
9
  - 支持 DSH Web `0.1.5-rc.2`,修正客户端服务注入声明,使插件可在新版宿主加载;旧版 DSH 不在支持范围内。
package/README.md CHANGED
@@ -72,7 +72,7 @@ Add plugins as needed to your existing DeepSeek Harness environment.
72
72
 
73
73
  ## Installation
74
74
 
75
- DeepSeek Harness **`0.1.5-rc.2`** is supported; older versions are outside the current support range. Make sure the `dsh` command is available. The example uses the `web` profile; replace it with your target profile.
75
+ Supported DeepSeek Harness versions: **`0.1.0-rc.8`, `0.1.1-rc.2`, `0.1.2-rc.1`, `0.1.5-rc.1`, and `0.1.5-rc.2`**. New compatibility is added without dropping these older releases. Make sure the `dsh` command is available. The example uses the `web` profile; replace it with your target profile.
76
76
 
77
77
  ```powershell
78
78
  [Console]::OutputEncoding = [System.Text.Encoding]::UTF8
@@ -143,9 +143,9 @@ npm run test:e2e
143
143
 
144
144
  End-to-end tests also require pnpm on PATH (CI uses `11.25.0`). They install the local package through the official CLI and boot the full DSH Web app to test pet settings, persistence, session creation, question responses, completion and failure notifications, and cancellation. Only the external model HTTP service is replaced with a local fixture; no paid model or image generation is used. Tests use a separate `DSH_HOME` and keep logs and screenshots in the ignored `.preview/e2e-latest-*` directory without changing your everyday profile.
145
145
 
146
- The official type check verifies structural compatibility, not service lifecycle behavior. E2E runs as a separate CI job with a 25-minute budget; publishing requires a successful main push CI run for the exact tagged commit, including both language jobs. Wait for CI before tagging; missing, running, skipped, or failed checks block publishing. Windows Profile link errors (`EBUSY`) retry after 5 seconds within a shared 120-second startup budget; shutdown may require up to 10 additional seconds. This mitigates transient failures without claiming Windows stability. Other failures remain failures. Reports retain the locale, original failure, retry observations, and separate cleanup errors. PowerShell (`powershell.exe` on Windows, `pwsh` elsewhere) retains the latest five completed, marked runs. Unmarked historical evidence, unfinished runs, and directories containing `.keep` are preserved; pruning never follows directory links. Add `.keep` to release acceptance evidence before subsequent runs.
146
+ The official type check verifies structural compatibility, not service lifecycle behavior. E2E runs as a separate CI job with a 25-minute budget; publishing requires a successful main push CI run for the exact tagged commit, including both language jobs for all five supported host versions. Wait for CI before tagging; missing, running, skipped, or failed checks block publishing. Windows Profile link errors (`EBUSY`) retry after 5 seconds within a shared 120-second startup budget; shutdown may require up to 10 additional seconds. This mitigates transient failures without claiming Windows stability. Other failures remain failures. Reports retain the locale, original failure, retry observations, and separate cleanup errors. PowerShell (`powershell.exe` on Windows, `pwsh` elsewhere) retains the latest five completed, marked runs. Unmarked historical evidence, unfinished runs, and directories containing `.keep` are preserved; pruning never follows directory links. Add `.keep` to release acceptance evidence before subsequent runs.
147
147
 
148
- Set `DSH_PET_E2E_LOCALE` to `zh-CN` (default) or `en-US` to choose the browser language; CI tests both.
148
+ Set `DSH_PET_E2E_LOCALE` to `zh-CN` (default) or `en-US` to choose the browser language; CI tests both languages on all five supported versions. Set `DSH_PET_E2E_VERSION` to choose an older host; its complete official dependency graph is installed in isolation with exact versions. Development dependencies remain on rc.2. Set `DSH_PET_E2E_ROOT` to a separate directory named `.preview` to place isolated hosts and evidence on another volume.
149
149
 
150
150
  ## License
151
151
 
package/README.zh-CN.md CHANGED
@@ -72,7 +72,7 @@
72
72
 
73
73
  ## 安装
74
74
 
75
- 支持 DeepSeek Harness **`0.1.5-rc.2`**,需要可使用 `dsh` 命令。旧版不在当前支持范围内。以下示例使用 `web` profile,请按实际环境替换。
75
+ 支持 DeepSeek Harness **`0.1.0-rc.8`、`0.1.1-rc.2`、`0.1.2-rc.1`、`0.1.5-rc.1`、`0.1.5-rc.2`**,需要可使用 `dsh` 命令。新增兼容不移除这些旧版。以下示例使用 `web` profile,请按实际环境替换。
76
76
 
77
77
  ```powershell
78
78
  [Console]::OutputEncoding = [System.Text.Encoding]::UTF8
@@ -143,9 +143,9 @@ npm run test:e2e
143
143
 
144
144
  端到端测试另需 PATH 中有 pnpm(CI 使用 `11.25.0`)。它通过官方 CLI 安装本地发行包、启动完整 DSH Web,验证宠物设置、持久化、创建会话、提问回传、完成与失败通知和停止任务。只有外部模型 HTTP 服务使用本地夹具,不调用付费模型或生成图片。测试使用独立 `DSH_HOME`,日志和截图保存在忽略的 `.preview/e2e-latest-*` 下,不改动日常 Profile。
145
145
 
146
- 官方类型检查验证结构兼容性,不替代服务生命周期验证。E2E 拆为独立 CI job,限时 25 分钟;发布前必须验证标签提交对应的 main push CI 成功,且中英文 job 均通过;先等待 CI,再打标签,缺失、运行中、跳过或失败的检查都会阻止发布。Windows Profile 链接错误(`EBUSY`)在共享的 120 秒启动预算内每次等待 5 秒后重试,关闭进程最多另需 10 秒;这只缓解瞬时竞争,不代表 Windows 已稳定,其他错误直接失败。报告同时保留语言、原始失败、重试记录及独立清理错误。通过 PowerShell(Windows 使用 `powershell.exe`,其他平台使用 `pwsh`)保留最近 5 次已标记并结束的运行;未标记的历史证据、未结束运行及含 `.keep` 文件的目录不回收,清理不跟随目录链接。发布验收证据应在后续运行前添加 `.keep`。
146
+ 官方类型检查验证结构兼容性,不替代服务生命周期验证。E2E 拆为独立 CI job,限时 25 分钟;发布前必须验证标签提交对应的 main push CI 成功,且全部 5 个宿主版本的中英文 job 均通过;先等待 CI,再打标签,缺失、运行中、跳过或失败的检查都会阻止发布。Windows Profile 链接错误(`EBUSY`)在共享的 120 秒启动预算内每次等待 5 秒后重试,关闭进程最多另需 10 秒;这只缓解瞬时竞争,不代表 Windows 已稳定,其他错误直接失败。报告同时保留语言、原始失败、重试记录及独立清理错误。通过 PowerShell(Windows 使用 `powershell.exe`,其他平台使用 `pwsh`)保留最近 5 次已标记并结束的运行;未标记的历史证据、未结束运行及含 `.keep` 文件的目录不回收,清理不跟随目录链接。发布验收证据应在后续运行前添加 `.keep`。
147
147
 
148
- 可设置 `DSH_PET_E2E_LOCALE` 为 `zh-CN`(默认)或 `en-US` 选择浏览器语言,CI 分别验证两种语言。
148
+ 可设置 `DSH_PET_E2E_LOCALE` 为 `zh-CN`(默认)或 `en-US` 选择浏览器语言,CI 对全部 5 个版本分别验证两种语言。设置 `DSH_PET_E2E_VERSION` 可选择旧版宿主,其完整官方依赖图在隔离目录内精确安装,开发依赖继续保持 rc.2。可通过 `DSH_PET_E2E_ROOT` 指向另一个名为 `.preview` 的独立目录,将测试宿主和证据放到其他磁盘。
149
149
 
150
150
  ## 许可证
151
151
 
package/lib/client.js CHANGED
@@ -37,6 +37,140 @@ __export(client_exports, {
37
37
  });
38
38
  module.exports = __toCommonJS(client_exports);
39
39
 
40
+ // src/session-compat.ts
41
+ function compatibleSessions(sessions) {
42
+ const cache = /* @__PURE__ */ new WeakMap();
43
+ return {
44
+ list: sessions.list,
45
+ open: (id) => sessions.open(id),
46
+ create: (options) => sessions.create(options),
47
+ binding(id) {
48
+ const binding = sessions.binding(id);
49
+ if (!binding || binding.eventSource) return binding;
50
+ const cached = cache.get(binding);
51
+ if (cached) return cached;
52
+ let lastSeq = -1, initialized = false;
53
+ let snapshot = { revision: 0, change: { kind: "replace", entries: [] } };
54
+ const eventSource = {
55
+ getSnapshot() {
56
+ const state = binding.session.getSnapshot();
57
+ if (state.openState === "cold" || state.openState === "loading") initialized = false;
58
+ const events = [...state.chat?.timeline.turns.values() ?? []].flatMap((turn) => [turn.start, turn.end]).filter((entry) => !!entry).sort((a, b) => a.seq - b.seq);
59
+ const additions = events.filter((entry) => entry.seq > lastSeq);
60
+ if (additions.length) {
61
+ lastSeq = additions.at(-1).seq;
62
+ snapshot = { revision: snapshot.revision + 1, change: { kind: initialized ? "append" : "replace", entries: additions.map((entry) => ({ type: "event", event: entry })) } };
63
+ }
64
+ initialized = state.openState === void 0 || state.openState === "open";
65
+ return snapshot;
66
+ },
67
+ subscribe: (listener) => binding.session.subscribe(listener)
68
+ };
69
+ const adapted = { ...binding, eventSource };
70
+ cache.set(binding, adapted);
71
+ return adapted;
72
+ }
73
+ };
74
+ }
75
+
76
+ // src/legacy-pending.ts
77
+ function compatiblePending(sessions, resolveModern) {
78
+ const legacy = legacyPending(sessions);
79
+ const listeners = /* @__PURE__ */ new Set();
80
+ let source = legacy;
81
+ let off;
82
+ let timer;
83
+ const notify = () => {
84
+ for (const listener of listeners) listener();
85
+ };
86
+ const sync = () => {
87
+ const next = resolveModern() ?? legacy;
88
+ if (next === source && off) return;
89
+ off?.();
90
+ source = next;
91
+ off = listeners.size ? source.subscribe(notify) : void 0;
92
+ notify();
93
+ };
94
+ return {
95
+ getSnapshot: () => source.getSnapshot(),
96
+ subscribe(listener) {
97
+ listeners.add(listener);
98
+ if (!timer) {
99
+ sync();
100
+ timer = setInterval(sync, 250);
101
+ }
102
+ return () => {
103
+ listeners.delete(listener);
104
+ if (!listeners.size) {
105
+ clearInterval(timer);
106
+ timer = void 0;
107
+ off?.();
108
+ off = void 0;
109
+ }
110
+ };
111
+ }
112
+ };
113
+ }
114
+ function legacyPending(sessions) {
115
+ const listeners = /* @__PURE__ */ new Set();
116
+ const subscriptions = /* @__PURE__ */ new Map();
117
+ let snapshot = /* @__PURE__ */ new Map();
118
+ let offList;
119
+ const refresh = () => {
120
+ const list = sessions.list.getSnapshot();
121
+ for (const [id, item] of subscriptions) if (!list.byId[id] || list.byId[id].origin === "subagent") {
122
+ item.off();
123
+ subscriptions.delete(id);
124
+ }
125
+ const next = /* @__PURE__ */ new Map();
126
+ for (const id of list.ids) {
127
+ if (list.byId[id]?.origin === "subagent") continue;
128
+ const source = sessions.binding(id)?.session;
129
+ if (!source) continue;
130
+ if (listeners.size && subscriptions.get(id)?.source !== source) {
131
+ subscriptions.get(id)?.off();
132
+ subscriptions.set(id, { source, off: source.subscribe(refresh) });
133
+ }
134
+ const wait = source.getSnapshot().pending?.[0];
135
+ if (!wait) continue;
136
+ next.set(id, {
137
+ kind: wait.kind,
138
+ key: wait.key,
139
+ sessionId: wait.sessionId,
140
+ ...wait.payload,
141
+ async answer(answer) {
142
+ if (wait.sessionId !== id || !source.getSnapshot().pending?.includes(wait)) throw new Error("\u8BF7\u6C42\u5DF2\u7ED3\u675F\u6216\u5DF2\u66F4\u6362");
143
+ const normalized = wait.kind === "question" ? { answers: answer.answers.map(({ custom, ...item }) => ({ ...item, ...custom?.trim() ? { custom: custom.trim() } : {} })) } : answer;
144
+ const value = wait.kind === "approval" ? { sessionId: id, approvalId: wait.payload.approvalId, outcome: answer } : { sessionId: id, answer: normalized };
145
+ const receipt = await wait.respond({ ok: true, value });
146
+ if (!receipt.accepted) throw new Error(receipt.reason ?? "\u5BBF\u4E3B\u62D2\u7EDD\u54CD\u5E94");
147
+ }
148
+ });
149
+ }
150
+ snapshot = next;
151
+ for (const listener of listeners) listener();
152
+ };
153
+ return {
154
+ getSnapshot: () => snapshot,
155
+ subscribe(listener) {
156
+ listeners.add(listener);
157
+ if (!offList) {
158
+ offList = sessions.list.subscribe(refresh);
159
+ refresh();
160
+ }
161
+ return () => {
162
+ listeners.delete(listener);
163
+ if (!listeners.size) {
164
+ offList?.();
165
+ offList = void 0;
166
+ for (const item of subscriptions.values()) item.off();
167
+ subscriptions.clear();
168
+ }
169
+ };
170
+ }
171
+ };
172
+ }
173
+
40
174
  // src/companion-api.ts
41
175
  function createCompanionProvider(handlers) {
42
176
  let snapshot = null, active = true, displays = 0, signature = "null";
@@ -759,7 +893,7 @@ function PluginUpdateHeader({ locale }) {
759
893
  zh2 ? "\u5BA0\u7269" : "Pets",
760
894
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dcp-version", children: [
761
895
  "v",
762
- "0.1.3"
896
+ "0.1.4"
763
897
  ] })
764
898
  ] }),
765
899
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("nav", { className: "dcp-project-links", children: [
@@ -1977,7 +2111,7 @@ function observePetSettingsIcon() {
1977
2111
  // src/client.tsx
1978
2112
  var import_jsx_runtime4 = require("react/jsx-runtime");
1979
2113
  var name = "michengai-codex-pet";
1980
- var inject = ["slots", "sessions", "uiSession", "locale"];
2114
+ var inject = ["slots", "sessions", "locale"];
1981
2115
  function openSettings() {
1982
2116
  const trigger = document.querySelector("[data-dcu-settings-trigger]");
1983
2117
  if (trigger)
@@ -2150,6 +2284,11 @@ function Page({
2150
2284
  );
2151
2285
  }
2152
2286
  function apply(ctx) {
2287
+ const sessions = compatibleSessions(ctx.sessions);
2288
+ const pending = compatiblePending(sessions, () => {
2289
+ const service = ctx.reflect ? ctx.reflect.get("uiSession") : ctx.uiSession;
2290
+ return service?.pendingInteractions;
2291
+ });
2153
2292
  ctx.slots.inject(
2154
2293
  "settings.section",
2155
2294
  () => ctx.slots.register(
@@ -2159,7 +2298,7 @@ function apply(ctx) {
2159
2298
  label: () => translator(ctx.locale.getSnapshot().active)("\u5BA0\u7269"),
2160
2299
  order: 12
2161
2300
  },
2162
- () => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Page, { sessions: ctx.sessions, locale: ctx.locale })
2301
+ () => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Page, { sessions, locale: ctx.locale })
2163
2302
  )
2164
2303
  );
2165
2304
  ctx.slots.inject(
@@ -2169,8 +2308,8 @@ function apply(ctx) {
2169
2308
  () => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2170
2309
  Overlay,
2171
2310
  {
2172
- sessions: ctx.sessions,
2173
- pending: ctx.uiSession.pendingInteractions,
2311
+ sessions,
2312
+ pending,
2174
2313
  locale: ctx.locale
2175
2314
  }
2176
2315
  )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@michengai/dsh-codex-pet",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "license": "Apache-2.0",
5
5
  "description": "独立实现的 DSH 宠物插件:Codex 原始宠物库、Skill 创建、Web 页内显示与消费者接入接口",
6
6
  "type": "module",
@@ -43,9 +43,8 @@
43
43
  "client": {
44
44
  "platform": "web",
45
45
  "inject": [
46
- "@deepseek-ai/dsh-api-session-controller",
46
+ "@deepseek-ai/dsh-client-ui-conversation",
47
47
  "@deepseek-ai/dsh-client-ui-renderer",
48
- "@deepseek-ai/dsh-client-ui-session",
49
48
  "@deepseek-ai/dsh-client-locale"
50
49
  ]
51
50
  }
@@ -60,7 +59,7 @@
60
59
  "assets:import": "tsx scripts/import-codex.ts"
61
60
  },
62
61
  "peerDependencies": {
63
- "@deepseek-ai/dsh-host-webserver": "0.1.5-rc.2",
62
+ "@deepseek-ai/dsh-host-webserver": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2",
64
63
  "react": "^18.2.0",
65
64
  "react-dom": "^18.2.0"
66
65
  },