@shgroup/dsh-serenity-hooks 1.31.10 → 1.31.13

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
@@ -3,7 +3,7 @@
3
3
  > **一句话**:装上这个插件,你在电脑上给 AI 划一块自己的工作区(就是一个普通目录),
4
4
  > AI 在里面干活时就有了**记忆、纪律、工具和边界**——中途换模型、重启电脑、第二天再来,都能接着干。
5
5
  >
6
- > 适用 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(下称 DSH)0.1.5-rc.1 及以上。
6
+ > 适用 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(下称 DSH)0.1.5-rc.2 及以上。
7
7
  > 想了解背后的想法(为什么叫"认知容器"),看 [docs/cognitive-container-theory.md](https://github.com/tellmewhattodo/dsh-serenity-plugin/blob/master/docs/cognitive-container-theory.md);本文只讲**能干什么、怎么用**。
8
8
 
9
9
  **几个词先说明白**(后面都用这几个词,不再解释):
@@ -32,7 +32,7 @@
32
32
 
33
33
  ## 2. 快速开始(2 分钟)
34
34
 
35
- 前置:Node ≥ 20(或 bun)、DSH 0.1.5-rc.1 及以上。
35
+ 前置:Node ≥ 20(或 bun)、DSH 0.1.5-rc.2 及以上。
36
36
 
37
37
  ```bash
38
38
  # 1. 装插件(自动加入 DSH 的 web profile)
@@ -317,14 +317,19 @@ AI 一次能"记住"的内容有上限。满了不用你手动开新会话:
317
317
 
318
318
  ```bash
319
319
  pnpm typecheck # 类型检查(node + 浏览器端两套)
320
- pnpm test # 全量测试(当前 80 个文件 / 1176 个用例)
320
+ pnpm test # 全量测试(当前 80 个文件 / 1186 个用例)
321
321
  pnpm build # 打包(lib/index.js + client.js)
322
322
  ```
323
323
 
324
- - **开发用小工具**:`scripts/dsh-develop.ts`——typecheck / test / build / status / commit / push / version / bump / deploy / **lockfile** / restart-web / publish / pack-check / github-push 一条龙。
324
+ - **开发用小工具**:`scripts/dsh-develop.ts`——typecheck / test / build / status / commit / push / version / bump / deploy / **lockfile** / **host-upgrade** / restart-web / publish / pack-check / github-push 一条龙。
325
325
  `lockfile` = 重生成锁文件 + 用 `--frozen-lockfile` 自检(CI 的 `Install (hooks)` 同款判定);
326
326
  `pack-check` 会在发布前核对打包产物是否完整(曾经踩过"发到 npm 少了文件"的坑);`scripts/dsh-crash-investigate.ts` 用来查崩溃(只读)。
327
327
  ⚠️ **改完 `package.json` 依赖后必须跑 `lockfile` 并提交锁文件** —— v1.31.6 漏了这一步,CI 从此一直红(红在"测试根本没跑",见 CHANGELOG v1.31.10)
328
+ - **宿主类型基准 = devDependencies**(v1.31.11):`tsconfig.json` / `client/tsconfig.json` 的 `paths` 指向**仓库内** `node_modules/@deepseek-ai/*`,由精确钉版的 devDependencies 提供 → **新增 paths 条目必须同时加 devDependency**(否则 tsc 静默回落 node_modules = 假绿,CI 的 typecheck 也就形同虚设)。机械闸门见 `tests/compliance.test.ts` F7;升级宿主时只改 `package.json` 一处 + 重跑 `lockfile`
329
+ - **升级宿主(v1.31.12)**:`dsh-develop host-upgrade <版本|dist-tag>` 全局升级 DSH CLI(包名硬编码 `@deepseek-ai/dsh`、默认官方源、`--dry-run` 预览)→ 把 `package.json` 的 peer/devDeps 基准抬到同一版本 + 重跑 `lockfile`(`compliance.test.ts` F6c/F7d 与 `host-manifest.test.ts` 会强制各声明面同步,漏一处必红)→ `restart-web` → `dashboard health` 看 `dshVersion`
330
+ - **诊断会话打不开(v1.31.13)**:`dsh-develop session-doctor` —— 会话日志体检(**只读**)。
331
+ `--probe` 走宿主**真实读取路径**判定(`msm("dsh-develop", ["session-doctor","--probe","--summary"])` 可全量跑)。
332
+ ⚠️ 两个易误读点:① `readStoredLog` 是**存储层**读、**不走格式迁移** ⇒ 它对历史世代报 "no upgrade path" 属**正常现象**,不是损坏证据;判断"用户能不能打开"要看应用面 `open(id,'read')`。② 本工具修的两个真实缺陷见 CHANGELOG v1.31.13(`rebuild` 写的 `user/message` 缺 `id`/`role` ⇒ 会话**永久打不开**;`findSessionLog` 不认 `session.vN.jsonl.zstd` ⇒ 清理静默失效)
328
333
  - **架构**:Cordis 原生插件,用 DSH 的正式接口注册工具和拦截点——**从不修改 DSH 本体**
329
334
  - **代码地图**:[docs/codebase-overview-v1.22.md](https://github.com/tellmewhattodo/dsh-serenity-plugin/blob/master/docs/codebase-overview-v1.22.md)
330
335
  - **设计决策**:见 [CHANGELOG.md](https://github.com/tellmewhattodo/dsh-serenity-plugin/blob/master/CHANGELOG.md) 和维护技能 `dsh-serenity-plugin-development`
@@ -383,4 +388,4 @@ pnpm build # 打包(lib/index.js + client.js)
383
388
 
384
389
  MIT(见 [LICENSE](https://github.com/tellmewhattodo/dsh-serenity-plugin/blob/master/LICENSE))
385
390
 
386
- > **版本**:v1.31.10 | **前置**:DSH 0.1.5-rc.1+ / Node ≥ 20 或 bun | **测试**:80 个文件 / 1176 个用例
391
+ > **版本**:v1.31.13 | **前置**:DSH 0.1.5-rc.2+ / Node ≥ 20 或 bun | **测试**:80 个文件 / 1186 个用例
package/dsh.plugin.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "id": "dsh-serenity-hooks",
3
- "version": "1.31.10",
3
+ "version": "1.31.13",
4
4
  "main": "lib/index.js",
5
- "description": "宁静号 ACC harness(Native Cordis 插件):给 DSH 装一个「AI 工作区」——11 个工具(container_fs/logbook/dashboard/container_git/msm/praxis/handyman/localstore/container_admin/autopilot-trajectory/im-bridge)+ 机械约束(安全模式/工作区围墙/密钥守卫)+ 工作日志与原地重建 + 网页登录入口/微信桥/子角色/对外问答页/自主巡航。适配 DSH 0.1.5-rc.1(deepseek-ai/deepseek-harness)。",
5
+ "description": "宁静号 ACC harness(Native Cordis 插件):给 DSH 装一个「AI 工作区」——11 个工具(container_fs/logbook/dashboard/container_git/msm/praxis/handyman/localstore/container_admin/autopilot-trajectory/im-bridge)+ 机械约束(安全模式/工作区围墙/密钥守卫)+ 工作日志与原地重建 + 网页登录入口/微信桥/子角色/对外问答页/自主巡航。适配 DSH 0.1.5-rc.2(deepseek-ai/deepseek-harness)。",
6
6
  "engines": {
7
- "dsh": ">=0.1.5-rc.1"
7
+ "dsh": ">=0.1.5-rc.2"
8
8
  },
9
9
  "contributes": {
10
10
  "tools": [
@@ -62,7 +62,7 @@ export type HostEventName = (typeof HOST_EVENT_NAMES)[number];
62
62
  */
63
63
  export declare const HOST_EVENTS: readonly HostEventContract[];
64
64
  /** dsp 被验证过的宿主版本范围(与 package.json peerDependencies 同源,单一真相源) */
65
- export declare const REQUIRED_HOST_RANGE = "^0.1.5-rc.1";
65
+ export declare const REQUIRED_HOST_RANGE = "^0.1.5-rc.2";
66
66
  export interface HostContractIssue {
67
67
  id: string;
68
68
  kind: 'service' | 'member' | 'version';
package/lib/index.js CHANGED
@@ -1302,8 +1302,8 @@ const HOST_SERVICES = [
1302
1302
  }
1303
1303
  ];
1304
1304
  /** dsp 被验证过的宿主版本范围(与 package.json peerDependencies 同源,单一真相源) */
1305
- const REQUIRED_HOST_RANGE = "^0.1.5-rc.1";
1306
- /** 范围 floor:剥掉 caret/比较前缀(`^0.1.5-rc.1` → `0.1.5-rc.1`),供 {@link checkHostVersion} 使用 */
1305
+ const REQUIRED_HOST_RANGE = "^0.1.5-rc.2";
1306
+ /** 范围 floor:剥掉 caret/比较前缀(`^0.1.5-rc.2` → `0.1.5-rc.2`),供 {@link checkHostVersion} 使用 */
1307
1307
  const REQUIRED_HOST_FLOOR = REQUIRED_HOST_RANGE.replace(/^[\^~>=<\s]+/, "");
1308
1308
  /** 范围 ceiling:`^0.1.x` 的上界 = `<0.2.0`(显式常量,见 {@link checkHostVersion} 注释) */
1309
1309
  const REQUIRED_HOST_CEILING = "0.2.0";
@@ -7341,7 +7341,7 @@ function registerStatusApi(ctx, opts = {}) {
7341
7341
  const id = s.id ?? s.header?.id;
7342
7342
  if (id) liveIds.add(id);
7343
7343
  }
7344
- const { sessionsRootDir, collectEligibleSessions, performCleanup, cutoffDaysAgo } = await import("./session-cleanup-PahSNvjI.js");
7344
+ const { sessionsRootDir, collectEligibleSessions, performCleanup, cutoffDaysAgo } = await import("./session-cleanup-CMT4mHWt.js");
7345
7345
  const root = sessionsRootDir();
7346
7346
  if (req.method === "GET") {
7347
7347
  const { candidates } = performCleanup(root, cutoffDaysAgo(days), liveIds, { dryRun: true });
@@ -8654,6 +8654,22 @@ function performRebuild(session, pending, meter) {
8654
8654
  });
8655
8655
  }
