dsh-plugin-tool-management 0.17.0 → 0.18.5

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.
Files changed (84) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/README.md +19 -4
  3. package/README_EN.md +19 -4
  4. package/docs/images/1-EN.png +0 -0
  5. package/docs/images/1.png +0 -0
  6. package/docs/images/2-EN.png +0 -0
  7. package/docs/images/2.png +0 -0
  8. package/docs/images/3-EN.png +0 -0
  9. package/docs/images/3.png +0 -0
  10. package/docs/images/4-EN.png +0 -0
  11. package/docs/images/4.png +0 -0
  12. package/docs/images/5-EN.png +0 -0
  13. package/docs/images/5.png +0 -0
  14. package/docs/images/6-EN.png +0 -0
  15. package/docs/images/6.png +0 -0
  16. package/docs/images/7-EN.png +0 -0
  17. package/docs/images/7.png +0 -0
  18. package/docs/images/8-EN.png +0 -0
  19. package/docs/images/8.png +0 -0
  20. package/docs/update.md +29 -0
  21. package/lib/client.js +1662 -161
  22. package/lib/compat/capability-specs.js +321 -0
  23. package/lib/compat/host-probe.js +261 -0
  24. package/lib/compat/host-roots.js +168 -0
  25. package/lib/compat/probe-types.js +6 -0
  26. package/lib/compat/probe.js +9 -720
  27. package/lib/context-inject-contract.js +114 -0
  28. package/lib/context-inject-frame.js +147 -0
  29. package/lib/context-inject-select.js +127 -0
  30. package/lib/context-inject-surface.js +97 -0
  31. package/lib/context-inject.js +10 -478
  32. package/lib/exports/transcript.js +223 -0
  33. package/lib/http-api.js +229 -0
  34. package/lib/hub.js +2 -0
  35. package/lib/index.js +138 -868
  36. package/lib/mcp/inspect-probe.js +199 -0
  37. package/lib/mcp/manager.js +30 -548
  38. package/lib/mcp/tool-visibility.js +388 -0
  39. package/lib/memories/archive-engine.js +142 -5
  40. package/lib/memories/archive.js +10 -1
  41. package/lib/memories/discovery.js +261 -0
  42. package/lib/memories/export-plan.js +42 -0
  43. package/lib/memories/memories-types.js +1 -0
  44. package/lib/memories/service.js +4 -38
  45. package/lib/memories/snapshot.js +10 -252
  46. package/lib/op-registry.js +21 -0
  47. package/lib/ops/compat.js +11 -0
  48. package/lib/ops/quick-prompts.js +26 -0
  49. package/lib/ops/scene-records.js +40 -0
  50. package/lib/ops/scene-sync.js +71 -1
  51. package/lib/ops/sessions.js +34 -14
  52. package/lib/ops/snapshot.js +18 -12
  53. package/lib/prompts/quick-service.js +211 -0
  54. package/lib/scene-linkage.js +184 -0
  55. package/lib/sessions/archive-schemas.js +121 -0
  56. package/lib/sessions/path-key.js +46 -0
  57. package/lib/sessions/workspace.js +29 -166
  58. package/lib/settings-sidecars.js +143 -0
  59. package/lib/skills/core-types.js +8 -0
  60. package/lib/skills/core-util.js +81 -0
  61. package/lib/skills/core.js +56 -2326
  62. package/lib/skills/dir-watch.js +71 -0
  63. package/lib/skills/frontmatter.js +96 -0
  64. package/lib/skills/homes.js +14 -0
  65. package/lib/skills/import-pipeline.js +231 -0
  66. package/lib/skills/manager-state.js +800 -0
  67. package/lib/skills/official.js +269 -0
  68. package/lib/skills/provider-registration.js +89 -0
  69. package/lib/skills/service.js +5 -240
  70. package/lib/skills/skill-roots.js +287 -0
  71. package/lib/skills/skill-trash.js +265 -0
  72. package/lib/skills/system-trash.js +97 -0
  73. package/lib/skills/upload-pipeline.js +374 -0
  74. package/lib/slash-settings.js +25 -0
  75. package/lib/subagents/persona-parse.js +312 -0
  76. package/lib/subagents/persona-types.js +5 -0
  77. package/lib/subagents/persona-write.js +93 -0
  78. package/lib/subagents/run-provider.js +159 -0
  79. package/lib/subagents/service.js +14 -638
  80. package/lib/subagents/tool-filter.js +98 -0
  81. package/lib/token-config.js +240 -0
  82. package/lib/tool-table-switch.js +163 -0
  83. package/lib/tools/scene.js +40 -9
  84. package/package.json +3 -2
