@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 +4 -0
- package/CHANGELOG.zh-CN.md +4 -0
- package/README.md +3 -3
- package/README.zh-CN.md +3 -3
- package/lib/client.js +144 -5
- package/package.json +3 -4
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.
|
package/CHANGELOG.zh-CN.md
CHANGED
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
|
|
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`
|
|
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
|
|
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.
|
|
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", "
|
|
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
|
|
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
|
|
2173
|
-
pending
|
|
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
|
+
"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-
|
|
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
|
},
|