8656
8656
  session.append("user/message", {
8657
+ /**
8658
+ * v1.31.13 修复(**会话打不开的真因**,S142 §26):
8659
+ * `user/message` 的 payload 必须是**完整 UserMessage**——宿主
8660
+ * `dsh-session/lib/types/index.js:229-259` `assertMessageEventShape` 对四种消息事件
8661
+ * (system/user/assistant/message + tool/result)强制:
8662
+ * `data.id` 非空字符串 → 否则 `"<subject> lacks an identified message"`
8663
+ * `data.role === 'user'` → 否则 `"<subject> message must have role \"user\""`
8664
+ * 而 `user/message` 的 message **就是 data 本身**(`type==='user/message' ? record : record.message`)。
8665
+ *
8666
+ * 旧实现只写 `{content, source}`(缺 `id` 与 `role`)→ 该事件**当场落盘成功**,
8667
+ * 但宿主在**下一次打开该会话**时整份日志校验失败抛 `SessionPersistenceCorruptionError`
8668
+ * → **会话永久打不开**(用户报的"会话老是损坏")。实证见 S142 §26.2(真实日志 seq 5066)。
8669
+ * 正确形状与 `seams/bootstrap.ts:306-311` 的锚定消息一致。
8670
+ */
8671
+ id: `rebuild-anchor-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
8672
+ role: "user",
8657
8673
  content: [{
8658
8674
  type: "text",
8659
8675
  text: pending.anchor
@@ -6,7 +6,9 @@ import { join } from "node:path";
6
6
  *
7
7
  * 背景(实证):DSH 会话物理存储 = `$DSH_HOME/sessions/`(缺省 ~/.dsh/sessions;
8
8
  * base bundle cordis.patch.yml root: dshHomePath('sessions'))。磁盘布局:
9
- * <root>/--<project-slug>--/<encoded-session-id>/session.jsonl(.zstd)
9
+ * <root>/--<project-slug>--/<encoded-session-id>/session[.vN].jsonl(.zstd)
10
+ * **世代(v1.31.13 补)**:宿主自 DSH 0.1.5 起按世代写文件,且迁移**保留源文件**
11
+ * ⇒ 一个会话目录常见 v0 与 v3 两个文件并存。本模块用 `sessionLogArtifacts()` 统一枚举世代。
10
12
  * DSH **无删除会话 API**(PersistenceCoordinator 仅 create/append/load/inspect/borrow,
11
13
  * 无 delete/purge;workspace archiveSession 只加归档集不删文件)——物理删除只能直接
12
14
  * 删文件。删除后一致性(利好):sessionPersistence.list() = readdir 扫描磁盘现存 →
@@ -39,15 +41,17 @@ function collectEligibleSessions(root, cutoffMs, liveIds = /* @__PURE__ */ new S
39
41
  const projectPath = join(root, project.name);
40
42
  for (const entry of readdirSync(projectPath, { withFileTypes: true })) {
41
43
  if (!entry.isDirectory()) continue;
42
- const log = findSessionLog(join(projectPath, entry.name));
44
+ const dirPath = join(projectPath, entry.name);
45
+ const artifacts = sessionLogArtifacts(dirPath);
46
+ if (artifacts.length === 0) continue;
47
+ const log = findSessionLog(dirPath);
43
48
  if (log === null) continue;
44
49
  if (liveIds.has(entry.name)) continue;
45
- let mtime;
46
- try {
47
- mtime = statSync(log).mtimeMs;
48
- } catch {
49
- continue;
50
- }
50
+ let mtime = Number.NEGATIVE_INFINITY;
51
+ for (const artifact of artifacts) try {
52
+ mtime = Math.max(mtime, statSync(artifact.path).mtimeMs);
53
+ } catch {}
54
+ if (!Number.isFinite(mtime)) continue;
51
55
  if (mtime >= cutoffMs) continue;
52
56
  out.push({
53
57
  id: entry.name,
@@ -59,13 +63,46 @@ function collectEligibleSessions(root, cutoffMs, liveIds = /* @__PURE__ */ new S
59
63
  }
60
64
  return out;
61
65
  }
62
- /** 在会话目录下找 session 日志文件(.jsonl / .jsonl.zstd);无 → null */
63
- function findSessionLog(sessionDirPath) {
64
- for (const name of ["session.jsonl", "session.jsonl.zstd"]) {
65
- const p = join(sessionDirPath, name);
66
- if (existsSync(p)) return p;
66
+ /**
67
+ * 会话日志文件名识别:`session.jsonl` / `session.jsonl.zstd`(= **v0 世代**)/
68
+ * `session.v<N>.jsonl[.zstd]`(= 第 N 世代,DSH 0.1.5 起按世代写文件)。
69
+ * 出处:`@deepseek-ai/dsh-session-persistence-jsonl` `parseSessionFormatLogFilename` 同款形态。
70
+ */
71
+ const SESSION_LOG_RE = /^session(?:\.v(\d+))?\.jsonl(\.zstd)?$/;
72
+ /**
73
+ * 列出会话目录下的**全部日志世代**,按代递增排序(同代内 `.jsonl` 在前、`.zstd` 在后 = 后者更代表"当前书写格式")。
74
+ *
75
+ * 为什么需要(R↓,v1.31.13 修复):宿主自 0.1.5 起改成**按世代写文件**,且迁移**保留源文件**
76
+ * ⇒ 同一会话常见 `session.jsonl.zstd`(v0)与 `session.v3.jsonl.zstd`(v3)**并存**。
77
+ * 旧实现只认前两个名字 → 新格式会话对本模块**完全不可见**(静默 no-op:清理永远不生效、磁盘只涨)。
78
+ */
79
+ function sessionLogArtifacts(sessionDirPath) {
80
+ let names;
81
+ try {
82
+ names = readdirSync(sessionDirPath);
83
+ } catch {
84
+ return [];
67
85
  }
68
- return null;
86
+ const out = [];
87
+ for (const name of names) {
88
+ const m = SESSION_LOG_RE.exec(name);
89
+ if (m === null) continue;
90
+ out.push({
91
+ name,
92
+ generation: m[1] === void 0 ? 0 : Number(m[1]),
93
+ path: join(sessionDirPath, name)
94
+ });
95
+ }
96
+ return out.sort((a, b) => a.generation - b.generation || (a.name.endsWith(".zstd") ? 1 : 0) - (b.name.endsWith(".zstd") ? 1 : 0));
97
+ }
98
+ /**
99
+ * 在会话目录下找 session 日志文件;无 → null。
100
+ * 多世代并存时返回**最高世代**(= 宿主 `findLog` 选中的当前世代;旧行为对单文件目录完全一致)。
101
+ */
102
+ function findSessionLog(sessionDirPath) {
103
+ const artifacts = sessionLogArtifacts(sessionDirPath);
104
+ const latest = artifacts[artifacts.length - 1];
105
+ return latest === void 0 ? null : latest.path;
69
106
  }
70
107
  /**
71
108
  * 执行清理(用户拍板:直接物理删,不过滤不归档;dryRun 预览不删)。
@@ -3,7 +3,9 @@
3
3
  *
4
4
  * 背景(实证):DSH 会话物理存储 = `$DSH_HOME/sessions/`(缺省 ~/.dsh/sessions;
5
5
  * base bundle cordis.patch.yml root: dshHomePath('sessions'))。磁盘布局:
6
- * <root>/--<project-slug>--/<encoded-session-id>/session.jsonl(.zstd)
6
+ * <root>/--<project-slug>--/<encoded-session-id>/session[.vN].jsonl(.zstd)
7
+ * **世代(v1.31.13 补)**:宿主自 DSH 0.1.5 起按世代写文件,且迁移**保留源文件**
8
+ * ⇒ 一个会话目录常见 v0 与 v3 两个文件并存。本模块用 `sessionLogArtifacts()` 统一枚举世代。
7
9
  * DSH **无删除会话 API**(PersistenceCoordinator 仅 create/append/load/inspect/borrow,
8
10
  * 无 delete/purge;workspace archiveSession 只加归档集不删文件)——物理删除只能直接
9
11
  * 删文件。删除后一致性(利好):sessionPersistence.list() = readdir 扫描磁盘现存 →
@@ -35,7 +37,22 @@ export interface CandidateSession {
35
37
  * root 不存在/为空 → 返回 [](非错误)。
36
38
  */
37
39
  export declare function collectEligibleSessions(root: string, cutoffMs: number, liveIds?: ReadonlySet<string>): CandidateSession[];
38
- /** 在会话目录下找 session 日志文件(.jsonl / .jsonl.zstd);无 → null */
40
+ /**
41
+ * 列出会话目录下的**全部日志世代**,按代递增排序(同代内 `.jsonl` 在前、`.zstd` 在后 = 后者更代表"当前书写格式")。
42
+ *
43
+ * 为什么需要(R↓,v1.31.13 修复):宿主自 0.1.5 起改成**按世代写文件**,且迁移**保留源文件**
44
+ * ⇒ 同一会话常见 `session.jsonl.zstd`(v0)与 `session.v3.jsonl.zstd`(v3)**并存**。
45
+ * 旧实现只认前两个名字 → 新格式会话对本模块**完全不可见**(静默 no-op:清理永远不生效、磁盘只涨)。
46
+ */
47
+ export declare function sessionLogArtifacts(sessionDirPath: string): Array<{
48
+ name: string;
49
+ generation: number;
50
+ path: string;
51
+ }>;
52
+ /**
53
+ * 在会话目录下找 session 日志文件;无 → null。
54
+ * 多世代并存时返回**最高世代**(= 宿主 `findLog` 选中的当前世代;旧行为对单文件目录完全一致)。
55
+ */
39
56
  export declare function findSessionLog(sessionDirPath: string): string | null;
40
57
  /** 删除执行结果 */
41
58
  export interface CleanupResult {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shgroup/dsh-serenity-hooks",
3
- "version": "1.31.10",
4
- "description": "宁静号 ACC harness(Native Cordis 插件)——给 DeepSeek Harness 装一个「AI 工作区」:11 个工具(container_fs/logbook/dashboard/container_git/msm/praxis/handyman/localstore/container_admin/autopilot-trajectory/im-bridge)+ 机械约束(安全模式/工作区围墙/密钥守卫/对外输出守卫)+ 工作日志与原地重建 + 网页登录入口/微信桥/子角色/对外问答页/自主巡航。适配 DSH 0.1.5-rc.1。",
3
+ "version": "1.31.13",
4
+ "description": "宁静号 ACC harness(Native Cordis 插件)——给 DeepSeek Harness 装一个「AI 工作区」:11 个工具(container_fs/logbook/dashboard/container_git/msm/praxis/handyman/localstore/container_admin/autopilot-trajectory/im-bridge)+ 机械约束(安全模式/工作区围墙/密钥守卫/对外输出守卫)+ 工作日志与原地重建 + 网页登录入口/微信桥/子角色/对外问答页/自主巡航。适配 DSH 0.1.5-rc.2。",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -52,24 +52,24 @@
52
52
  }
53
53
  },
54
54
  "peerDependencies": {
55
- "@deepseek-ai/dsh-agent": "^0.1.5-rc.1",
56
- "@deepseek-ai/dsh-agent-loop": "^0.1.5-rc.1",
57
- "@deepseek-ai/dsh-agent-presets": "^0.1.5-rc.1",
58
- "@deepseek-ai/dsh-compaction": "^0.1.5-rc.1",
59
- "@deepseek-ai/dsh-host-webserver": "^0.1.5-rc.1",
60
- "@deepseek-ai/dsh-llm": "^0.1.5-rc.1",
61
- "@deepseek-ai/dsh-session": "^0.1.5-rc.1",
62
- "@deepseek-ai/dsh-session-title": "^0.1.5-rc.1",
63
- "@deepseek-ai/dsh-shell": "^0.1.5-rc.1",
64
- "@deepseek-ai/dsh-shell-env": "^0.1.5-rc.1",
65
- "@deepseek-ai/dsh-skill": "^0.1.5-rc.1",
66
- "@deepseek-ai/dsh-system-prompt": "^0.1.5-rc.1",
67
- "@deepseek-ai/dsh-tools": "^0.1.5-rc.1",
68
- "@deepseek-ai/dsh-web": "^0.1.5-rc.1",
69
- "@deepseek-ai/dsh-web-fetch-http": "^0.1.5-rc.1",
55
+ "@deepseek-ai/cordis": "^4.0.2",
56
+ "@deepseek-ai/dsh-agent": "^0.1.5-rc.2",
57
+ "@deepseek-ai/dsh-agent-loop": "^0.1.5-rc.2",
58
+ "@deepseek-ai/dsh-agent-presets": "^0.1.5-rc.2",
59
+ "@deepseek-ai/dsh-compaction": "^0.1.5-rc.2",
60
+ "@deepseek-ai/dsh-host-webserver": "^0.1.5-rc.2",
61
+ "@deepseek-ai/dsh-llm": "^0.1.5-rc.2",
62
+ "@deepseek-ai/dsh-session": "^0.1.5-rc.2",
63
+ "@deepseek-ai/dsh-session-title": "^0.1.5-rc.2",
64
+ "@deepseek-ai/dsh-shell": "^0.1.5-rc.2",
65
+ "@deepseek-ai/dsh-shell-env": "^0.1.5-rc.2",
66
+ "@deepseek-ai/dsh-skill": "^0.1.5-rc.2",
67
+ "@deepseek-ai/dsh-system-prompt": "^0.1.5-rc.2",
68
+ "@deepseek-ai/dsh-tools": "^0.1.5-rc.2",
69
+ "@deepseek-ai/dsh-web": "^0.1.5-rc.2",
70
+ "@deepseek-ai/dsh-web-fetch-http": "^0.1.5-rc.2",
70
71
  "@deepseek-ai/schemastery": "^3.18.2",
71
- "cordis": "^4.0.0-rc.7",
72
- "@deepseek-ai/cordis": "^4.0.2"
72
+ "cordis": "^4.0.0-rc.7"
73
73
  },
74
74
  "peerDependenciesMeta": {
75
75
  "@deepseek-ai/dsh-host-webserver": {
@@ -95,6 +95,38 @@
95
95
  }
96
96
  },
97
97
  "devDependencies": {
98
+ "@deepseek-ai/cordis": "^4.0.2",
99
+ "@deepseek-ai/dsh-agent": "0.1.5-rc.2",
100
+ "@deepseek-ai/dsh-agent-loop": "0.1.5-rc.2",
101
+ "@deepseek-ai/dsh-agent-presets": "0.1.5-rc.2",
102
+ "@deepseek-ai/dsh-api-session-controller": "0.1.5-rc.2",
103
+ "@deepseek-ai/dsh-client-connection": "0.1.5-rc.2",
104
+ "@deepseek-ai/dsh-client-locale": "0.1.5-rc.2",
105
+ "@deepseek-ai/dsh-client-ui-conversation": "0.1.5-rc.2",
106
+ "@deepseek-ai/dsh-client-ui-primitives": "0.1.5-rc.2",
107
+ "@deepseek-ai/dsh-client-ui-renderer": "0.1.5-rc.2",
108
+ "@deepseek-ai/dsh-client-ui-session": "0.1.5-rc.2",
109
+ "@deepseek-ai/dsh-client-ui-settings": "0.1.5-rc.2",
110
+ "@deepseek-ai/dsh-client-ui-slots": "0.1.5-rc.2",
111
+ "@deepseek-ai/dsh-compaction": "0.1.5-rc.2",
112
+ "@deepseek-ai/dsh-host-webserver": "0.1.5-rc.2",
113
+ "@deepseek-ai/dsh-llm": "0.1.5-rc.2",
114
+ "@deepseek-ai/dsh-session": "0.1.5-rc.2",
115
+ "@deepseek-ai/dsh-session-persistence": "0.1.5-rc.2",
116
+ "@deepseek-ai/dsh-session-projection": "0.1.5-rc.2",
117
+ "@deepseek-ai/dsh-session-title": "0.1.5-rc.2",
118
+ "@deepseek-ai/dsh-settings": "0.1.5-rc.2",
119
+ "@deepseek-ai/dsh-shell": "0.1.5-rc.2",
120
+ "@deepseek-ai/dsh-shell-env": "0.1.5-rc.2",
121
+ "@deepseek-ai/dsh-skill": "0.1.5-rc.2",
122
+ "@deepseek-ai/dsh-subagent": "0.1.5-rc.2",
123
+ "@deepseek-ai/dsh-system-prompt": "0.1.5-rc.2",
124
+ "@deepseek-ai/dsh-token-meter": "0.1.5-rc.2",
125
+ "@deepseek-ai/dsh-tools": "0.1.5-rc.2",
126
+ "@deepseek-ai/dsh-web": "0.1.5-rc.2",
127
+ "@deepseek-ai/dsh-web-fetch-http": "0.1.5-rc.2",
128
+ "@deepseek-ai/dsh-workspace": "0.1.5-rc.2",
129
+ "@deepseek-ai/schemastery": "^3.18.2",
98
130
  "@types/node": "^20.0.0",
99
131
  "@types/qrcode-generator": "^1.0.6",
100
132
  "@types/react": "^18.2.0",