@@ -0,0 +1,168 @@
1
+ // 宿主安装根的发现与「该走哪条恢复路」的判定。
2
+ //
3
+ // 声明从 compat/probe.ts 按行号区间搬来,正文一字未改(唯一的容差是 `--export-top-level`
4
+ // 加的 `export ` 前缀,moved-verify 逐字对拍)。
5
+ //
6
+ // 为什么单独一层:这几件是「宿主装在哪、按什么形状找得到它」的**位置**知识,与 probe.ts 主体
7
+ // 那份「宿主版本与能力对不对」的**判定**知识是两件事;混在一起时 probe.ts 里几百行读代码的
8
+ // 视线都要先跨过一遍 asar / npx 缓存的路径拼接。
9
+ // 搬走的这些行里没有任何一处读 `import.meta.url` / `createRequire` —— 那两处在 probe.ts 主体
10
+ // 里(深度敏感,一挪就改语义),这一层不碰。
11
+ import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
12
+ import { dirname, join } from 'node:path';
13
+ import { realPathWithReason, safeResolve, } from './host-probe.js';
14
+ // 类型面照旧从 lib/compat/probe.js 对外可见(`ops/compat.ts` 等按这个路径引它们)。
15
+ export const IDENTITY_PACKAGES = [
16
+ '@deepseek-ai/cordis',
17
+ '@deepseek-ai/dsh-tools',
18
+ '@deepseek-ai/dsh-workspace',
19
+ '@deepseek-ai/dsh-session-projection-cache',
20
+ '@deepseek-ai/dsh-storage-domain',
21
+ '@deepseek-ai/dsh-spill-local',
22
+ ];
23
+ export const VERIFIED_HOST_VERSION = '0.2.0-rc.2';
24
+ export const OPERATION_ROUTES = {
25
+ archive: { native: ['workspace.archive-native'], adapter: ['workspace.enqueue', 'workspace.set-state'] },
26
+ unarchive: { native: ['workspace.unarchive-native'], adapter: ['workspace.enqueue', 'workspace.set-state'] },
27
+ batch: { native: ['workspace.batch-native'], adapter: ['workspace.enqueue', 'workspace.set-state'] },
28
+ delete: {
29
+ native: ['workspace.delete-native'],
30
+ // NOTE: `projection.delete-native` is deliberately NOT a route requirement.
31
+ // A host cache without its own delete barrier is expected on rc.2; the
32
+ // bridge wraps it (`workspace.js` / `sessions/bridge.ts`) and reports a
33
+ // refusal itself when even that is impossible. Requiring the native barrier
34
+ // here would disable deletion on exactly the host this plugin was verified
35
+ // against.
36
+ adapter: [
37
+ 'workspace.enqueue', 'workspace.set-state', 'workspace.index-header',
38
+ 'sessions.detach-live', 'sessions.cold-announce', 'projection.write',
39
+ // B2:运行时硬前提(`table.delete`)也算一条路由要求 —— 不算进来的话,宿主表不可删时
40
+ // 路由说可用、点下去必拒。batch 的 adapter 路由**有意**保持只有 enqueue/set-state:
41
+ // 它的逐条失败会在结果里按 sessionId 报出来,此处不放宽也不收紧。
42
+ 'projection.table-delete',
43
+ ],
44
+ },
45
+ list: { native: [], adapter: ['workspace.read-state', 'workspace.read-table', 'workspace.index-shape'] },
46
+ };
47
+ export function recoveryFor(_finding) {
48
+ return `宿主 ${VERIFIED_HOST_VERSION} 的该项能力未通过探测;请更新本插件到与本机 DSH 匹配的版本,或改用宿主原生入口(先运行 node scripts/doctor.mjs 查看差异)。`;
49
+ }
50
+ export function hostRootCandidates() {
51
+ const home = process.env.DSH_HOME || join(process.env.USERPROFILE || process.env.HOME || '', '.dsh');
52
+ const candidates = [];
53
+ const asarHost = asarHostPackageRoot();
54
+ if (asarHost !== null)
55
+ candidates.push(asarHost);
56
+ if (home !== '')
57
+ candidates.push(join(home, 'profiles', 'node_modules', '@deepseek-ai'));
58
+ for (const anchor of IDENTITY_PACKAGES) {
59
+ // 锚点候选只认**真实形态**:取不到就跳过(这里没有可比的对象,如实跳过即可,
60
+ // 与身份比对不同 —— 那边取不到必须报出来,见 assessHost 的 realpath 说明)。
61
+ const real = realPathWithReason(safeResolve(anchor));
62
+ if ('reason' in real)
63
+ continue;
64
+ const resolved = real.path;
65
+ let dir = dirname(resolved);
66
+ for (let i = 0; i < 4; i += 1) {
67
+ if (dir.endsWith(join('node_modules', '@deepseek-ai'))) {
68
+ candidates.push(dir);
69
+ break;
70
+ }
71
+ const parent = dirname(dir);
72
+ if (parent === dir)
73
+ break;
74
+ dir = parent;
75
+ }
76
+ }
77
+ candidates.push(...npxCacheHostRoots());
78
+ return candidates;
79
+ }
80
+ export function asarHostPackageRoot() {
81
+ const resources = process.resourcesPath;
82
+ if (typeof resources !== 'string' || resources === '')
83
+ return null;
84
+ const dir = join(resources, 'app.asar', 'dsh', 'node_modules', '@deepseek-ai');
85
+ try {
86
+ if (!existsSync(join(dir, 'dsh', 'package.json')))
87
+ return null;
88
+ }
89
+ catch {
90
+ return null;
91
+ }
92
+ return dir;
93
+ }
94
+ export function npxCacheHostRoots() {
95
+ const home = process.env.USERPROFILE || process.env.HOME || '';
96
+ let cache = process.env.npm_config_cache || '';
97
+ if (!cache && home) {
98
+ try {
99
+ const rc = readFileSync(join(home, '.npmrc'), 'utf8');
100
+ cache = rc.match(/^\s*cache\s*=\s*(.+?)\s*$/m)?.[1] ?? '';
101
+ }
102
+ catch { /* no .npmrc — defaults below */ }
103
+ }
104
+ if (!cache && process.env.LOCALAPPDATA)
105
+ cache = join(process.env.LOCALAPPDATA, 'npm-cache');
106
+ if (!cache)
107
+ return [];
108
+ const roots = [];
109
+ const npxRoot = join(cache, '_npx');
110
+ let entries = [];
111
+ try {
112
+ entries = readdirSync(npxRoot);
113
+ }
114
+ catch {
115
+ return [];
116
+ }
117
+ for (const entry of entries) {
118
+ const dir = join(npxRoot, entry, 'node_modules', '@deepseek-ai');
119
+ if (!existsSync(join(dir, 'dsh', 'package.json')))
120
+ continue;
121
+ try {
122
+ roots.push({ dir, mtime: statSync(dir).mtimeMs });
123
+ }
124
+ catch { /* raced — skip */ }
125
+ }
126
+ return roots.sort((left, right) => right.mtime - left.mtime).map((root) => root.dir);
127
+ }
128
+ export function findingsById(assessment) {
129
+ return new Map(assessment.findings.map((finding) => [finding.id, finding]));
130
+ }
131
+ export function refusalsFor(assessment, ids) {
132
+ const index = findingsById(assessment);
133
+ const out = [];
134
+ for (const id of ids) {
135
+ const finding = index.get(id);
136
+ if (finding === undefined || finding.state === 'ok')
137
+ continue;
138
+ out.push({ id: finding.id, label: finding.label, detail: finding.detail, recovery: recoveryFor(finding) });
139
+ }
140
+ return out;
141
+ }
142
+ export function routeFor(assessment, operation) {
143
+ const routes = OPERATION_ROUTES[operation];
144
+ const index = findingsById(assessment);
145
+ const allOk = (ids) => ids.every((id) => {
146
+ const finding = index.get(id);
147
+ // A capability that the host does not expose at all cannot block a route
148
+ // it is not part of; absent ids are treated as satisfied.
149
+ return finding === undefined || finding.state === 'ok';
150
+ });
151
+ if (routes.native.length > 0 && allOk(routes.native))
152
+ return { via: 'native', refusals: [] };
153
+ if (allOk(routes.adapter))
154
+ return { via: 'adapter', refusals: [] };
155
+ const needed = routes.native.length > 0 ? [...new Set([...routes.native, ...routes.adapter])] : routes.adapter;
156
+ const refusals = refusalsFor(assessment, needed);
157
+ if (refusals.length > 0)
158
+ return { via: 'none', refusals };
159
+ return {
160
+ via: 'none',
161
+ refusals: [{
162
+ id: operation,
163
+ label: operation,
164
+ detail: '宿主未提供该操作的任何可用路径',
165
+ recovery: recoveryFor({ id: operation }),
166
+ }],
167
+ };
168
+ }
@@ -0,0 +1,6 @@
1
+ // 宿主探测的公开类型面:能力判定、身份比对、评估快照、拒绝文案。
2
+ //
3
+ // 为什么单独一层:probe.ts 的判定逻辑、host-probe.ts 的取数原语、capability-specs.ts
4
+ // 的能力表都要读这些类型。留在 probe.ts 里会让三者互相 import 出类型环,
5
+ // 同目录已有先例 —— memories/constants.ts 正是为断环而抽出的常量层。
6
+ export {};