kcode-pi 0.1.14 → 0.1.16
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 +31 -25
- package/dist/context/project-context.js +20 -20
- package/extensions/kingdee-harness.ts +89 -82
- package/extensions/kingdee-header.ts +16 -16
- package/extensions/kingdee-tools.ts +112 -83
- 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 +52 -47
- package/src/harness/format.ts +12 -12
- package/src/harness/gates.ts +23 -13
- package/src/harness/plan-steps.ts +3 -3
- package/src/harness/sdk-policy.ts +37 -0
- 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
package/src/tools/build-debug.ts
CHANGED
|
@@ -20,17 +20,17 @@ export interface DebugFinding {
|
|
|
20
20
|
|
|
21
21
|
export function planBuild(cwd: string, profile: ProductProfile, target?: string): BuildPlan {
|
|
22
22
|
if (profile.product === "unknown") {
|
|
23
|
-
throw new Error("
|
|
23
|
+
throw new Error("产品画像未知。运行 kd_build 前请先设置 product。");
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
if (profile.platform === "cosmic") return planJavaBuild(cwd, profile, target);
|
|
27
27
|
if (profile.platform === "enterprise-csharp") return planCsharpBuild(cwd, profile, target);
|
|
28
28
|
if (profile.platform === "enterprise-python") {
|
|
29
29
|
throw new Error(
|
|
30
|
-
"
|
|
30
|
+
"企业版 Python 插件通常没有本地构建步骤。请通过 BOS 注册和功能测试验证,并在 VERIFY.md 中记录脚本路径、插件类型、FormId、字段/实体标识和测试数据。",
|
|
31
31
|
);
|
|
32
32
|
}
|
|
33
|
-
throw new Error(
|
|
33
|
+
throw new Error(`未找到 ${profile.product}/${profile.platform}/${profile.techStack} 的构建策略。`);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
export async function runBuild(plan: BuildPlan, dryRun?: boolean) {
|
|
@@ -55,66 +55,66 @@ export function analyzeDebugText(text: string): DebugFinding[] {
|
|
|
55
55
|
pushIfMatch(findings, lines, /NullPointerException|Object reference not set/i, {
|
|
56
56
|
severity: "error",
|
|
57
57
|
rule: "null-pointer",
|
|
58
|
-
message: "
|
|
59
|
-
nextStep: "
|
|
58
|
+
message: "检测到空指针/空引用异常。",
|
|
59
|
+
nextStep: "检查堆栈附近的字段元数据、可空字段、DynamicObject 取值和 DataSet 行读取。",
|
|
60
60
|
});
|
|
61
61
|
|
|
62
62
|
pushIfMatch(findings, lines, /ClassNotFoundException|NoClassDefFoundError|FileNotFoundException.*\.jar/i, {
|
|
63
63
|
severity: "error",
|
|
64
64
|
rule: "classpath",
|
|
65
|
-
message: "
|
|
66
|
-
nextStep: "
|
|
65
|
+
message: "检测到类或 jar 依赖缺失。",
|
|
66
|
+
nextStep: "检查模块依赖、biz/cuslib 部署,以及是否使用了正确产品/版本的 SDK。",
|
|
67
67
|
});
|
|
68
68
|
|
|
69
69
|
pushIfMatch(findings, lines, /DataSet.*closed|ResultSet.*closed|connection.*closed/i, {
|
|
70
70
|
severity: "error",
|
|
71
71
|
rule: "dataset-scope",
|
|
72
|
-
message: "
|
|
73
|
-
nextStep: "
|
|
72
|
+
message: "检测到已关闭的 DataSet/connection 被继续使用。",
|
|
73
|
+
nextStep: "确保 DataSet 处理位于 try-with-resources 内,并处于创建它的事务/资源作用域内。",
|
|
74
74
|
});
|
|
75
75
|
|
|
76
76
|
pushIfMatch(findings, lines, /SQLSyntaxErrorException|PSQLException|syntax error|invalid column|column .* does not exist/i, {
|
|
77
77
|
severity: "error",
|
|
78
78
|
rule: "sql-metadata",
|
|
79
|
-
message: "
|
|
80
|
-
nextStep: "
|
|
79
|
+
message: "检测到 SQL 或元数据不匹配。",
|
|
80
|
+
nextStep: "使用 kd_cosmic_metadata 并设置 sql=true 查证表名、数据库字段、枚举值和 dbName/dbKey。",
|
|
81
81
|
});
|
|
82
82
|
|
|
83
83
|
pushIfMatch(findings, lines, /deadlock|lock wait timeout|could not serialize access|并发|死锁/i, {
|
|
84
84
|
severity: "error",
|
|
85
85
|
rule: "transaction-lock",
|
|
86
|
-
message: "
|
|
87
|
-
nextStep: "
|
|
86
|
+
message: "检测到事务锁或并发问题。",
|
|
87
|
+
nextStep: "检查事务范围、跨库写入、更新顺序,以及外部调用是否放在事务内。",
|
|
88
88
|
});
|
|
89
89
|
|
|
90
90
|
pushIfMatch(findings, lines, /OutOfMemoryError|GC overhead|Java heap space|内存溢出/i, {
|
|
91
91
|
severity: "error",
|
|
92
92
|
rule: "memory",
|
|
93
|
-
message: "
|
|
94
|
-
nextStep: "
|
|
93
|
+
message: "检测到内存压力或 OOM。",
|
|
94
|
+
nextStep: "检查全表查询、无限集合、过深字段路径,以及大 DataSet/物化加载。",
|
|
95
95
|
});
|
|
96
96
|
|
|
97
97
|
pushIfMatch(findings, lines, /StackOverflowError|propertyChanged/i, {
|
|
98
98
|
severity: "warning",
|
|
99
99
|
rule: "event-recursion",
|
|
100
|
-
message: "
|
|
101
|
-
nextStep: "
|
|
100
|
+
message: "可能存在事件递归触发。",
|
|
101
|
+
nextStep: "检查 propertyChanged/setValue 循环,写字段前比较新旧值。",
|
|
102
102
|
});
|
|
103
103
|
|
|
104
104
|
pushIfMatch(findings, lines, /Gradle|Compilation failed|javac|CS\d{4}|MSB\d{4}|BUILD FAILED|BUILD FAILURE/i, {
|
|
105
105
|
severity: "error",
|
|
106
106
|
rule: "build-error",
|
|
107
|
-
message: "
|
|
108
|
-
nextStep: "
|
|
107
|
+
message: "检测到构建或编译错误。",
|
|
108
|
+
nextStep: "使用产品对应的构建输出。Cosmic Java 需查证 SDK 签名;企业版 C# 需查证命名空间和引用。",
|
|
109
109
|
});
|
|
110
110
|
|
|
111
111
|
if (findings.length === 0) {
|
|
112
112
|
findings.push({
|
|
113
113
|
severity: "info",
|
|
114
114
|
rule: "no-known-pattern",
|
|
115
|
-
message: "
|
|
115
|
+
message: "未匹配到已知金蝶调试模式。",
|
|
116
116
|
evidence: "",
|
|
117
|
-
nextStep: "
|
|
117
|
+
nextStep: "请提供更完整的日志、堆栈、产品/版本、目标单据/表单和最近代码改动。",
|
|
118
118
|
});
|
|
119
119
|
}
|
|
120
120
|
|
|
@@ -127,8 +127,8 @@ export function formatDebugFindings(findings: DebugFinding[]): string {
|
|
|
127
127
|
[
|
|
128
128
|
`[${finding.severity}] ${finding.rule}`,
|
|
129
129
|
finding.message,
|
|
130
|
-
finding.evidence ?
|
|
131
|
-
|
|
130
|
+
finding.evidence ? `证据:${finding.evidence}` : undefined,
|
|
131
|
+
`下一步:${finding.nextStep}`,
|
|
132
132
|
]
|
|
133
133
|
.filter(Boolean)
|
|
134
134
|
.join("\n"),
|
|
@@ -138,7 +138,7 @@ export function formatDebugFindings(findings: DebugFinding[]): string {
|
|
|
138
138
|
|
|
139
139
|
export function readDebugInput(cwd: string, text?: string, path?: string): { source: string; text: string } {
|
|
140
140
|
if (text) return { source: "inline", text };
|
|
141
|
-
if (!path) throw new Error("
|
|
141
|
+
if (!path) throw new Error("kd_debug 需要提供 text 或 path。");
|
|
142
142
|
|
|
143
143
|
const fullPath = resolveWorkspacePath(cwd, path);
|
|
144
144
|
return { source: path, text: readFileSync(fullPath, "utf8") };
|
|
@@ -152,39 +152,39 @@ function planJavaBuild(cwd: string, profile: ProductProfile, target?: string): B
|
|
|
152
152
|
const mvnw = join(cwd, "mvnw");
|
|
153
153
|
|
|
154
154
|
if (existsSync(gradlewBat)) {
|
|
155
|
-
return buildPlan(profile, gradlewBat, [task], cwd, "
|
|
155
|
+
return buildPlan(profile, gradlewBat, [task], cwd, "检测到 Cosmic 家族 Java 项目的 Gradle wrapper。");
|
|
156
156
|
}
|
|
157
157
|
if (existsSync(gradlew)) {
|
|
158
|
-
return buildPlan(profile, gradlew, [task], cwd, "
|
|
158
|
+
return buildPlan(profile, gradlew, [task], cwd, "检测到 Cosmic 家族 Java 项目的 Gradle wrapper。");
|
|
159
159
|
}
|
|
160
160
|
if (existsSync(mvnwBat)) {
|
|
161
|
-
return buildPlan(profile, mvnwBat, [target ?? "test"], cwd, "
|
|
161
|
+
return buildPlan(profile, mvnwBat, [target ?? "test"], cwd, "检测到 Cosmic 家族 Java 项目的 Maven wrapper。");
|
|
162
162
|
}
|
|
163
163
|
if (existsSync(mvnw)) {
|
|
164
|
-
return buildPlan(profile, mvnw, [target ?? "test"], cwd, "
|
|
164
|
+
return buildPlan(profile, mvnw, [target ?? "test"], cwd, "检测到 Cosmic 家族 Java 项目的 Maven wrapper。");
|
|
165
165
|
}
|
|
166
166
|
if (existsSync(join(cwd, "build.gradle")) || existsSync(join(cwd, "build.gradle.kts"))) {
|
|
167
|
-
return buildPlan(profile, "gradle", [task], cwd, "
|
|
167
|
+
return buildPlan(profile, "gradle", [task], cwd, "检测到 Gradle 构建文件,但未找到 wrapper。");
|
|
168
168
|
}
|
|
169
169
|
if (existsSync(join(cwd, "pom.xml"))) {
|
|
170
|
-
return buildPlan(profile, "mvn", [target ?? "test"], cwd, "
|
|
170
|
+
return buildPlan(profile, "mvn", [target ?? "test"], cwd, "检测到 Maven pom.xml,但未找到 wrapper。");
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
-
throw new Error("
|
|
173
|
+
throw new Error("未找到 Java 构建入口。期望在工作区根目录看到 gradlew、build.gradle、mvnw 或 pom.xml。");
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
function planCsharpBuild(cwd: string, profile: ProductProfile, target?: string): BuildPlan {
|
|
177
177
|
const explicit = target ? resolveWorkspacePath(cwd, target) : undefined;
|
|
178
178
|
if (explicit && existsSync(explicit)) {
|
|
179
|
-
return buildPlan(profile, "dotnet", ["build", explicit], cwd, "
|
|
179
|
+
return buildPlan(profile, "dotnet", ["build", explicit], cwd, "使用显式指定的 C# 项目或解决方案。");
|
|
180
180
|
}
|
|
181
181
|
|
|
182
182
|
const candidates = readdirSync(cwd).filter((entry) => [".sln", ".csproj"].includes(extname(entry).toLowerCase()));
|
|
183
183
|
if (candidates.length > 0) {
|
|
184
|
-
return buildPlan(profile, "dotnet", ["build", join(cwd, candidates[0])], cwd,
|
|
184
|
+
return buildPlan(profile, "dotnet", ["build", join(cwd, candidates[0])], cwd, `检测到企业版 C# 项目文件 ${candidates[0]}。`);
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
-
throw new Error("
|
|
187
|
+
throw new Error("未找到 C# 构建入口。期望在工作区根目录看到 .sln 或 .csproj,或通过 target 指定路径。");
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
function buildPlan(profile: ProductProfile, executable: string, args: string[], cwd: string, reason: string): BuildPlan {
|
|
@@ -201,7 +201,7 @@ function buildPlan(profile: ProductProfile, executable: string, args: string[],
|
|
|
201
201
|
}
|
|
202
202
|
|
|
203
203
|
function formatBuildPlan(plan: BuildPlan): string {
|
|
204
|
-
return [
|
|
204
|
+
return [`产品:${plan.profile}`, `原因:${plan.reason}`, `命令:${plan.command.display}`].join("\n");
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
function formatArg(value: string): string {
|
|
@@ -46,7 +46,7 @@ export async function inspectSdkSignature(cwd: string, params: SdkSignatureParam
|
|
|
46
46
|
query,
|
|
47
47
|
exitCode: 2,
|
|
48
48
|
stdout: "",
|
|
49
|
-
stderr: "
|
|
49
|
+
stderr: "kd_sdk_signature 需要提供 query 或 className。method 只是在已匹配类/类型内部过滤。",
|
|
50
50
|
sources: [],
|
|
51
51
|
};
|
|
52
52
|
}
|
|
@@ -57,14 +57,14 @@ export async function inspectSdkSignature(cwd: string, params: SdkSignatureParam
|
|
|
57
57
|
|
|
58
58
|
export function formatSdkSignatureResult(result: SdkSignatureResult): string {
|
|
59
59
|
return [
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
result.sources.length ?
|
|
60
|
+
`语言:${result.language}`,
|
|
61
|
+
`查询:${result.query}`,
|
|
62
|
+
`退出码:${result.exitCode}`,
|
|
63
|
+
result.sources.length ? `来源:\n${result.sources.map((source) => `- ${source}`).join("\n")}` : "来源:无",
|
|
64
64
|
result.stdout.trim() ? `\nSTDOUT:\n${result.stdout.trim()}` : undefined,
|
|
65
65
|
result.stderr.trim() ? `\nSTDERR:\n${result.stderr.trim()}` : undefined,
|
|
66
66
|
"",
|
|
67
|
-
"
|
|
67
|
+
"只有退出码为 0 时,才能把该结果作为本地 SDK 证据。失败时,应先使用构建输出或项目 SDK 配置查证,再相信随包知识库。",
|
|
68
68
|
]
|
|
69
69
|
.filter(Boolean)
|
|
70
70
|
.join("\n");
|
|
@@ -79,7 +79,7 @@ async function inspectJavaSignature(cwd: string, params: SdkSignatureParams, que
|
|
|
79
79
|
query,
|
|
80
80
|
exitCode: 2,
|
|
81
81
|
stdout: "",
|
|
82
|
-
stderr: "
|
|
82
|
+
stderr: "当前项目未找到 jar 文件。请先构建/复制依赖,或传入 path=<sdk/lib 目录>。",
|
|
83
83
|
sources: [],
|
|
84
84
|
};
|
|
85
85
|
}
|
|
@@ -91,7 +91,7 @@ async function inspectJavaSignature(cwd: string, params: SdkSignatureParams, que
|
|
|
91
91
|
query,
|
|
92
92
|
exitCode: 1,
|
|
93
93
|
stdout: "",
|
|
94
|
-
stderr:
|
|
94
|
+
stderr: `项目 jar 中未找到匹配 "${query}" 的类。`,
|
|
95
95
|
sources: jars.map((jar) => relativeOrSelf(cwd, jar)).slice(0, 20),
|
|
96
96
|
};
|
|
97
97
|
}
|
|
@@ -136,7 +136,7 @@ async function inspectCsharpSignature(cwd: string, params: SdkSignatureParams, q
|
|
|
136
136
|
query,
|
|
137
137
|
exitCode: 2,
|
|
138
138
|
stdout: "",
|
|
139
|
-
stderr: "
|
|
139
|
+
stderr: "当前项目未找到 dll 文件。请先构建/还原引用,或传入 path=<sdk/bin 目录>。",
|
|
140
140
|
sources: [],
|
|
141
141
|
};
|
|
142
142
|
}
|
|
@@ -180,7 +180,7 @@ async function inspectCsharpSignature(cwd: string, params: SdkSignatureParams, q
|
|
|
180
180
|
query,
|
|
181
181
|
exitCode: stdout.trim() ? 0 : 1,
|
|
182
182
|
stdout,
|
|
183
|
-
stderr: stdout.trim() ? "" :
|
|
183
|
+
stderr: stdout.trim() ? "" : `项目 dll 中未找到匹配 "${query}" 的公开类型。`,
|
|
184
184
|
sources: dlls.map((dll) => relativeOrSelf(cwd, dll)).slice(0, 20),
|
|
185
185
|
};
|
|
186
186
|
} catch (error) {
|