dsh-deps 0.0.1 → 0.1.0

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/plugin.mjs ADDED
@@ -0,0 +1,156 @@
1
+ /**
2
+ * dsh-deps 的 host 半:往 DSH 里注册模型可调用工具 `dsh_deps`。
3
+ *
4
+ * 契约(照本机 DSH 0.2.2-rc.1 实测):
5
+ * - 只 import `node:` 内置与包内相对路径,**不 import `@deepseek-ai/*`**;
6
+ * - 工具用裸 JSON Schema ToolDefinition 注册,无编译;
7
+ * - 只读、不联网:latest 只来自调用方传的本地快照;快照缺了就 unknown;
8
+ * - 不自动改文件:pin 只返回 diff 文本。
9
+ */
10
+
11
+ import { runAction, VERSION } from './lib/engine.mjs'
12
+ import { renderReport } from './lib/format.mjs'
13
+ import { describeError } from './lib/errors.mjs'
14
+
15
+ /** cordis 插件名(= 包名)。 */
16
+ export const name = 'dsh-deps'
17
+
18
+ /** 需要宿主提供的服务:工具注册表。 */
19
+ export const inject = ['tools']
20
+
21
+ /** 默认值;可被 cordis.patch.yml 的 config 覆盖。 */
22
+ const DEFAULTS = {
23
+ snapshot: null,
24
+ installed: null,
25
+ nodeVersion: '',
26
+ }
27
+
28
+ /** 工具参数(宿主强制 JSON Schema 子集;任意 JSON 字段用 {} 声明)。 */
29
+ const PARAMETERS = {
30
+ type: 'object',
31
+ additionalProperties: false,
32
+ properties: {
33
+ action: {
34
+ type: 'string',
35
+ enum: ['plan', 'why', 'pin', 'audit'],
36
+ description: 'plan = 升级清单 + 五档分级 + 风险 + 建议顺序;why = 某个依赖为什么这么判;pin = 把范围收紧到已锁版本的 diff;audit = 一次体检。',
37
+ },
38
+ package_json: { description: 'package.json 解析后的对象(只读,不会被修改)。' },
39
+ package_json_text: { type: 'string', description: 'package.json 原文(用于 pin 生成带行号的 diff;与 package_json 二选一)。' },
40
+ snapshot: { description: '本地 registry 快照 {name:{latest,deprecated?,engines?,yanked?}};latest 只能来自这里,缺了就 unknown。' },
41
+ installed: { description: 'installed 快照 {name:"x.y.z"}(例如从 lockfile 解析);不传则当前版本取声明范围下界。' },
42
+ manifests: { type: 'array', items: { type: 'object' }, description: '工作区里所有 manifest(用于统计被依赖次数;第一份是根)。' },
43
+ dependents: { description: '显式的被依赖次数 {name: count},覆盖自动统计。' },
44
+ node_version: { type: 'string', description: '当前 Node 版本(默认取运行时版本),用于判断 engines 兼容性。' },
45
+ name: { type: 'string', description: 'why 动作要解释的依赖名。' },
46
+ },
47
+ required: ['action'],
48
+ }
49
+
50
+ /** 工具返回值 schema:声明关键字段,允许可空 / 任意 JSON。 */
51
+ const OUTPUT_SCHEMA = {
52
+ type: 'object',
53
+ properties: {
54
+ tool: { type: 'string' },
55
+ version: { type: 'string' },
56
+ action: { type: 'string' },
57
+ readOnly: { type: 'boolean' },
58
+ wroteFiles: { type: 'array', items: { type: 'string' } },
59
+ manifestName: { type: 'string' },
60
+ nodeVersion: { type: 'string' },
61
+ snapshotProvided: { type: 'boolean' },
62
+ installedProvided: { type: 'boolean' },
63
+ versionSourceNote: { type: 'string' },
64
+ entries: { type: 'array', items: { type: 'object' } },
65
+ plan: {},
66
+ audit: {},
67
+ rationale: { type: 'string' },
68
+ phaseOrder: { type: 'array', items: { type: 'string' } },
69
+ found: { type: 'boolean' },
70
+ checks: { type: 'array', items: { type: 'object' } },
71
+ conclusion: { type: 'string' },
72
+ changes: { type: 'array', items: { type: 'object' } },
73
+ diff: { type: 'string' },
74
+ applied: { type: 'boolean' },
75
+ summary: { type: 'string' },
76
+ notes: { type: 'array', items: { type: 'string' } },
77
+ limitations: { type: 'array', items: { type: 'string' } },
78
+ },
79
+ required: ['action', 'readOnly'],
80
+ }
81
+
82
+ /**
83
+ * 组装工具定义。
84
+ * @param {object} [config] 插件配置(来自 cordis.patch.yml)
85
+ * @returns {object} 可注册的 ToolDefinition
86
+ */
87
+ export function createToolDefinition(config = {}) {
88
+ const settings = { ...DEFAULTS, ...config }
89
+
90
+ return {
91
+ name: 'dsh_deps',
92
+ description:
93
+ '依赖升级规划:给定 package.json 与(可选的)本地 registry 快照,算哪些依赖能升、升了有什么风险、按什么顺序升。'
94
+ + '五档分级写死:patch / minor / major / pinned / unknown;latest 只来自调用方给的本地快照,快照里没有就 unknown,绝不联网猜。'
95
+ + '风险信号具体到 major 升级 / engines 不兼容 / deprecated / yanked / peer 范围破坏,每条给建议动作;'
96
+ + '建议顺序先 patch 后 minor 再 major,同组按被依赖次数降序并说明理由。只读:不写 package.json / lockfile,pin 只返回 diff 文本。',
97
+ parameters: PARAMETERS,
98
+ output: {
99
+ schema: OUTPUT_SCHEMA,
100
+ render(_args, value) {
101
+ return [{ type: 'text', text: renderReport(value, { detail: 'brief' }) }]
102
+ },
103
+ presentationMeta(_args, value) {
104
+ return {
105
+ action: value.action,
106
+ verdict: value.audit?.verdict ?? null,
107
+ bump: value.plan?.counts?.byBump ?? null,
108
+ actionable: value.plan?.counts?.actionable ?? null,
109
+ changes: Array.isArray(value.changes) ? value.changes.length : null,
110
+ }
111
+ },
112
+ },
113
+ presentCall(args) {
114
+ return { card: 'search', title: `依赖升级规划 ${args.action}${args.name ? ` · ${args.name}` : ''}`, kind: 'search', rawInput: args }
115
+ },
116
+ presentResult(_args, result) {
117
+ if (result.isError || !result.meta) return undefined
118
+ const meta = result.meta
119
+ const state = meta.action === 'pin'
120
+ ? `pin ${meta.changes ?? 0} 项`
121
+ : meta.action === 'why'
122
+ ? '单依赖解释'
123
+ : `${meta.actionable ?? 0} 个可升 · ${meta.verdict ?? ''}`
124
+ return { card: 'search', title: `dsh_deps · ${state}`, content: result.content }
125
+ },
126
+ async execute(args, exec) {
127
+ try {
128
+ return await runAction(args.action, {
129
+ packageJson: args.package_json ?? settings.packageJson,
130
+ packageJsonText: args.package_json_text,
131
+ snapshot: args.snapshot ?? settings.snapshot,
132
+ installed: args.installed ?? settings.installed,
133
+ manifests: args.manifests,
134
+ dependents: args.dependents,
135
+ nodeVersion: args.node_version || settings.nodeVersion,
136
+ name: args.name,
137
+ signal: exec?.signal,
138
+ })
139
+ } catch (error) {
140
+ const info = describeError(error)
141
+ throw new Error(`[${info.code}] ${info.message}${info.hint ? `\n→ ${info.hint}` : ''}`)
142
+ }
143
+ },
144
+ }
145
+ }
146
+
147
+ /**
148
+ * 插件激活:注册工具。
149
+ * @param {object} ctx cordis 上下文(需已注入 tools)
150
+ * @param {object} [config] 插件配置
151
+ * @returns {void}
152
+ */
153
+ export function apply(ctx, config = {}) {
154
+ ctx.tools.register(createToolDefinition(config))
155
+ ctx.logger?.info?.(`dsh-deps ${VERSION}: 已注册工具 dsh_deps(升级规划,只读不猜 latest)`)
156
+ }