dsh-paoding 0.3.3 → 0.3.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.
- package/README.md +6 -3
- package/README_en.md +6 -3
- package/docs/architecture.md +4 -1
- package/docs/architecture_en.md +8 -2
- package/docs/configuration.md +3 -3
- package/docs/configuration_en.md +2 -2
- package/docs/installation.md +44 -9
- package/docs/installation_en.md +44 -9
- package/package.json +4 -2
- package/plugins/paoding-config-ui/api-core.mjs +67 -16
- package/plugins/paoding-config-ui/index.mjs +5 -1
- package/plugins/paoding-config-ui/lib/base.css +1 -1
- package/plugins/paoding-config-ui/lib/client.js +32 -0
- package/plugins/paoding-config-ui/package.json +1 -2
- package/plugins/paoding-config-ui/runtime-inventory.mjs +20 -0
- package/presets/orchestrator/agent.cordis.yml +3 -0
- package/tools/lib/preset-system.mjs +557 -0
- package/tools/lib/state.mjs +98 -23
|
@@ -12,6 +12,14 @@ import { mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from 'n
|
|
|
12
12
|
import { readFile } from 'node:fs/promises'
|
|
13
13
|
import { assignSlugs, collectState, generateAndInstall, presetIdOf } from '../../tools/install.mjs'
|
|
14
14
|
import { autoAssignments } from '../../tools/lib/alloc.mjs'
|
|
15
|
+
import {
|
|
16
|
+
backfillHomePatchRows,
|
|
17
|
+
detectPresetSystem,
|
|
18
|
+
formatGeneratorMarker,
|
|
19
|
+
listOrchestratorPresetIds,
|
|
20
|
+
parseGeneratorMarker,
|
|
21
|
+
readHomePatchRows,
|
|
22
|
+
} from '../../tools/lib/preset-system.mjs'
|
|
15
23
|
|
|
16
24
|
export function resolveDshHome() {
|
|
17
25
|
return process.env.DSH_HOME || path.join(os.homedir(), '.dsh')
|
|
@@ -118,6 +126,9 @@ export function serializeState(s) {
|
|
|
118
126
|
suggested: s.suggested,
|
|
119
127
|
installedPresets,
|
|
120
128
|
workspaceMeta,
|
|
129
|
+
// 预设安装轨道(declarative = 0.1.7+ 声明行 / directory = ≤0.1.6 目录扫描),
|
|
130
|
+
// 面板可据此展示;旧版 collectState 产出的 state 无此字段时按目录轨兜底
|
|
131
|
+
presetSystem: s.presetSystem ?? 'directory',
|
|
121
132
|
// 主 persona 尾部追加的默认常量(供 UI「人设追加」默认展示 / 恢复默认)
|
|
122
133
|
mainPersonaExtraDefault: s.mainPersonaExtraDefault ?? null,
|
|
123
134
|
// 运行时识别结果透传(字段缺失视为未启用运行时检测,与旧版 UI 行为一致)
|
|
@@ -139,10 +150,11 @@ export function installAssignments(state, assignments, { dryRun = false, saveCon
|
|
|
139
150
|
// ── 首装 / 升级后 preset 自动重生成 ─────────────────────────────────────────
|
|
140
151
|
//
|
|
141
152
|
// 唯一官方安装通道是插件通道(dsh plugin add dsh-paoding),包不再携带 CLI:
|
|
142
|
-
// preset
|
|
143
|
-
//
|
|
144
|
-
//
|
|
145
|
-
//
|
|
153
|
+
// preset 的落盘改由插件启动时自愈。对账基准是 preset 目录里的 .generator-version
|
|
154
|
+
// 标记文件(v2 起内容 = 生成器版本 + 预设安装轨道两行):插件包版本变、或宿主
|
|
155
|
+
// 轨道翻转(只升 dsh 不动插件——升级最常见路径,旧标记只记版本时同样解析为
|
|
156
|
+
// 轨道不符)→ 下次启动自动自愈,一举解决「升级后 preset 还是旧版产物」与
|
|
157
|
+
// 「升 dsh 后 preset 静默消失」两类漂移。
|
|
146
158
|
|
|
147
159
|
// 生成器版本(标记对账基准):插件包根 package.json 读一次即缓存。读失败兜底
|
|
148
160
|
// '0.0.0'——最坏后果只是每次启动多重生成一次 preset,不会装坏任何东西。
|
|
@@ -162,21 +174,30 @@ export function pluginVersion() {
|
|
|
162
174
|
const PRESET_ENSURE_ABORTED = '插件已卸载(dispose),本次 preset 生成中止'
|
|
163
175
|
|
|
164
176
|
/**
|
|
165
|
-
* 首装 /
|
|
177
|
+
* 首装 / 升级后自动安装 orchestrator preset(等价 install --auto 语义)。
|
|
166
178
|
*
|
|
167
|
-
*
|
|
168
|
-
* 不符 →
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
*
|
|
179
|
+
* 判定(满足其一即动盘):
|
|
180
|
+
* - preset 目录 / 标记缺失,或标记版本与 generatorVersion 不符 → 整盘重生成;
|
|
181
|
+
* - 版本一致但标记轨道与当前宿主轨道不符(只升 dsh 不动插件 / 旧格式标记)→
|
|
182
|
+
* 轻量迁移:声明轨上按磁盘产物补写缺失声明行(内容字节不动,不重生成),
|
|
183
|
+
* directory 轨上落回整盘重生成(残留声明行会让 0.1.6 profile 启动失败,
|
|
184
|
+
* 撤块自愈由其 directory 分支完成);
|
|
185
|
+
* - 版本轨道都一致 → 对账声明行(缺行补行、孤儿行撤行),齐则跳过。
|
|
186
|
+
* 局部 collectState() 不带运行时事实(首装触发点在插件启动、宿主服务未必就绪,
|
|
187
|
+
* 且与 CLI --auto 语义对齐;预设安装轨道由 collectState 内部按 argv 宿主版本 /
|
|
188
|
+
* dsh --version / 文件探测兜底,state.presetSystem 随 state 一并进
|
|
189
|
+
* generateAndInstall 双轨收尾;不走 refreshState()——那会拿无事实的扫描覆盖
|
|
190
|
+
* 路由层的共享缓存)后按既有配置合成 assignments(无配置写基础模板),经
|
|
191
|
+
* generateAndInstall 落盘,最后写标记文件(版本 + 轨道)。
|
|
172
192
|
* shouldAbort 在各 await 点后检查:插件 dispose 后在途的生成不再继续写盘。
|
|
173
193
|
* 可脱离 ctx 独立调用(单测友好),任何异常自捕、绝不抛出。
|
|
174
194
|
*
|
|
175
195
|
* @param {{dshHome?: string, generatorVersion?: string, shouldAbort?: () => boolean}} opts
|
|
176
196
|
* 缺省取 resolveDshHome() 与 pluginVersion();shouldAbort 返回 true 时中止
|
|
177
197
|
* (按 reason 返回,不算 error)。
|
|
178
|
-
* @returns {Promise<{installed: boolean, reason?: string, error?: string}>}
|
|
179
|
-
* installed=true 表示本次实际重生成;
|
|
198
|
+
* @returns {Promise<{installed: boolean, backfilled?: string[], reason?: string, error?: string}>}
|
|
199
|
+
* installed=true 表示本次实际重生成;backfilled 非空表示本次补写了哪些
|
|
200
|
+
* preset 的声明行(内容未重生成);两者皆否时带 reason(无需动盘 / 已中止)
|
|
180
201
|
* 或 error(生成失败,调用方只记日志)。
|
|
181
202
|
*/
|
|
182
203
|
export async function ensurePresetInstalled({ dshHome = resolveDshHome(), generatorVersion = pluginVersion(), shouldAbort = null } = {}) {
|
|
@@ -185,10 +206,35 @@ export async function ensurePresetInstalled({ dshHome = resolveDshHome(), genera
|
|
|
185
206
|
const markerFile = path.join(presetDir, '.generator-version')
|
|
186
207
|
let marker = null
|
|
187
208
|
try {
|
|
188
|
-
marker = (await readFile(markerFile, 'utf8'))
|
|
209
|
+
marker = parseGeneratorMarker(await readFile(markerFile, 'utf8'))
|
|
189
210
|
} catch { /* 目录或标记缺失:按未生成处理 */ }
|
|
190
|
-
|
|
191
|
-
|
|
211
|
+
|
|
212
|
+
if (marker !== null && marker.version === generatorVersion) {
|
|
213
|
+
// 版本一致:内容无需重生成,但宿主轨道可能已随 dsh 升降级翻转(只升 dsh
|
|
214
|
+
// 不动插件是升级常态),声明行也可能被外部动过——这里做轻量对账。
|
|
215
|
+
const system = await detectPresetSystem({ dshHome })
|
|
216
|
+
if (shouldAbort?.()) return { installed: false, reason: PRESET_ENSURE_ABORTED }
|
|
217
|
+
const presetIds = listOrchestratorPresetIds(dshHome)
|
|
218
|
+
if (system === 'declarative') {
|
|
219
|
+
const backfilled = backfillHomePatchRows(dshHome, presetIds)
|
|
220
|
+
if (marker.track === 'declarative' && backfilled.length === 0) {
|
|
221
|
+
return { installed: false, reason: 'preset 已由当前版本生成器产出,无需重生成' }
|
|
222
|
+
}
|
|
223
|
+
writeFileSync(markerFile, formatGeneratorMarker(generatorVersion, 'declarative'), 'utf8')
|
|
224
|
+
return backfilled.length > 0
|
|
225
|
+
? { installed: false, backfilled, reason: `宿主已切换声明行轨,补写 ${backfilled.length} 条预设声明行(preset 内容未重生成)` }
|
|
226
|
+
: { installed: false, reason: '预设安装轨道标记已更新为声明行轨(内容无需重生成)' }
|
|
227
|
+
}
|
|
228
|
+
// directory 轨:声明行残留会让 0.1.6 profile 启动失败——有残留走整盘
|
|
229
|
+
// 重生成(directory 分支撤块自愈);行清白时只升级标记格式,不动内容。
|
|
230
|
+
if (readHomePatchRows(dshHome).length === 0) {
|
|
231
|
+
if (marker.track === 'directory') {
|
|
232
|
+
return { installed: false, reason: 'preset 已由当前版本生成器产出,无需重生成' }
|
|
233
|
+
}
|
|
234
|
+
writeFileSync(markerFile, formatGeneratorMarker(generatorVersion, 'directory'), 'utf8')
|
|
235
|
+
return { installed: false, reason: '预设安装轨道标记已升级为带轨道格式(内容无需重生成)' }
|
|
236
|
+
}
|
|
237
|
+
// 声明行残留 + directory 宿主:落到下方整盘重生成
|
|
192
238
|
}
|
|
193
239
|
|
|
194
240
|
if (shouldAbort?.()) return { installed: false, reason: PRESET_ENSURE_ABORTED }
|
|
@@ -215,9 +261,14 @@ export async function ensurePresetInstalled({ dshHome = resolveDshHome(), genera
|
|
|
215
261
|
// 标记最后写:generateAndInstall 会整目录重建(rmSync),先写必被删。
|
|
216
262
|
if (shouldAbort?.()) return { installed: false, reason: PRESET_ENSURE_ABORTED }
|
|
217
263
|
mkdirSync(presetDir, { recursive: true })
|
|
218
|
-
|
|
264
|
+
const track = result.presetSystem === 'declarative' ? 'declarative' : 'directory'
|
|
265
|
+
writeFileSync(markerFile, formatGeneratorMarker(generatorVersion, track), 'utf8')
|
|
266
|
+
// 声明轨上整盘重生成只重建本 preset 的行:其余工作区 preset 目录若在而
|
|
267
|
+
// 声明行缺(轨道翻转后首次触发本路径),一并补齐。
|
|
268
|
+
const backfilled = track === 'declarative' ? backfillHomePatchRows(dshHome, listOrchestratorPresetIds(dshHome)) : []
|
|
219
269
|
return {
|
|
220
270
|
installed: true,
|
|
271
|
+
...(backfilled.length > 0 ? { backfilled } : {}),
|
|
221
272
|
reason: state.existing
|
|
222
273
|
? 'preset 缺失或由旧版生成器产出,已按现有配置重新生成'
|
|
223
274
|
: 'preset 缺失或由旧版生成器产出,已写入基础模板',
|
|
@@ -175,12 +175,16 @@ function triggerPresetEnsure(ctx, isDisposed) {
|
|
|
175
175
|
ctx.logger?.info?.(
|
|
176
176
|
`paoding-config-ui: orchestrator preset 已重生成(generator v${generatorVersion},${r.reason})`,
|
|
177
177
|
)
|
|
178
|
+
} else if (Array.isArray(r.backfilled) && r.backfilled.length > 0) {
|
|
179
|
+
// 轨道迁移 / 声明行对账补写(preset 内容未重生成):值得留一行轨迹,
|
|
180
|
+
// 方便「升级 dsh 后主子代理消失」这类问题定位。
|
|
181
|
+
ctx.logger?.info?.(`paoding-config-ui: ${r.reason ?? '预设声明行已补写'}(${r.backfilled.join('、')})`)
|
|
178
182
|
} else if (r.error) {
|
|
179
183
|
// 失败复位防抖闩:下次 activate(热重载 / 重注册)可重试
|
|
180
184
|
presetEnsureStarted = false
|
|
181
185
|
ctx.logger?.warn?.(`paoding-config-ui: preset 自动生成失败(可在侧栏底部「庖丁配置」入口手动应用): ${r.error}`)
|
|
182
186
|
}
|
|
183
|
-
//
|
|
187
|
+
// 版本轨道一致的常规跳过 / 纯标记格式升级不打日志:每次启动都刷一行纯噪音。
|
|
184
188
|
})
|
|
185
189
|
.catch((err) => {
|
|
186
190
|
presetEnsureStarted = false
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
flex: none;
|
|
45
45
|
padding: 1px 8px;
|
|
46
46
|
border-radius: 999px;
|
|
47
|
-
background: var(--dsw-alias-accent
|
|
47
|
+
background: var(--dsw-alias-interactive-bg-hover-accent, var(--dsw-alias-bg-layer-2));
|
|
48
48
|
font-size: 11px;
|
|
49
49
|
line-height: 16px;
|
|
50
50
|
font-weight: 500;
|
|
@@ -24,6 +24,8 @@
|
|
|
24
24
|
* - factory 内 require() 只解析平台 seed 模块(react / cordis /
|
|
25
25
|
* ui-slots / ui-primitives 与已物化模块);本 bundle 依赖 react 与
|
|
26
26
|
* @deepseek-ai/dsh-client-ui-primitives。
|
|
27
|
+
* - 图标跨版本兜底:DSH ≤0.1.6 图标导出名带尺寸后缀(IconCheckOutline16),
|
|
28
|
+
* 0.1.7-rc.1 起改粗细命名 + size prop,factory 内把旧名别名到 Regular 版。
|
|
27
29
|
* - 挂载点:左侧栏底部动作位入口(sidebar.footer.action 键控槽,与插件
|
|
28
30
|
* 广场 cordis 徽章同槽,设置行上方)+ 会话中栏全页 overlay
|
|
29
31
|
* (data-dsh-paoding-view / html[data-dsh-paoding-active]);
|
|
@@ -51,6 +53,36 @@ window.__ModuleLoader__.load({
|
|
|
51
53
|
var useState = React.useState, useEffect = React.useEffect, useCallback = React.useCallback, useRef = React.useRef;
|
|
52
54
|
var P = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
53
55
|
|
|
56
|
+
// 图标跨版本兜底:DSH ≤0.1.6 的 ui-primitives 图标导出名带尺寸后缀
|
|
57
|
+
// (IconCheckOutline16 / IconChevronDownOutline14,IconProps { size,
|
|
58
|
+
// className });0.1.7-rc.1 起改粗细命名(…OutlineRegular / …Medium,
|
|
59
|
+
// size 变 prop、默认 16),12 个旧名全部消失。同一份 bundle 要在两代
|
|
60
|
+
// 宿主上都能跑:旧名缺、新名在,才把旧名别名到对应 Regular 版——新
|
|
61
|
+
// 组件接受 size prop,ic() 的 size 传参照常生效,旧 14px 名 → Regular
|
|
62
|
+
// + size 14 视觉等价(同为 1px 描边)。旧宿主上有原生实现就用原生,
|
|
63
|
+
// Button / Pill 等两代都有的导出一律不动。
|
|
64
|
+
P = Object.assign({}, P); // 复制一份导出面再补别名:不往共享模块对象上写属性(避免污染宿主里其他 ui-primitives 消费者);P 是 factory 作用域的 var,重赋值后所有后续片段看到的就是这份副本
|
|
65
|
+
(function () {
|
|
66
|
+
var ICON_ALIAS = {
|
|
67
|
+
IconCheckOutline16: "IconCheckOutlineRegular",
|
|
68
|
+
IconChevronDownOutline14: "IconChevronDownOutlineRegular",
|
|
69
|
+
IconCordisPluginOutline14: "IconCordisPluginOutlineRegular",
|
|
70
|
+
IconDataOutline16: "IconDataOutlineRegular",
|
|
71
|
+
IconEditOutline16: "IconEditOutlineRegular",
|
|
72
|
+
IconLoadingOutline16: "IconLoadingOutlineRegular",
|
|
73
|
+
IconPlusOutline16: "IconPlusOutlineRegular",
|
|
74
|
+
IconRefreshOutline16: "IconRefreshOutlineRegular",
|
|
75
|
+
IconSkillOutline16: "IconSkillOutlineRegular",
|
|
76
|
+
IconTrashOutline16: "IconTrashOutlineRegular",
|
|
77
|
+
IconUserOutline16: "IconUserOutlineRegular",
|
|
78
|
+
IconWarningOutline16: "IconWarningOutlineRegular",
|
|
79
|
+
};
|
|
80
|
+
Object.keys(ICON_ALIAS).forEach(function (oldName) {
|
|
81
|
+
var newName = ICON_ALIAS[oldName];
|
|
82
|
+
if (P[oldName] === undefined && P[newName] !== undefined) P[oldName] = P[newName];
|
|
83
|
+
});
|
|
84
|
+
})();
|
|
85
|
+
|
|
54
86
|
// ── 样式注入(幂等)─────────────────────────────────────────────────
|
|
55
87
|
//
|
|
56
88
|
// 样式正文在 lib/base.css,由 Node 半经 GET /api/paoding/client.css 下发
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "paoding-config-ui",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.5",
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.mjs",
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
"client": {
|
|
10
10
|
"platform": "web",
|
|
11
11
|
"inject": [
|
|
12
|
-
"@deepseek-ai/dsh-client-runtime",
|
|
13
12
|
"@deepseek-ai/dsh-client-ui-settings",
|
|
14
13
|
"@deepseek-ai/dsh-client-connection"
|
|
15
14
|
]
|
|
@@ -18,6 +18,9 @@
|
|
|
18
18
|
* MCP 工具由 dsh-mcp-client 以 `mcp__<server>__<tool>` 公开名注册,
|
|
19
19
|
* 故 schemas()/entries() 等能枚举出形如 mcp__tavily__tavily_search 的
|
|
20
20
|
* 全名,与 tools/install.mjs 的 inventory 命名约定一致。
|
|
21
|
+
* - 预设安装轨道(presetSystem):agentPresets 服务有无 register 方法——
|
|
22
|
+
* 0.1.7+ 的 agent-preset-registry(声明行轨)有,≤0.1.6 的目录扫描服务
|
|
23
|
+
* 没有;collectState 拿它免掉 dsh --version 子进程探测。
|
|
21
24
|
*
|
|
22
25
|
* 约定:本模块只负责“取数”,任何一步失败都不抛出——错误记入 error 字符串
|
|
23
26
|
* (多条用 '; ' 连接、整体截断),返回可用的部分结果;列表带截断上限防爆。
|
|
@@ -187,6 +190,22 @@ function readRegisteredToolNames(ctx, errors) {
|
|
|
187
190
|
return { names: out, ok: acquired }
|
|
188
191
|
}
|
|
189
192
|
|
|
193
|
+
/**
|
|
194
|
+
* 预设安装轨道探测:0.1.7+ 宿主的 agentPresets 服务是 agent-preset-registry
|
|
195
|
+
* (带 register 方法,声明行轨);≤0.1.6 的同名服务只做 .agent-presets 目录
|
|
196
|
+
* 扫描、没有 register。ctx.reflect.get(name, false) 读不到服务返回 undefined、
|
|
197
|
+
* 不触发 inject 护栏,整个探测自捕——任何异常都按 directory(安全侧)处理,
|
|
198
|
+
* 永不抛出。
|
|
199
|
+
*/
|
|
200
|
+
function detectPresetSystemOf(ctx) {
|
|
201
|
+
try {
|
|
202
|
+
const svc = ctx?.reflect?.get?.('agentPresets', false)
|
|
203
|
+
return svc != null && typeof svc.register === 'function' ? 'declarative' : 'directory'
|
|
204
|
+
} catch {
|
|
205
|
+
return 'directory'
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
190
209
|
/**
|
|
191
210
|
* 采集运行时事实(供 collectState 合并 / UI 展示)。
|
|
192
211
|
* 永不抛出:任何异常都会落到 error 里,返回部分结果。
|
|
@@ -209,5 +228,6 @@ export function collectRuntimeFacts(ctx) {
|
|
|
209
228
|
...(error !== '' ? { error } : {}),
|
|
210
229
|
pluginEntries: plugin.entries,
|
|
211
230
|
toolNames: tools.names,
|
|
231
|
+
presetSystem: detectPresetSystemOf(ctx),
|
|
212
232
|
}
|
|
213
233
|
}
|
|
@@ -147,6 +147,9 @@
|
|
|
147
147
|
name: '@deepseek-ai/dsh-compaction-basic'
|
|
148
148
|
config:
|
|
149
149
|
thresholdRatio: 0.45
|
|
150
|
+
# 钉住摘要预算:0.1.7 起该键默认从 8192 升到 65536,显式 8192 保持
|
|
151
|
+
# 0.1.5/0.1.6 的实际行为不变(摘要单次预算不随宿主版本漂移)。
|
|
152
|
+
maxTokens: 8192
|
|
150
153
|
|
|
151
154
|
- id: command-compact
|
|
152
155
|
name: '@deepseek-ai/dsh-command-compact'
|