kcode-pi 0.1.14 → 0.1.15
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 +27 -25
- package/dist/context/project-context.js +20 -20
- package/extensions/kingdee-harness.ts +80 -80
- package/extensions/kingdee-header.ts +16 -16
- package/extensions/kingdee-tools.ts +82 -82
- package/package.json +2 -2
- package/prompts/kd-discuss.md +4 -4
- package/prompts/kd-execute.md +4 -5
- package/prompts/kd-plan.md +4 -5
- package/prompts/kd-ship.md +4 -5
- package/prompts/kd-spec.md +4 -5
- package/prompts/kd-verify.md +4 -5
- package/src/context/project-context.ts +20 -20
- package/src/harness/artifacts.ts +47 -47
- package/src/harness/format.ts +12 -12
- package/src/harness/gates.ts +5 -5
- package/src/harness/plan-steps.ts +3 -3
- package/src/harness/state.ts +4 -4
- package/src/harness/tdd-policy.ts +2 -2
- package/src/knowledge/format.ts +11 -12
- package/src/product/profile.ts +16 -16
- package/src/tools/build-debug.ts +35 -35
- package/src/tools/sdk-signature.ts +10 -10
|
@@ -32,7 +32,7 @@ function readActiveRun(cwd: string): ActiveRun | undefined {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
function formatProduct(run: ActiveRun | undefined): string {
|
|
35
|
-
if (!run) return "
|
|
35
|
+
if (!run) return "未选择";
|
|
36
36
|
const product = run.profile?.product ?? run.product ?? "unknown";
|
|
37
37
|
const techStack = run.profile?.techStack ?? "unknown";
|
|
38
38
|
const language = run.profile?.language ?? "unknown";
|
|
@@ -40,13 +40,13 @@ function formatProduct(run: ActiveRun | undefined): string {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
function formatPhase(phase: ActiveRun["phase"]): string {
|
|
43
|
-
return phase ?? "
|
|
43
|
+
return phase ?? "空闲";
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
function formatGate(run: ActiveRun | undefined): string {
|
|
47
|
-
if (!run?.gate) return "
|
|
48
|
-
if (run.gate.passed) return "
|
|
49
|
-
return
|
|
47
|
+
if (!run?.gate) return "门禁:待检查";
|
|
48
|
+
if (run.gate.passed) return "门禁:通过";
|
|
49
|
+
return `门禁:阻塞${run.gate.reason ? ` - ${run.gate.reason}` : ""}`;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
function padOrTrim(text: string, width: number): string {
|
|
@@ -60,7 +60,7 @@ function logoLines(theme: Theme): string[] {
|
|
|
60
60
|
const muted = (text: string) => theme.fg("muted", text);
|
|
61
61
|
|
|
62
62
|
return [
|
|
63
|
-
`${accent("KCode")} ${muted("
|
|
63
|
+
`${accent("KCode")} ${muted("金蝶 Pi Harness")}`,
|
|
64
64
|
`${accent("=====")} ${muted("discuss -> spec -> plan -> execute -> verify -> ship")}`,
|
|
65
65
|
];
|
|
66
66
|
}
|
|
@@ -76,15 +76,15 @@ export default function (pi: ExtensionAPI) {
|
|
|
76
76
|
const phase = formatPhase(run?.phase);
|
|
77
77
|
const product = formatProduct(run);
|
|
78
78
|
const gate = formatGate(run);
|
|
79
|
-
const risk = run?.risk ?? "
|
|
80
|
-
const runId = run?.id ?? "
|
|
79
|
+
const risk = run?.risk ?? "未知";
|
|
80
|
+
const runId = run?.id ?? "无";
|
|
81
81
|
|
|
82
82
|
const status = [
|
|
83
|
-
theme.fg("muted", "
|
|
83
|
+
theme.fg("muted", "阶段:"),
|
|
84
84
|
theme.fg("accent", phase),
|
|
85
|
-
theme.fg("muted", " |
|
|
85
|
+
theme.fg("muted", " | 产品:"),
|
|
86
86
|
theme.fg("text", product),
|
|
87
|
-
theme.fg("muted", " |
|
|
87
|
+
theme.fg("muted", " | 风险:"),
|
|
88
88
|
theme.fg(risk === "high" ? "error" : risk === "medium" ? "warning" : "success", risk),
|
|
89
89
|
theme.fg("muted", " | "),
|
|
90
90
|
theme.fg(run?.gate?.passed === false ? "error" : "muted", gate),
|
|
@@ -94,7 +94,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
94
94
|
"",
|
|
95
95
|
...logoLines(theme).map((line) => padOrTrim(line, width)),
|
|
96
96
|
padOrTrim(status, width),
|
|
97
|
-
padOrTrim(theme.fg("dim", `run
|
|
97
|
+
padOrTrim(theme.fg("dim", `run:${runId}`), width),
|
|
98
98
|
"",
|
|
99
99
|
];
|
|
100
100
|
},
|
|
@@ -104,19 +104,19 @@ export default function (pi: ExtensionAPI) {
|
|
|
104
104
|
});
|
|
105
105
|
|
|
106
106
|
pi.registerCommand("kcode-header", {
|
|
107
|
-
description: "
|
|
107
|
+
description: "恢复 KCode 金蝶标题栏",
|
|
108
108
|
handler: async (_args, ctx) => {
|
|
109
109
|
if (ctx.mode !== "tui") return;
|
|
110
|
-
ctx.ui.notify("
|
|
110
|
+
ctx.ui.notify("请重启会话或重新加载扩展以恢复 KCode 标题栏。", "info");
|
|
111
111
|
},
|
|
112
112
|
});
|
|
113
113
|
|
|
114
114
|
pi.registerCommand("builtin-header", {
|
|
115
|
-
description: "
|
|
115
|
+
description: "恢复 Pi 内置标题栏",
|
|
116
116
|
handler: async (_args, ctx) => {
|
|
117
117
|
if (ctx.mode !== "tui") return;
|
|
118
118
|
ctx.ui.setHeader(undefined);
|
|
119
|
-
ctx.ui.notify("
|
|
119
|
+
ctx.ui.notify("已恢复 Pi 内置标题栏", "info");
|
|
120
120
|
},
|
|
121
121
|
});
|
|
122
122
|
}
|
|
@@ -74,8 +74,8 @@ function sdkLanguageForProfile(profile: ProductProfile, value: string | undefine
|
|
|
74
74
|
|
|
75
75
|
function rejectNonCosmic(profile: ProductProfile): string | undefined {
|
|
76
76
|
if (isCosmicFamily(profile)) return undefined;
|
|
77
|
-
if (profile.product === "unknown") return "
|
|
78
|
-
return
|
|
77
|
+
if (profile.product === "unknown") return "请先提供 Cosmic 家族产品:cangqiong、xinghan、flagship 或 cosmic。";
|
|
78
|
+
return `当前产品 ${profile.product} 使用 ${profile.platform}/${profile.techStack},不适用 Cosmic 官方能力。`;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
async function runOrDryRun(
|
|
@@ -87,7 +87,7 @@ async function runOrDryRun(
|
|
|
87
87
|
const command = await commandPromise;
|
|
88
88
|
if (dryRun) {
|
|
89
89
|
return {
|
|
90
|
-
content: [{ type: "text" as const, text:
|
|
90
|
+
content: [{ type: "text" as const, text: `仅展示命令,不执行:\n${command.display}` }],
|
|
91
91
|
details: { command: command.display, dryRun: true },
|
|
92
92
|
};
|
|
93
93
|
}
|
|
@@ -102,13 +102,13 @@ async function runOrDryRun(
|
|
|
102
102
|
|
|
103
103
|
const kdSearchTool = defineTool({
|
|
104
104
|
name: "kd_search",
|
|
105
|
-
label: "KD
|
|
106
|
-
description: "
|
|
105
|
+
label: "KD 搜索",
|
|
106
|
+
description: "搜索 KCode 随包金蝶知识库,包括 SDK、插件生命周期、代码模式和常见实现建议。",
|
|
107
107
|
parameters: Type.Object({
|
|
108
|
-
query: Type.String({ description: "
|
|
109
|
-
product: Type.Optional(Type.String({ description: "
|
|
110
|
-
edition: Type.Optional(Type.String({ description: "
|
|
111
|
-
limit: Type.Optional(Type.Number({ description: "
|
|
108
|
+
query: Type.String({ description: "要搜索的关键词、API、类名、表名或生命周期术语。" }),
|
|
109
|
+
product: Type.Optional(Type.String({ description: "金蝶产品:flagship、cosmic、xinghan、cangqiong 或 enterprise。" })),
|
|
110
|
+
edition: Type.Optional(Type.String({ description: "旧参数,等同于 product。优先使用 product。" })),
|
|
111
|
+
limit: Type.Optional(Type.Number({ description: "最大结果数,默认 5。" })),
|
|
112
112
|
}),
|
|
113
113
|
|
|
114
114
|
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
@@ -117,15 +117,15 @@ const kdSearchTool = defineTool({
|
|
|
117
117
|
if (!scopes) {
|
|
118
118
|
const guidance =
|
|
119
119
|
profile.product === "unknown"
|
|
120
|
-
? "
|
|
121
|
-
: "
|
|
120
|
+
? "请先提供 product,例如 flagship、enterprise、cosmic、xinghan 或 cangqiong。"
|
|
121
|
+
: "当前产品画像未配置可搜索知识范围。";
|
|
122
122
|
return {
|
|
123
123
|
content: [
|
|
124
124
|
{
|
|
125
125
|
type: "text",
|
|
126
126
|
text: [
|
|
127
|
-
|
|
128
|
-
"
|
|
127
|
+
`产品画像:${profile.product}/${profile.techStack}/${profile.language}`,
|
|
128
|
+
"KCode 随包知识库搜索需要明确产品画像。",
|
|
129
129
|
guidance,
|
|
130
130
|
].join("\n"),
|
|
131
131
|
},
|
|
@@ -145,12 +145,12 @@ const kdSearchTool = defineTool({
|
|
|
145
145
|
|
|
146
146
|
const kdTableTool = defineTool({
|
|
147
147
|
name: "kd_table",
|
|
148
|
-
label: "KD
|
|
149
|
-
description: "
|
|
148
|
+
label: "KD 表结构",
|
|
149
|
+
description: "按表名查询 KCode 随包金蝶表结构,查询结果受产品画像约束。",
|
|
150
150
|
parameters: Type.Object({
|
|
151
|
-
table: Type.String({ description: "
|
|
152
|
-
product: Type.Optional(Type.String({ description: "
|
|
153
|
-
edition: Type.Optional(Type.String({ description: "
|
|
151
|
+
table: Type.String({ description: "表名,例如 T_PUR_POORDER。" }),
|
|
152
|
+
product: Type.Optional(Type.String({ description: "金蝶产品:flagship、cosmic、xinghan、cangqiong 或 enterprise。" })),
|
|
153
|
+
edition: Type.Optional(Type.String({ description: "旧参数,等同于 product。优先使用 product。" })),
|
|
154
154
|
}),
|
|
155
155
|
|
|
156
156
|
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
@@ -159,15 +159,15 @@ const kdTableTool = defineTool({
|
|
|
159
159
|
if (!edition) {
|
|
160
160
|
const guidance =
|
|
161
161
|
profile.product === "unknown"
|
|
162
|
-
? "
|
|
163
|
-
: "
|
|
162
|
+
? "请先提供 product。不要跨金蝶产品族猜测表结构。"
|
|
163
|
+
: "没有元数据查证前,不要把旗舰版/企业版表结构假设复用到苍穹/星瀚/Cosmic。";
|
|
164
164
|
return {
|
|
165
165
|
content: [
|
|
166
166
|
{
|
|
167
167
|
type: "text",
|
|
168
168
|
text: [
|
|
169
|
-
|
|
170
|
-
"
|
|
169
|
+
`产品画像:${profile.product}/${profile.techStack}/${profile.language}`,
|
|
170
|
+
"KCode 随包表结构目前主要覆盖旗舰版和企业版。",
|
|
171
171
|
guidance,
|
|
172
172
|
].join("\n"),
|
|
173
173
|
},
|
|
@@ -186,14 +186,14 @@ const kdTableTool = defineTool({
|
|
|
186
186
|
|
|
187
187
|
const kdCheckTool = defineTool({
|
|
188
188
|
name: "kd_check",
|
|
189
|
-
label: "KD
|
|
189
|
+
label: "KD 检查",
|
|
190
190
|
description:
|
|
191
|
-
"
|
|
191
|
+
"检查金蝶 Java/C#/Python 插件代码中的魔法值、命名问题、循环内 DB 调用和空 catch 等问题。",
|
|
192
192
|
parameters: Type.Object({
|
|
193
|
-
code: Type.Optional(Type.String({ description: "
|
|
194
|
-
path: Type.Optional(Type.String({ description: "
|
|
195
|
-
product: Type.Optional(Type.String({ description: "
|
|
196
|
-
language: Type.Optional(Type.String({ description: "
|
|
193
|
+
code: Type.Optional(Type.String({ description: "要检查的源码。与 path 二选一。" })),
|
|
194
|
+
path: Type.Optional(Type.String({ description: "要检查的源码文件路径。与 code 二选一。" })),
|
|
195
|
+
product: Type.Optional(Type.String({ description: "金蝶产品。未提供 language 时用于推导 Java 或 C#。" })),
|
|
196
|
+
language: Type.Optional(Type.String({ description: "语言:java、csharp 或 python。会覆盖产品推导结果。" })),
|
|
197
197
|
}),
|
|
198
198
|
|
|
199
199
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
@@ -210,7 +210,7 @@ const kdCheckTool = defineTool({
|
|
|
210
210
|
|
|
211
211
|
if (!code) {
|
|
212
212
|
return {
|
|
213
|
-
content: [{ type: "text", text: "
|
|
213
|
+
content: [{ type: "text", text: "kd_check 需要提供 code 或 path。" }],
|
|
214
214
|
details: { error: "missing-code-or-path" },
|
|
215
215
|
};
|
|
216
216
|
}
|
|
@@ -220,7 +220,7 @@ const kdCheckTool = defineTool({
|
|
|
220
220
|
content: [
|
|
221
221
|
{
|
|
222
222
|
type: "text",
|
|
223
|
-
text:
|
|
223
|
+
text: `来源:${source}\n产品:${profile.product}/${profile.techStack}\n语言:${language}\n\n${formatCheckResults(results)}`,
|
|
224
224
|
},
|
|
225
225
|
],
|
|
226
226
|
details: { source, product: profile.product, language, issues: results },
|
|
@@ -230,12 +230,12 @@ const kdCheckTool = defineTool({
|
|
|
230
230
|
|
|
231
231
|
const kdCosmicConfigTool = defineTool({
|
|
232
232
|
name: "kd_cosmic_config",
|
|
233
|
-
label: "KD Cosmic
|
|
234
|
-
description: "
|
|
233
|
+
label: "KD Cosmic 配置",
|
|
234
|
+
description: "运行 Cosmic 家族金蝶产品的官方能力配置预检查。",
|
|
235
235
|
parameters: Type.Object({
|
|
236
|
-
product: Type.String({ description: "Cosmic
|
|
237
|
-
config: Type.Optional(Type.String({ description: "
|
|
238
|
-
dryRun: Type.Optional(Type.Boolean({ description: "
|
|
236
|
+
product: Type.String({ description: "Cosmic 家族产品:cangqiong、xinghan、flagship 或 cosmic。" }),
|
|
237
|
+
config: Type.Optional(Type.String({ description: "可选 ok-cosmic.json 路径。默认按当前工作目录解析。" })),
|
|
238
|
+
dryRun: Type.Optional(Type.Boolean({ description: "只返回命令,不实际执行。" })),
|
|
239
239
|
}),
|
|
240
240
|
|
|
241
241
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
@@ -248,18 +248,18 @@ const kdCosmicConfigTool = defineTool({
|
|
|
248
248
|
|
|
249
249
|
const kdCosmicMetadataTool = defineTool({
|
|
250
250
|
name: "kd_cosmic_metadata",
|
|
251
|
-
label: "KD Cosmic
|
|
252
|
-
description: "
|
|
251
|
+
label: "KD Cosmic 元数据",
|
|
252
|
+
description: "查询官方 Cosmic 表单/单据元数据,包括字段、枚举值、操作和 SQL 表信息。",
|
|
253
253
|
parameters: Type.Object({
|
|
254
|
-
product: Type.String({ description: "Cosmic
|
|
255
|
-
form: Type.String({ description: "Form ID
|
|
256
|
-
config: Type.Optional(Type.String({ description: "
|
|
257
|
-
fuzzy: Type.Optional(Type.String({ description: "
|
|
258
|
-
typeFilter: Type.Optional(Type.String({ description: "
|
|
259
|
-
sql: Type.Optional(Type.Boolean({ description: "
|
|
260
|
-
op: Type.Optional(Type.Boolean({ description: "
|
|
261
|
-
showDetail: Type.Optional(Type.Boolean({ description: "
|
|
262
|
-
dryRun: Type.Optional(Type.Boolean({ description: "
|
|
254
|
+
product: Type.String({ description: "Cosmic 家族产品:cangqiong、xinghan、flagship 或 cosmic。" }),
|
|
255
|
+
form: Type.String({ description: "Form ID、单据 ID 或中文单据名;多个目标可用逗号分隔。" }),
|
|
256
|
+
config: Type.Optional(Type.String({ description: "可选 ok-cosmic.json 路径。" })),
|
|
257
|
+
fuzzy: Type.Optional(Type.String({ description: "可选字段关键词,用空格或逗号分隔。" })),
|
|
258
|
+
typeFilter: Type.Optional(Type.String({ description: "可选字段类型正则,例如 combo|check 或 decimal。" })),
|
|
259
|
+
sql: Type.Optional(Type.Boolean({ description: "是否包含数据库表和字段信息。" })),
|
|
260
|
+
op: Type.Optional(Type.Boolean({ description: "是否显示表单/单据操作。" })),
|
|
261
|
+
showDetail: Type.Optional(Type.Boolean({ description: "是否显示详细元数据输出。" })),
|
|
262
|
+
dryRun: Type.Optional(Type.Boolean({ description: "只返回命令,不实际执行。" })),
|
|
263
263
|
}),
|
|
264
264
|
|
|
265
265
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
@@ -273,15 +273,15 @@ const kdCosmicMetadataTool = defineTool({
|
|
|
273
273
|
const kdCosmicApiTool = defineTool({
|
|
274
274
|
name: "kd_cosmic_api",
|
|
275
275
|
label: "KD Cosmic API",
|
|
276
|
-
description: "
|
|
276
|
+
description: "查询随包 Cosmic API 知识,获取类和方法线索;最终签名事实应以 kd_sdk_signature 或项目构建输出为准。",
|
|
277
277
|
parameters: Type.Object({
|
|
278
|
-
product: Type.String({ description: "Cosmic
|
|
279
|
-
mode: Type.String({ description: "search
|
|
280
|
-
query: Type.String({ description: "
|
|
281
|
-
config: Type.Optional(Type.String({ description: "
|
|
282
|
-
method: Type.Optional(Type.String({ description: "
|
|
283
|
-
compact: Type.Optional(Type.Boolean({ description: "
|
|
284
|
-
dryRun: Type.Optional(Type.Boolean({ description: "
|
|
278
|
+
product: Type.String({ description: "Cosmic 家族产品:cangqiong、xinghan、flagship 或 cosmic。" }),
|
|
279
|
+
mode: Type.String({ description: "查询模式:search、search-method 或 detail。" }),
|
|
280
|
+
query: Type.String({ description: "类名、方法名或完整限定类名。" }),
|
|
281
|
+
config: Type.Optional(Type.String({ description: "可选 ok-cosmic.json 路径。" })),
|
|
282
|
+
method: Type.Optional(Type.String({ description: "detail 模式下的可选方法过滤条件。" })),
|
|
283
|
+
compact: Type.Optional(Type.Boolean({ description: "支持时请求紧凑详情输出。" })),
|
|
284
|
+
dryRun: Type.Optional(Type.Boolean({ description: "只返回命令,不实际执行。" })),
|
|
285
285
|
}),
|
|
286
286
|
|
|
287
287
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
@@ -289,7 +289,7 @@ const kdCosmicApiTool = defineTool({
|
|
|
289
289
|
const rejection = rejectNonCosmic(profile);
|
|
290
290
|
if (rejection) return { content: [{ type: "text", text: rejection }], details: { rejected: true, product: profile.product } };
|
|
291
291
|
if (!["search", "search-method", "detail"].includes(params.mode)) {
|
|
292
|
-
return { content: [{ type: "text", text: "mode
|
|
292
|
+
return { content: [{ type: "text", text: "mode 必须是 search、search-method 或 detail。" }], details: { error: "invalid-mode" } };
|
|
293
293
|
}
|
|
294
294
|
return runOrDryRun(
|
|
295
295
|
cosmicApiCommand(ctx.cwd, {
|
|
@@ -305,17 +305,17 @@ const kdCosmicApiTool = defineTool({
|
|
|
305
305
|
|
|
306
306
|
const kdSdkSignatureTool = defineTool({
|
|
307
307
|
name: "kd_sdk_signature",
|
|
308
|
-
label: "KD SDK
|
|
308
|
+
label: "KD SDK 签名",
|
|
309
309
|
description:
|
|
310
|
-
"
|
|
310
|
+
"从当前项目真实存在的 SDK jar 或 dll 中检查方法/类型签名。涉及 API 签名事实时,优先使用它而不是随包知识库。",
|
|
311
311
|
parameters: Type.Object({
|
|
312
|
-
product: Type.Optional(Type.String({ description: "
|
|
313
|
-
language: Type.Optional(Type.String({ description: "java
|
|
314
|
-
query: Type.Optional(Type.String({ description: "
|
|
315
|
-
className: Type.Optional(Type.String({ description: "
|
|
316
|
-
method: Type.Optional(Type.String({ description: "
|
|
317
|
-
path: Type.Optional(Type.String({ description: "
|
|
318
|
-
limit: Type.Optional(Type.Number({ description: "
|
|
312
|
+
product: Type.Optional(Type.String({ description: "金蝶产品。未提供 language 时用于推导 Java 或 C#。" })),
|
|
313
|
+
language: Type.Optional(Type.String({ description: "java 或 csharp。默认由产品画像推导。" })),
|
|
314
|
+
query: Type.Optional(Type.String({ description: "要搜索的类/类型关键词,例如 QueryServiceHelper 或 DynamicObject。" })),
|
|
315
|
+
className: Type.Optional(Type.String({ description: "已知时提供完整限定 Java/C# 类型名。" })),
|
|
316
|
+
method: Type.Optional(Type.String({ description: "在匹配类/类型内过滤方法或属性;不会全局扫描所有方法。" })),
|
|
317
|
+
path: Type.Optional(Type.String({ description: "可选 SDK lib/bin 目录或依赖根路径。默认从当前项目查找。" })),
|
|
318
|
+
limit: Type.Optional(Type.Number({ description: "最大检查 jar/dll/class 数量。默认 20 个结果类、200 个文件。" })),
|
|
319
319
|
}),
|
|
320
320
|
|
|
321
321
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
@@ -338,12 +338,12 @@ const kdSdkSignatureTool = defineTool({
|
|
|
338
338
|
|
|
339
339
|
const kdKsqlLintTool = defineTool({
|
|
340
340
|
name: "kd_ksql_lint",
|
|
341
|
-
label: "KD KSQL
|
|
342
|
-
description: "
|
|
341
|
+
label: "KD KSQL 检查",
|
|
342
|
+
description: "对生成的 KSQL/SQL 文件运行官方 ok-ksql lint 检查。",
|
|
343
343
|
parameters: Type.Object({
|
|
344
|
-
product: Type.String({ description: "Cosmic
|
|
345
|
-
path: Type.String({ description: "SQL/KSQL
|
|
346
|
-
dryRun: Type.Optional(Type.Boolean({ description: "
|
|
344
|
+
product: Type.String({ description: "Cosmic 家族产品:cangqiong、xinghan、flagship 或 cosmic。" }),
|
|
345
|
+
path: Type.String({ description: "SQL/KSQL 文件路径,可为工作区相对路径或绝对路径。" }),
|
|
346
|
+
dryRun: Type.Optional(Type.Boolean({ description: "只返回命令,不实际执行。" })),
|
|
347
347
|
}),
|
|
348
348
|
|
|
349
349
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
@@ -356,12 +356,12 @@ const kdKsqlLintTool = defineTool({
|
|
|
356
356
|
|
|
357
357
|
const kdBuildTool = defineTool({
|
|
358
358
|
name: "kd_build",
|
|
359
|
-
label: "KD
|
|
360
|
-
description: "
|
|
359
|
+
label: "KD 构建",
|
|
360
|
+
description: "按产品画像运行或预览金蝶构建命令,支持 Cosmic Java 和企业版 C# 项目。",
|
|
361
361
|
parameters: Type.Object({
|
|
362
|
-
product: Type.String({ description: "
|
|
363
|
-
target: Type.Optional(Type.String({ description: "
|
|
364
|
-
dryRun: Type.Optional(Type.Boolean({ description: "
|
|
362
|
+
product: Type.String({ description: "金蝶产品:cangqiong、xinghan、flagship、cosmic 或 enterprise。" }),
|
|
363
|
+
target: Type.Optional(Type.String({ description: "Java 可提供 Gradle/Maven task;C# 可提供 .sln/.csproj 路径。" })),
|
|
364
|
+
dryRun: Type.Optional(Type.Boolean({ description: "只返回构建命令,不实际执行。" })),
|
|
365
365
|
}),
|
|
366
366
|
|
|
367
367
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
@@ -380,12 +380,12 @@ const kdBuildTool = defineTool({
|
|
|
380
380
|
|
|
381
381
|
const kdDebugTool = defineTool({
|
|
382
382
|
name: "kd_debug",
|
|
383
|
-
label: "KD
|
|
384
|
-
description: "
|
|
383
|
+
label: "KD 调试",
|
|
384
|
+
description: "分析金蝶构建/运行日志或堆栈,给出可能原因和下一步检查建议。",
|
|
385
385
|
parameters: Type.Object({
|
|
386
|
-
text: Type.Optional(Type.String({ description: "
|
|
387
|
-
path: Type.Optional(Type.String({ description: "
|
|
388
|
-
product: Type.Optional(Type.String({ description: "
|
|
386
|
+
text: Type.Optional(Type.String({ description: "日志文本或堆栈。与 path 二选一。" })),
|
|
387
|
+
path: Type.Optional(Type.String({ description: "日志文件路径。与 text 二选一。" })),
|
|
388
|
+
product: Type.Optional(Type.String({ description: "可选产品提示,用于补充上下文。" })),
|
|
389
389
|
}),
|
|
390
390
|
|
|
391
391
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
@@ -396,9 +396,9 @@ const kdDebugTool = defineTool({
|
|
|
396
396
|
return {
|
|
397
397
|
content: [
|
|
398
398
|
{
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
399
|
+
type: "text",
|
|
400
|
+
text: `来源:${input.source}\n产品:${profile.product}/${profile.platform}/${profile.techStack}\n\n${formatDebugFindings(findings)}`,
|
|
401
|
+
},
|
|
402
402
|
],
|
|
403
403
|
details: { source: input.source, product: profile.product, findings },
|
|
404
404
|
};
|
package/package.json
CHANGED
package/prompts/kd-discuss.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: 开始或继续金蝶 Harness 工作流的需求讨论阶段。
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
使用 `kd-discuss` skill。
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
围绕本次请求开始或更新当前金蝶 Harness run:
|
|
8
8
|
|
|
9
9
|
{{args}}
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
请把业务目标、金蝶产品/版本、技术栈、插件类型、目标单据/表单/实体、非目标范围和待确认问题记录到 `CONTEXT.md`。
|
package/prompts/kd-execute.md
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: 在 Harness 门禁约束下执行当前金蝶实施计划。
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
使用 `kd-execute` skill。
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
编辑代码前,先使用 `kd_plan_status` 检查当前 run。如果缺少 `PLAN.md` 或门禁被阻塞,必须停止并说明缺少的文档或证据。通过后只实现 `PLAN.md` 批准的内容,并更新 `EXECUTION.md`。
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
用户补充说明:
|
|
10
10
|
|
|
11
11
|
{{args}}
|
|
12
|
-
|
package/prompts/kd-plan.md
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: 为当前金蝶 Harness run 编写实施计划。
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
使用 `kd-plan` skill。
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
读取 `CONTEXT.md` 和 `SPEC.md`,编写或更新 `PLAN.md`。必须包含已检查的项目结构、需要查看的文件、预计修改的真实路径、必须查证的金蝶 API/元数据、验证命令和回滚说明。
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
用户补充说明:
|
|
10
10
|
|
|
11
11
|
{{args}}
|
|
12
|
-
|
package/prompts/kd-ship.md
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: 验证后整理金蝶交付摘要。
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
使用 `kd-ship` skill。
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
读取当前 run 的阶段文档,生成 `SHIP.md`,说明行为变化、验证证据、残余风险和后续事项。缺少 `VERIFY.md` 时不得进入交付总结。
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
用户补充说明:
|
|
10
10
|
|
|
11
11
|
{{args}}
|
|
12
|
-
|
package/prompts/kd-spec.md
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: 为当前金蝶 Harness run 编写需求规格文档。
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
使用 `kd-spec` skill。
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
读取当前金蝶 run 的上下文,编写或更新 `SPEC.md`。必须包含验收标准、生命周期/扩展点、数据对象、异常行为、性能约束、假设和风险。
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
用户补充说明:
|
|
10
10
|
|
|
11
11
|
{{args}}
|
|
12
|
-
|
package/prompts/kd-verify.md
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: 验证当前金蝶实现并收集证据。
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
使用 `kd-verify` skill。
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
执行计划中的验证命令,收集证据,运行可用检查,并更新 `VERIFY.md`。如果某项验证无法运行,记录具体阻塞原因和残余风险。
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
用户补充说明:
|
|
10
10
|
|
|
11
11
|
{{args}}
|
|
12
|
-
|
|
@@ -59,33 +59,33 @@ export function generateProjectContext(cwd: string): string {
|
|
|
59
59
|
const sourceSamples = scan.files.filter((file) => SOURCE_EXTENSIONS.has(extname(file).toLowerCase())).slice(0, MAX_SOURCE_SAMPLES);
|
|
60
60
|
|
|
61
61
|
return [
|
|
62
|
-
"# KCode
|
|
62
|
+
"# KCode 项目上下文",
|
|
63
63
|
"",
|
|
64
|
-
`-
|
|
65
|
-
`-
|
|
66
|
-
`-
|
|
64
|
+
`- 项目根目录:${cwd}`,
|
|
65
|
+
`- 项目名称:${basename(cwd)}`,
|
|
66
|
+
`- 生成时间:${new Date().toISOString()}`,
|
|
67
67
|
"",
|
|
68
|
-
"##
|
|
68
|
+
"## 持久规则",
|
|
69
69
|
"",
|
|
70
|
-
"-
|
|
71
|
-
"-
|
|
72
|
-
"-
|
|
73
|
-
"-
|
|
74
|
-
"-
|
|
75
|
-
"-
|
|
70
|
+
"- 本文件是 KCode 的项目记忆,计划或编辑代码前必须读取。",
|
|
71
|
+
"- 业务需求不得生成 demo/sample/scaffold 代码。",
|
|
72
|
+
"- 不要假设模块结构。必须基于下方真实路径,并在编辑前确认目标文件。",
|
|
73
|
+
"- 调用文件工具时优先使用项目相对路径。在 Windows 中,不要把路径改写为 /mnt/<drive>/... 或 /<drive>/...;只有确需绝对路径时才使用 Windows 路径。",
|
|
74
|
+
"- 如果本文件过期,计划前先运行 `kcode context --refresh` 重新生成。",
|
|
75
|
+
"- 只有 Harness 进入 `execute` 且 PLAN.md 写明真实目标路径后,才能写产品代码。",
|
|
76
76
|
"",
|
|
77
|
-
"##
|
|
77
|
+
"## 项目结构摘要",
|
|
78
78
|
"",
|
|
79
|
-
`-
|
|
80
|
-
`-
|
|
81
|
-
`-
|
|
82
|
-
`-
|
|
79
|
+
`- 是否存在 code 目录:${codeDir ? "是" : "否"}`,
|
|
80
|
+
`- 可能的源码根:${formatList(likelyRoots)}`,
|
|
81
|
+
`- 构建文件:${formatList(buildFiles)}`,
|
|
82
|
+
`- 识别到的模块:${formatList(modules)}`,
|
|
83
83
|
"",
|
|
84
|
-
"##
|
|
84
|
+
"## 源码样例",
|
|
85
85
|
"",
|
|
86
86
|
formatBlockList(sourceSamples),
|
|
87
87
|
"",
|
|
88
|
-
"##
|
|
88
|
+
"## 顶层目录",
|
|
89
89
|
"",
|
|
90
90
|
formatBlockList(scan.directories.filter((dir) => !dir.includes("/") && !dir.includes("\\")).sort()),
|
|
91
91
|
"",
|
|
@@ -202,11 +202,11 @@ function isSolutionOrProject(file: string): boolean {
|
|
|
202
202
|
}
|
|
203
203
|
|
|
204
204
|
function formatList(values: string[]): string {
|
|
205
|
-
return values.length > 0 ? values.join(", ") : "
|
|
205
|
+
return values.length > 0 ? values.join(", ") : "未识别";
|
|
206
206
|
}
|
|
207
207
|
|
|
208
208
|
function formatBlockList(values: string[]): string {
|
|
209
|
-
if (values.length === 0) return "-
|
|
209
|
+
if (values.length === 0) return "- 未识别";
|
|
210
210
|
return values.map((value) => `- ${value}`).join("\n");
|
|
211
211
|
}
|
|
212
212
|
|