@xdevops/issue-auto-finish 1.0.2 → 1.0.3
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/dist/KnowledgeAnalyzer-EZSJT2MJ.js +13 -0
- package/dist/KnowledgeAnalyzer-EZSJT2MJ.js.map +1 -0
- package/dist/KnowledgeStore-4ROC6F56.js +10 -0
- package/dist/KnowledgeStore-4ROC6F56.js.map +1 -0
- package/dist/ai-runner/AIRunner.d.ts +2 -0
- package/dist/ai-runner/AIRunner.d.ts.map +1 -1
- package/dist/ai-runner/BaseAIRunner.d.ts +9 -0
- package/dist/ai-runner/BaseAIRunner.d.ts.map +1 -1
- package/dist/ai-runner-RGAJPOOW.js +16 -0
- package/dist/ai-runner-RGAJPOOW.js.map +1 -0
- package/dist/analyze-I7UOJB4F.js +72 -0
- package/dist/analyze-I7UOJB4F.js.map +1 -0
- package/dist/chunk-3JUHZGX5.js +171 -0
- package/dist/chunk-3JUHZGX5.js.map +1 -0
- package/dist/chunk-5JYCGAU3.js +318 -0
- package/dist/chunk-5JYCGAU3.js.map +1 -0
- package/dist/chunk-5VUB3UUK.js +643 -0
- package/dist/chunk-5VUB3UUK.js.map +1 -0
- package/dist/{chunk-IDUKWCC2.js → chunk-C6ZJVIPZ.js} +1151 -80
- package/dist/chunk-C6ZJVIPZ.js.map +1 -0
- package/dist/{chunk-OWVT3Z34.js → chunk-JFYAXNNS.js} +121 -31
- package/dist/chunk-JFYAXNNS.js.map +1 -0
- package/dist/chunk-KISVPNSV.js +188 -0
- package/dist/chunk-KISVPNSV.js.map +1 -0
- package/dist/{chunk-I3T573SU.js → chunk-LEQYGOMJ.js} +65 -2
- package/dist/chunk-LEQYGOMJ.js.map +1 -0
- package/dist/{chunk-TBIEB3JY.js → chunk-N5YK6YVI.js} +592 -767
- package/dist/chunk-N5YK6YVI.js.map +1 -0
- package/dist/{chunk-RIUI4ROA.js → chunk-PECYMYAK.js} +2 -2
- package/dist/chunk-SWG2Y7YX.js +410 -0
- package/dist/chunk-SWG2Y7YX.js.map +1 -0
- package/dist/chunk-TZ6C7HL5.js +59 -0
- package/dist/chunk-TZ6C7HL5.js.map +1 -0
- package/dist/cli/commands/analyze.d.ts +8 -0
- package/dist/cli/commands/analyze.d.ts.map +1 -0
- package/dist/cli.js +67 -3
- package/dist/cli.js.map +1 -1
- package/dist/clients/GongfengClient.d.ts +5 -0
- package/dist/clients/GongfengClient.d.ts.map +1 -1
- package/dist/config-RI7NLDXI.js +7 -0
- package/dist/config-RI7NLDXI.js.map +1 -0
- package/dist/config.d.ts +19 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/{doctor-B26Q6JWI.js → doctor-ZPGIBA5N.js} +3 -3
- package/dist/events/EventBus.d.ts +1 -1
- package/dist/events/EventBus.d.ts.map +1 -1
- package/dist/git/GitOperations.d.ts +12 -0
- package/dist/git/GitOperations.d.ts.map +1 -1
- package/dist/i18n/locales/en.d.ts.map +1 -1
- package/dist/i18n/locales/zh-CN.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -5
- package/dist/{init-L3VIWCOV.js → init-LZGCIHE7.js} +8 -4
- package/dist/{init-L3VIWCOV.js.map → init-LZGCIHE7.js.map} +1 -1
- package/dist/knowledge/KnowledgeAnalyzer.d.ts +31 -0
- package/dist/knowledge/KnowledgeAnalyzer.d.ts.map +1 -0
- package/dist/knowledge/KnowledgeDefaults.d.ts +7 -0
- package/dist/knowledge/KnowledgeDefaults.d.ts.map +1 -0
- package/dist/knowledge/KnowledgeEntry.d.ts +30 -0
- package/dist/knowledge/KnowledgeEntry.d.ts.map +1 -0
- package/dist/knowledge/KnowledgeLoader.d.ts +18 -0
- package/dist/knowledge/KnowledgeLoader.d.ts.map +1 -0
- package/dist/knowledge/KnowledgeStore.d.ts +35 -0
- package/dist/knowledge/KnowledgeStore.d.ts.map +1 -0
- package/dist/knowledge/ProjectKnowledge.d.ts +79 -0
- package/dist/knowledge/ProjectKnowledge.d.ts.map +1 -0
- package/dist/knowledge/analyze-prompt.d.ts +2 -0
- package/dist/knowledge/analyze-prompt.d.ts.map +1 -0
- package/dist/knowledge/importers/GongfengExtractor.d.ts +27 -0
- package/dist/knowledge/importers/GongfengExtractor.d.ts.map +1 -0
- package/dist/knowledge/importers/IwikiImporter.d.ts +21 -0
- package/dist/knowledge/importers/IwikiImporter.d.ts.map +1 -0
- package/dist/knowledge/index.d.ts +12 -0
- package/dist/knowledge/index.d.ts.map +1 -0
- package/dist/lib.js +19 -10
- package/dist/orchestrator/PipelineOrchestrator.d.ts +5 -1
- package/dist/orchestrator/PipelineOrchestrator.d.ts.map +1 -1
- package/dist/phases/BasePhase.d.ts.map +1 -1
- package/dist/poller/IssuePoller.d.ts +5 -0
- package/dist/poller/IssuePoller.d.ts.map +1 -1
- package/dist/prompts/chat-templates.d.ts +4 -0
- package/dist/prompts/chat-templates.d.ts.map +1 -0
- package/dist/prompts/templates.d.ts +11 -0
- package/dist/prompts/templates.d.ts.map +1 -1
- package/dist/rules/RuleResolver.d.ts +4 -0
- package/dist/rules/RuleResolver.d.ts.map +1 -1
- package/dist/run.js +11 -5
- package/dist/run.js.map +1 -1
- package/dist/services/ChatService.d.ts +39 -0
- package/dist/services/ChatService.d.ts.map +1 -0
- package/dist/shutdown/ShutdownSignal.d.ts +3 -0
- package/dist/shutdown/ShutdownSignal.d.ts.map +1 -0
- package/dist/{start-TVN4SS6E.js → start-NMQHUKGF.js} +1 -1
- package/dist/tracker/IssueState.d.ts +1 -0
- package/dist/tracker/IssueState.d.ts.map +1 -1
- package/dist/tracker/IssueTracker.d.ts +2 -0
- package/dist/tracker/IssueTracker.d.ts.map +1 -1
- package/dist/updater/AutoUpdater.d.ts +33 -0
- package/dist/updater/AutoUpdater.d.ts.map +1 -0
- package/dist/updater/UpdateExecutor.d.ts +7 -0
- package/dist/updater/UpdateExecutor.d.ts.map +1 -0
- package/dist/updater/VersionChecker.d.ts +22 -0
- package/dist/updater/VersionChecker.d.ts.map +1 -0
- package/dist/web/WebServer.d.ts +4 -0
- package/dist/web/WebServer.d.ts.map +1 -1
- package/dist/web/routes/api.d.ts +4 -0
- package/dist/web/routes/api.d.ts.map +1 -1
- package/dist/web/routes/chat.d.ts +7 -0
- package/dist/web/routes/chat.d.ts.map +1 -0
- package/dist/web/routes/knowledge.d.ts +13 -0
- package/dist/web/routes/knowledge.d.ts.map +1 -0
- package/dist/web/routes/setup.d.ts.map +1 -1
- package/dist/webhook/CommandExecutor.d.ts +4 -0
- package/dist/webhook/CommandExecutor.d.ts.map +1 -1
- package/dist/webhook/CommandParser.d.ts +2 -2
- package/dist/webhook/CommandParser.d.ts.map +1 -1
- package/dist/webhook/WebhookHandler.d.ts +8 -0
- package/dist/webhook/WebhookHandler.d.ts.map +1 -1
- package/dist/webhook/WebhookServer.d.ts +2 -0
- package/dist/webhook/WebhookServer.d.ts.map +1 -1
- package/package.json +4 -2
- package/src/web/frontend/dist/assets/index-AcJ0lPIv.js +67 -0
- package/src/web/frontend/dist/assets/index-BbRt5BAr.css +1 -0
- package/src/web/frontend/dist/index.html +2 -2
- package/dist/chunk-I3T573SU.js.map +0 -1
- package/dist/chunk-IDUKWCC2.js.map +0 -1
- package/dist/chunk-OWVT3Z34.js.map +0 -1
- package/dist/chunk-TBIEB3JY.js.map +0 -1
- package/src/web/frontend/dist/assets/index-CQdlU9PE.js +0 -65
- package/src/web/frontend/dist/assets/index-CgMEkyZJ.css +0 -1
- /package/dist/{chunk-RIUI4ROA.js.map → chunk-PECYMYAK.js.map} +0 -0
- /package/dist/{doctor-B26Q6JWI.js.map → doctor-ZPGIBA5N.js.map} +0 -0
- /package/dist/{start-TVN4SS6E.js.map → start-NMQHUKGF.js.map} +0 -0
|
@@ -0,0 +1,643 @@
|
|
|
1
|
+
import {
|
|
2
|
+
projectKnowledgeToMarkdown
|
|
3
|
+
} from "./chunk-5JYCGAU3.js";
|
|
4
|
+
import {
|
|
5
|
+
logger
|
|
6
|
+
} from "./chunk-TZ6C7HL5.js";
|
|
7
|
+
|
|
8
|
+
// src/knowledge/KnowledgeAnalyzer.ts
|
|
9
|
+
import fs from "fs";
|
|
10
|
+
import path from "path";
|
|
11
|
+
import { readdir, readFile } from "fs/promises";
|
|
12
|
+
import { execFile } from "child_process";
|
|
13
|
+
import { promisify } from "util";
|
|
14
|
+
|
|
15
|
+
// src/knowledge/KnowledgeDefaults.ts
|
|
16
|
+
var KNOWLEDGE_DEFAULTS = {
|
|
17
|
+
version: 1,
|
|
18
|
+
generatedAt: "2024-01-01T00:00:00Z",
|
|
19
|
+
repoPath: "",
|
|
20
|
+
structure: {
|
|
21
|
+
primaryLanguage: "TypeScript",
|
|
22
|
+
frameworks: ["Node.js"],
|
|
23
|
+
isMonorepo: false,
|
|
24
|
+
hasFrontendBackendSplit: true,
|
|
25
|
+
frontendDir: "frontend",
|
|
26
|
+
e2eDir: "frontend/e2e/dynamic",
|
|
27
|
+
e2eTool: "Playwright"
|
|
28
|
+
},
|
|
29
|
+
toolchain: {
|
|
30
|
+
packageManager: "pnpm",
|
|
31
|
+
installCommand: "pnpm install --frozen-lockfile",
|
|
32
|
+
installFallbackCommand: "pnpm install --frozen-lockfile --ignore-scripts",
|
|
33
|
+
lintCommand: "pnpm run lint",
|
|
34
|
+
buildCommand: "pnpm run build",
|
|
35
|
+
testCommand: "pnpm test",
|
|
36
|
+
testFilesCommand: "pnpm test4vscode --files {files}",
|
|
37
|
+
dependencyCheckPath: "node_modules/.bin/eslint"
|
|
38
|
+
},
|
|
39
|
+
codeStyle: {
|
|
40
|
+
indentStyle: "spaces",
|
|
41
|
+
indentSize: 2,
|
|
42
|
+
lineWidth: 120
|
|
43
|
+
},
|
|
44
|
+
businessContext: {
|
|
45
|
+
purpose: "",
|
|
46
|
+
targetUsers: "",
|
|
47
|
+
domain: "",
|
|
48
|
+
coreFeatures: []
|
|
49
|
+
},
|
|
50
|
+
architecture: {
|
|
51
|
+
overview: "",
|
|
52
|
+
keyModules: [],
|
|
53
|
+
dataFlow: "",
|
|
54
|
+
designPatterns: [],
|
|
55
|
+
externalDependencies: []
|
|
56
|
+
},
|
|
57
|
+
domainConcepts: [],
|
|
58
|
+
agentKnowledge: {
|
|
59
|
+
summary: "",
|
|
60
|
+
cursorRules: [],
|
|
61
|
+
conventions: []
|
|
62
|
+
},
|
|
63
|
+
ruleTriggers: [
|
|
64
|
+
{
|
|
65
|
+
filename: "session-rule.mdc",
|
|
66
|
+
keywords: ["Session", "PublishSession", "SessionData", "\u4F1A\u8BDD", "ActivitySession"]
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
filename: "backend-api-implementation.mdc",
|
|
70
|
+
keywords: ["\u65B0\u589E\u63A5\u53E3", "\u6DFB\u52A0\u63A5\u53E3", "\u4FEE\u6539\u63A5\u53E3", "Controller", "ServiceImpl", "\u8DEF\u7531"]
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
filename: "artifact-publish-rule.mdc",
|
|
74
|
+
keywords: ["\u5236\u54C1\u53D1\u5E03", "ArtifactPublish", "lockResource", "unlockResource", "\u53D1\u5E03\u7CFB\u7EDF"]
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
filename: "activity-realization-rule.mdc",
|
|
78
|
+
keywords: ["\u6D3B\u52A8\u5B9E\u73B0", "ActivityRealization", "BaseActivityRealization", "syncExecuteStatus", "queryExec"]
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
filename: "appset.mdc",
|
|
82
|
+
keywords: ["AppSet", "appset", "ComponentInstance", "StorageService", "IDC Set"]
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
filename: "add-artifact-workflow.mdc",
|
|
86
|
+
keywords: ["\u6DFB\u52A0\u5236\u54C1", "\u65B0\u589E\u5236\u54C1", "\u5236\u54C1\u7C7B\u578B", "ArtifactType", "ArtifactTypeId"]
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
filename: "add-appset-api-workflow.mdc",
|
|
90
|
+
keywords: ["AppSet\u63A5\u53E3", "AppSet API", "proto", "protobuf", "devops-contracts"]
|
|
91
|
+
}
|
|
92
|
+
],
|
|
93
|
+
knownIssues: [
|
|
94
|
+
{
|
|
95
|
+
description: "build \u9636\u6BB5 tests/ \u76EE\u5F55\u53EF\u80FD\u51FA\u73B0 TS2307: Cannot find module 'japa' \u6216 'sinon'",
|
|
96
|
+
pattern: "TS2307",
|
|
97
|
+
advice: "\u8FD9\u662F\u6D4B\u8BD5\u6846\u67B6\u7C7B\u578B\u58F0\u660E\u7684\u5DF2\u77E5\u95EE\u9898\uFF0C\u53EF\u4EE5\u5FFD\u7565"
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// src/knowledge/analyze-prompt.ts
|
|
103
|
+
function buildAnalyzePrompt(staticInfo) {
|
|
104
|
+
return `\u4F60\u662F\u4E00\u4E2A\u9879\u76EE\u5206\u6790\u4E13\u5BB6\u3002\u8BF7\u6839\u636E\u4EE5\u4E0B\u6536\u96C6\u5230\u7684\u9879\u76EE\u4FE1\u606F\uFF0C\u6DF1\u5EA6\u5206\u6790\u8BE5\u9879\u76EE\u5E76\u751F\u6210\u7ED3\u6784\u5316\u7684\u77E5\u8BC6\u914D\u7F6E\u3002\u4F60\u9700\u8981\u540C\u65F6\u7406\u89E3\u9879\u76EE\u7684**\u6280\u672F\u5143\u6570\u636E**\u548C**\u4E1A\u52A1\u8BED\u4E49**\u3002
|
|
105
|
+
|
|
106
|
+
## \u6536\u96C6\u5230\u7684\u9879\u76EE\u4FE1\u606F
|
|
107
|
+
|
|
108
|
+
${staticInfo}
|
|
109
|
+
|
|
110
|
+
## \u8F93\u51FA\u8981\u6C42
|
|
111
|
+
|
|
112
|
+
\u8BF7\u4E25\u683C\u6309\u7167\u4EE5\u4E0B JSON \u683C\u5F0F\u8F93\u51FA\uFF0C\u5305\u88F9\u5728 \`\`\`json \u4EE3\u7801\u5757\u4E2D\u3002\u6240\u6709\u5B57\u6BB5\u90FD\u9700\u8981\u6839\u636E\u5B9E\u9645\u5206\u6790\u7ED3\u679C\u586B\u5199\uFF1A
|
|
113
|
+
|
|
114
|
+
\`\`\`json
|
|
115
|
+
{
|
|
116
|
+
"version": 1,
|
|
117
|
+
"generatedAt": "<ISO \u65F6\u95F4\u6233>",
|
|
118
|
+
"repoPath": "<\u9879\u76EE\u8DEF\u5F84>",
|
|
119
|
+
"structure": {
|
|
120
|
+
"primaryLanguage": "<\u4E3B\u8BED\u8A00: TypeScript/JavaScript/Python/Go/Rust/Java \u7B49>",
|
|
121
|
+
"frameworks": ["<\u6846\u67B6\u5217\u8868>"],
|
|
122
|
+
"isMonorepo": false,
|
|
123
|
+
"hasFrontendBackendSplit": false,
|
|
124
|
+
"frontendDir": "<\u524D\u7AEF\u76EE\u5F55\uFF0C\u65E0\u5219\u7701\u7565>",
|
|
125
|
+
"e2eDir": "<E2E \u6D4B\u8BD5\u76EE\u5F55\uFF0C\u65E0\u5219\u7701\u7565>",
|
|
126
|
+
"e2eTool": "<E2E \u5DE5\u5177: Playwright/Cypress/Selenium \u7B49\uFF0C\u65E0\u5219\u7701\u7565>",
|
|
127
|
+
"description": "<\u7B80\u77ED\u9879\u76EE\u63CF\u8FF0>"
|
|
128
|
+
},
|
|
129
|
+
"toolchain": {
|
|
130
|
+
"packageManager": "<\u5305\u7BA1\u7406\u5668: pnpm/npm/yarn/bun/pip/cargo/go \u7B49>",
|
|
131
|
+
"installCommand": "<\u5B89\u88C5\u4F9D\u8D56\u7684\u547D\u4EE4>",
|
|
132
|
+
"installFallbackCommand": "<\u5B89\u88C5\u5931\u8D25\u65F6\u7684\u964D\u7EA7\u547D\u4EE4\uFF0C\u53EF\u9009>",
|
|
133
|
+
"lintCommand": "<lint \u547D\u4EE4\uFF0C\u65E0\u5219\u7701\u7565>",
|
|
134
|
+
"buildCommand": "<build \u547D\u4EE4\uFF0C\u65E0\u5219\u7701\u7565>",
|
|
135
|
+
"testCommand": "<test \u547D\u4EE4\uFF0C\u65E0\u5219\u7701\u7565>",
|
|
136
|
+
"testFilesCommand": "<\u8FD0\u884C\u6307\u5B9A\u6587\u4EF6\u6D4B\u8BD5\u7684\u547D\u4EE4\uFF0C\u7528 {files} \u4F5C\u4E3A\u5360\u4F4D\u7B26\uFF0C\u65E0\u5219\u7701\u7565>",
|
|
137
|
+
"dependencyCheckPath": "<\u7528\u4E8E\u68C0\u67E5\u4F9D\u8D56\u662F\u5426\u5B89\u88C5\u5B8C\u6210\u7684\u6587\u4EF6\u8DEF\u5F84\uFF0C\u5982 node_modules/.bin/eslint>"
|
|
138
|
+
},
|
|
139
|
+
"codeStyle": {
|
|
140
|
+
"indentStyle": "spaces",
|
|
141
|
+
"indentSize": 2,
|
|
142
|
+
"lineWidth": 120,
|
|
143
|
+
"additionalRules": ["<\u989D\u5916\u4EE3\u7801\u89C4\u8303\u8BF4\u660E>"]
|
|
144
|
+
},
|
|
145
|
+
"businessContext": {
|
|
146
|
+
"purpose": "<\u9879\u76EE\u505A\u4EC0\u4E48\u3001\u89E3\u51B3\u4EC0\u4E48\u95EE\u9898\uFF0C\u7528 2-3 \u53E5\u8BDD\u8BF4\u6E05\u695A>",
|
|
147
|
+
"targetUsers": "<\u76EE\u6807\u7528\u6237\u7FA4\u4F53\u548C\u4F7F\u7528\u573A\u666F>",
|
|
148
|
+
"domain": "<\u4E1A\u52A1\u9886\u57DF\uFF0C\u5982 DevOps\u3001\u7535\u5546\u3001\u91D1\u878D\u3001\u793E\u4EA4\u3001\u6559\u80B2\u7B49>",
|
|
149
|
+
"coreFeatures": ["<\u6838\u5FC3\u529F\u80FD\u5217\u8868\uFF0C\u6BCF\u6761\u7528\u4E00\u53E5\u8BDD\u63CF\u8FF0>"]
|
|
150
|
+
},
|
|
151
|
+
"architecture": {
|
|
152
|
+
"overview": "<\u67B6\u6784\u6982\u8FF0\uFF0C\u63CF\u8FF0\u7CFB\u7EDF\u7684\u6574\u4F53\u7EC4\u7EC7\u65B9\u5F0F\u3001\u5206\u5C42\u7ED3\u6784\u3001\u6838\u5FC3\u6D41\u8F6C\u8DEF\u5F84\uFF0C1-2 \u6BB5>",
|
|
153
|
+
"keyModules": [
|
|
154
|
+
{
|
|
155
|
+
"name": "<\u6A21\u5757\u540D>",
|
|
156
|
+
"path": "<\u5BF9\u5E94\u7684\u76EE\u5F55/\u6587\u4EF6\u8DEF\u5F84>",
|
|
157
|
+
"responsibility": "<\u8BE5\u6A21\u5757\u7684\u804C\u8D23\uFF0C\u7528\u4E00\u53E5\u8BDD\u8BF4\u6E05\u695A>"
|
|
158
|
+
}
|
|
159
|
+
],
|
|
160
|
+
"dataFlow": "<\u6838\u5FC3\u6570\u636E\u6D41\u63CF\u8FF0\uFF1A\u6570\u636E\u4ECE\u54EA\u91CC\u6765\u3001\u7ECF\u8FC7\u54EA\u4E9B\u6A21\u5757\u5904\u7406\u3001\u6700\u7EC8\u5230\u54EA\u91CC>",
|
|
161
|
+
"designPatterns": ["<\u4F7F\u7528\u7684\u8BBE\u8BA1\u6A21\u5F0F\u5217\u8868\uFF0C\u5982\u7B56\u7565\u6A21\u5F0F\u3001\u89C2\u5BDF\u8005\u6A21\u5F0F\u7B49>"],
|
|
162
|
+
"externalDependencies": ["<\u5173\u952E\u5916\u90E8\u4F9D\u8D56/\u670D\u52A1\uFF0C\u5982\u6570\u636E\u5E93\u3001\u6D88\u606F\u961F\u5217\u3001\u7B2C\u4E09\u65B9 API \u7B49>"]
|
|
163
|
+
},
|
|
164
|
+
"domainConcepts": [
|
|
165
|
+
{
|
|
166
|
+
"term": "<\u4E1A\u52A1\u672F\u8BED>",
|
|
167
|
+
"definition": "<\u8BE5\u672F\u8BED\u5728\u6B64\u9879\u76EE\u4E2D\u7684\u542B\u4E49>"
|
|
168
|
+
}
|
|
169
|
+
],
|
|
170
|
+
"agentKnowledge": {
|
|
171
|
+
"summary": "<Agent \u77E5\u8BC6\u6C89\u6DC0\u7684\u6574\u4F53\u6458\u8981\uFF1A\u6709\u54EA\u4E9B\u89C4\u5219\u6587\u4EF6\u3001CLAUDE.md \u5305\u542B\u4EC0\u4E48\u4FE1\u606F\u3001\u6574\u4F53\u5BF9 AI \u534F\u4F5C\u6709\u4EC0\u4E48\u6307\u5BFC>",
|
|
172
|
+
"cursorRules": [
|
|
173
|
+
{
|
|
174
|
+
"filename": "<.mdc \u6587\u4EF6\u540D>",
|
|
175
|
+
"purpose": "<\u8BE5\u89C4\u5219\u7684\u76EE\u7684\u548C\u9002\u7528\u573A\u666F>",
|
|
176
|
+
"keyPoints": ["<\u8BE5\u89C4\u5219\u4E2D\u6700\u91CD\u8981\u7684\u8981\u70B9\uFF0C\u6BCF\u6761\u7528\u4E00\u53E5\u8BDD>"]
|
|
177
|
+
}
|
|
178
|
+
],
|
|
179
|
+
"claudeMdSummary": "<CLAUDE.md \u7684\u6838\u5FC3\u5185\u5BB9\u6458\u8981\uFF1A\u9879\u76EE\u6982\u8FF0\u3001\u67B6\u6784\u3001\u5F00\u53D1\u7EA6\u5B9A\u3001\u6269\u5C55\u6307\u5357\u7B49\u5173\u952E\u4FE1\u606F>",
|
|
180
|
+
"conventions": ["<\u4ECE agent \u77E5\u8BC6\u4E2D\u63D0\u70BC\u7684\u5F00\u53D1\u7EA6\u5B9A\uFF0C\u5982 ESM \u5BFC\u5165\u89C4\u8303\u3001\u547D\u540D\u89C4\u8303\u3001\u6D4B\u8BD5\u89C4\u8303\u7B49>"]
|
|
181
|
+
},
|
|
182
|
+
"ruleTriggers": [
|
|
183
|
+
{
|
|
184
|
+
"filename": "<.mdc \u6587\u4EF6\u540D>",
|
|
185
|
+
"keywords": ["<\u89E6\u53D1\u5173\u952E\u8BCD\u5217\u8868\uFF0C\u6BCF\u4E2A\u6587\u4EF6 5-15 \u4E2A>"],
|
|
186
|
+
"description": "<\u89C4\u5219\u7B80\u77ED\u63CF\u8FF0>"
|
|
187
|
+
}
|
|
188
|
+
],
|
|
189
|
+
"knownIssues": [
|
|
190
|
+
{
|
|
191
|
+
"description": "<\u5DF2\u77E5\u95EE\u9898\u63CF\u8FF0>",
|
|
192
|
+
"pattern": "<\u9519\u8BEF\u5339\u914D\u6A21\u5F0F\uFF0C\u53EF\u9009>",
|
|
193
|
+
"advice": "<\u5904\u7406\u5EFA\u8BAE>"
|
|
194
|
+
}
|
|
195
|
+
]
|
|
196
|
+
}
|
|
197
|
+
\`\`\`
|
|
198
|
+
|
|
199
|
+
## \u5206\u6790\u6307\u5BFC
|
|
200
|
+
|
|
201
|
+
### \u6280\u672F\u5143\u6570\u636E
|
|
202
|
+
1. **\u5DE5\u5177\u94FE\u63A8\u65AD**\uFF1A\u4ECE package.json \u7684 scripts \u5B57\u6BB5\u63A8\u65AD lint/build/test \u547D\u4EE4\uFF1B\u4ECE lockfile \u7C7B\u578B\u5224\u65AD\u5305\u7BA1\u7406\u5668
|
|
203
|
+
2. **\u4EE3\u7801\u89C4\u8303**\uFF1A\u4ECE .editorconfig \u63A8\u65AD\u7F29\u8FDB\u548C\u884C\u5BBD\uFF1B\u4ECE ESLint/Prettier \u914D\u7F6E\u63D0\u53D6\u989D\u5916\u89C4\u5219
|
|
204
|
+
3. **Monorepo \u68C0\u6D4B**\uFF1A\u68C0\u67E5 pnpm-workspace.yaml\u3001lerna.json\u3001nx.json \u7B49\u6587\u4EF6
|
|
205
|
+
4. **\u524D\u540E\u7AEF\u5206\u79BB**\uFF1A\u6839\u636E\u76EE\u5F55\u7ED3\u6784\u5224\u65AD\u662F\u5426\u6709\u524D\u540E\u7AEF\u5206\u79BB
|
|
206
|
+
|
|
207
|
+
### \u4E1A\u52A1\u7406\u89E3\uFF08\u91CD\u70B9\uFF09
|
|
208
|
+
5. **\u4E1A\u52A1\u76EE\u7684**\uFF1A\u4ECE CLAUDE.md\u3001README.md\u3001\u5165\u53E3\u6587\u4EF6\u4E2D\u7406\u89E3\u9879\u76EE\u89E3\u51B3\u4EC0\u4E48\u95EE\u9898\u3001\u4E3A\u8C01\u670D\u52A1\u3002businessContext.purpose \u5E94\u8BE5\u8BA9\u4E00\u4E2A\u5B8C\u5168\u4E0D\u4E86\u89E3\u9879\u76EE\u7684\u4EBA\u8BFB\u5B8C\u5C31\u80FD\u7406\u89E3\u9879\u76EE\u505A\u4EC0\u4E48
|
|
209
|
+
6. **\u67B6\u6784\u5206\u6790**\uFF1A\u4ECE\u76EE\u5F55\u7ED3\u6784\u3001CLAUDE.md\u3001.mdc \u89C4\u5219\u4E2D\u63D0\u53D6\u5173\u952E\u6A21\u5757\u548C\u804C\u8D23\u5212\u5206\u3002keyModules \u5E94\u8986\u76D6\u6240\u6709\u91CD\u8981\u7684\u6E90\u7801\u76EE\u5F55\u3002overview \u5E94\u63CF\u8FF0\u7CFB\u7EDF\u7684\u6574\u4F53\u67B6\u6784\u800C\u975E\u7B80\u5355\u7F57\u5217\u6A21\u5757
|
|
210
|
+
7. **\u6838\u5FC3\u6570\u636E\u6D41**\uFF1A\u63CF\u8FF0\u7CFB\u7EDF\u4E2D\u6700\u91CD\u8981\u7684\u6570\u636E\u6D41\u8F6C\u8DEF\u5F84\uFF0C\u4F8B\u5982"\u7528\u6237\u8BF7\u6C42 \u2192 \u63A7\u5236\u5668 \u2192 \u670D\u52A1\u5C42 \u2192 \u6570\u636E\u5E93"
|
|
211
|
+
8. **\u9886\u57DF\u6982\u5FF5**\uFF1A\u4ECE CLAUDE.md\u3001.mdc \u89C4\u5219\u3001\u4EE3\u7801\u4E2D\u63D0\u53D6\u4E1A\u52A1\u672F\u8BED\uFF08\u5305\u62EC\u4E2D\u82F1\u6587\u672F\u8BED\uFF09\uFF0C\u5E76\u7ED9\u51FA\u5728\u6B64\u9879\u76EE\u4E0A\u4E0B\u6587\u4E2D\u7684\u51C6\u786E\u5B9A\u4E49\u3002\u4F8B\u5982 "worktree" \u5728\u67D0\u4E2A\u9879\u76EE\u4E2D\u6307 "git worktree \u9694\u79BB\u7684\u72EC\u7ACB\u5DE5\u4F5C\u76EE\u5F55"
|
|
212
|
+
9. **\u5916\u90E8\u4F9D\u8D56**\uFF1A\u8BC6\u522B\u9879\u76EE\u4F9D\u8D56\u7684\u5916\u90E8\u7CFB\u7EDF\u548C\u670D\u52A1\uFF08\u4E0D\u662F npm \u5305\uFF0C\u800C\u662F\u8FD0\u884C\u65F6\u4F9D\u8D56\u7684\u5916\u90E8\u7CFB\u7EDF\u5982 GitLab API\u3001\u6570\u636E\u5E93\u3001\u6D88\u606F\u961F\u5217\u7B49\uFF09
|
|
213
|
+
|
|
214
|
+
### Agent \u77E5\u8BC6\u6DF1\u5EA6\u5206\u6790\uFF08\u91CD\u70B9\uFF09
|
|
215
|
+
10. **\u89C4\u5219\u7406\u89E3**\uFF1A\u6DF1\u5EA6\u9605\u8BFB\u6BCF\u4E2A .mdc \u6587\u4EF6\u548C CLAUDE.md \u7684\u5B8C\u6574\u5185\u5BB9\u3002\u4E0D\u662F\u53EA\u63D0\u53D6\u5173\u952E\u8BCD\uFF0C\u800C\u662F\u7406\u89E3\u6BCF\u6761\u89C4\u5219\u7684**\u76EE\u7684**\uFF08\u4E3A\u4EC0\u4E48\u9700\u8981\u8FD9\u6761\u89C4\u5219\uFF09\u3001**\u9002\u7528\u573A\u666F**\uFF08\u4EC0\u4E48\u65F6\u5019\u89E6\u53D1\uFF09\u3001**\u6838\u5FC3\u8981\u70B9**\uFF08\u6700\u91CD\u8981\u7684\u7EA6\u675F\u548C\u6307\u5BFC\uFF09
|
|
216
|
+
11. **\u5F00\u53D1\u7EA6\u5B9A\u63D0\u70BC**\uFF1A\u4ECE CLAUDE.md \u548C .mdc \u89C4\u5219\u4E2D\u63D0\u70BC\u51FA\u5BF9\u65E5\u5E38\u5F00\u53D1\u6700\u91CD\u8981\u7684\u7EA6\u5B9A\uFF08\u5982\u6587\u4EF6\u547D\u540D\u89C4\u8303\u3001\u5BFC\u5165\u89C4\u8303\u3001\u6D4B\u8BD5\u89C4\u8303\u3001\u63D0\u4EA4\u89C4\u8303\u7B49\uFF09\uFF0C\u653E\u5165 agentKnowledge.conventions
|
|
217
|
+
12. **\u89C4\u5219\u89E6\u53D1\u5668**\uFF1A\u9605\u8BFB\u6BCF\u4E2A .mdc \u6587\u4EF6\u7684\u5185\u5BB9\uFF0C\u4ECE\u4E2D\u63D0\u53D6 5-15 \u4E2A\u4E1A\u52A1\u6982\u5FF5\u5173\u952E\u8BCD\u4F5C\u4E3A\u89E6\u53D1\u5668\u3002\u5173\u952E\u8BCD\u5E94\u5305\u62EC\u7C7B\u540D\u3001\u4E1A\u52A1\u672F\u8BED\u3001\u4E2D\u6587\u6982\u5FF5\u7B49
|
|
218
|
+
|
|
219
|
+
### \u95EE\u9898\u8BC6\u522B
|
|
220
|
+
13. **\u5DF2\u77E5\u95EE\u9898**\uFF1A\u8BC6\u522B\u9879\u76EE\u4E2D\u53EF\u80FD\u9047\u5230\u7684\u6784\u5EFA/\u6D4B\u8BD5\u95EE\u9898\uFF08\u5982\u5DF2\u77E5\u7684\u7C7B\u578B\u58F0\u660E\u7F3A\u5931\u3001\u7279\u5B9A\u6D4B\u8BD5\u6846\u67B6\u95EE\u9898\u7B49\uFF09
|
|
221
|
+
|
|
222
|
+
\u53EA\u8F93\u51FA JSON\uFF0C\u4E0D\u8981\u6DFB\u52A0\u5176\u4ED6\u8BF4\u660E\u6587\u5B57\u3002`;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// src/knowledge/KnowledgeAnalyzer.ts
|
|
226
|
+
var execFileAsync = promisify(execFile);
|
|
227
|
+
var logger2 = logger.child("KnowledgeAnalyzer");
|
|
228
|
+
async function collectSkillFiles(dir, basePath = "") {
|
|
229
|
+
const results = [];
|
|
230
|
+
try {
|
|
231
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
232
|
+
for (const entry of entries) {
|
|
233
|
+
const rel = basePath ? `${basePath}/${entry.name}` : entry.name;
|
|
234
|
+
if (entry.isDirectory()) {
|
|
235
|
+
const sub = await collectSkillFiles(path.join(dir, entry.name), rel);
|
|
236
|
+
results.push(...sub);
|
|
237
|
+
} else if (entry.name === "SKILL.md") {
|
|
238
|
+
const content = await readFile(path.join(dir, entry.name), "utf-8");
|
|
239
|
+
results.push({ relativePath: rel, content });
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
} catch {
|
|
243
|
+
}
|
|
244
|
+
return results;
|
|
245
|
+
}
|
|
246
|
+
async function collectStaticInfo(workDir) {
|
|
247
|
+
const sections = [];
|
|
248
|
+
const pkgPath = path.join(workDir, "package.json");
|
|
249
|
+
if (fs.existsSync(pkgPath)) {
|
|
250
|
+
try {
|
|
251
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
252
|
+
sections.push("### package.json");
|
|
253
|
+
sections.push("```json");
|
|
254
|
+
sections.push(JSON.stringify({
|
|
255
|
+
name: pkg.name,
|
|
256
|
+
scripts: pkg.scripts,
|
|
257
|
+
dependencies: Object.keys(pkg.dependencies ?? {}),
|
|
258
|
+
devDependencies: Object.keys(pkg.devDependencies ?? {})
|
|
259
|
+
}, null, 2));
|
|
260
|
+
sections.push("```");
|
|
261
|
+
} catch {
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
const lockfiles = ["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lockb"];
|
|
265
|
+
const foundLockfile = lockfiles.find((f) => fs.existsSync(path.join(workDir, f)));
|
|
266
|
+
if (foundLockfile) {
|
|
267
|
+
sections.push(`### Lockfile: ${foundLockfile}`);
|
|
268
|
+
}
|
|
269
|
+
for (const configFile of ["pyproject.toml", "Cargo.toml", "go.mod", "Makefile"]) {
|
|
270
|
+
const cfgPath = path.join(workDir, configFile);
|
|
271
|
+
if (fs.existsSync(cfgPath)) {
|
|
272
|
+
try {
|
|
273
|
+
const content = fs.readFileSync(cfgPath, "utf-8");
|
|
274
|
+
sections.push(`### ${configFile}`);
|
|
275
|
+
sections.push("```");
|
|
276
|
+
sections.push(content.slice(0, 3e3));
|
|
277
|
+
sections.push("```");
|
|
278
|
+
} catch {
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
const editorConfigPath = path.join(workDir, ".editorconfig");
|
|
283
|
+
if (fs.existsSync(editorConfigPath)) {
|
|
284
|
+
try {
|
|
285
|
+
const content = fs.readFileSync(editorConfigPath, "utf-8");
|
|
286
|
+
sections.push("### .editorconfig");
|
|
287
|
+
sections.push("```");
|
|
288
|
+
sections.push(content);
|
|
289
|
+
sections.push("```");
|
|
290
|
+
} catch {
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
const styleConfigs = [
|
|
294
|
+
".eslintrc.json",
|
|
295
|
+
".eslintrc.js",
|
|
296
|
+
".eslintrc.cjs",
|
|
297
|
+
"eslint.config.js",
|
|
298
|
+
"eslint.config.mjs",
|
|
299
|
+
".prettierrc",
|
|
300
|
+
".prettierrc.json",
|
|
301
|
+
"prettier.config.js"
|
|
302
|
+
];
|
|
303
|
+
for (const cfg of styleConfigs) {
|
|
304
|
+
const cfgPath = path.join(workDir, cfg);
|
|
305
|
+
if (fs.existsSync(cfgPath)) {
|
|
306
|
+
try {
|
|
307
|
+
const content = fs.readFileSync(cfgPath, "utf-8");
|
|
308
|
+
sections.push(`### ${cfg}`);
|
|
309
|
+
sections.push("```");
|
|
310
|
+
sections.push(content.slice(0, 2e3));
|
|
311
|
+
sections.push("```");
|
|
312
|
+
} catch {
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
const monoRepoFiles = ["pnpm-workspace.yaml", "lerna.json", "nx.json"];
|
|
317
|
+
for (const mf of monoRepoFiles) {
|
|
318
|
+
const mfPath = path.join(workDir, mf);
|
|
319
|
+
if (fs.existsSync(mfPath)) {
|
|
320
|
+
try {
|
|
321
|
+
const content = fs.readFileSync(mfPath, "utf-8");
|
|
322
|
+
sections.push(`### ${mf} (monorepo marker)`);
|
|
323
|
+
sections.push("```");
|
|
324
|
+
sections.push(content.slice(0, 1e3));
|
|
325
|
+
sections.push("```");
|
|
326
|
+
} catch {
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
const rulesDir = path.join(workDir, ".cursor", "rules");
|
|
331
|
+
if (fs.existsSync(rulesDir)) {
|
|
332
|
+
try {
|
|
333
|
+
const files = await readdir(rulesDir);
|
|
334
|
+
const mdcFiles = files.filter((f) => f.endsWith(".mdc"));
|
|
335
|
+
for (const mdc of mdcFiles) {
|
|
336
|
+
try {
|
|
337
|
+
const content = await readFile(path.join(rulesDir, mdc), "utf-8");
|
|
338
|
+
sections.push(`### .cursor/rules/${mdc}`);
|
|
339
|
+
sections.push("```");
|
|
340
|
+
sections.push(content);
|
|
341
|
+
sections.push("```");
|
|
342
|
+
} catch {
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
} catch {
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
const legacyRulesPath = path.join(workDir, ".cursorrules");
|
|
349
|
+
if (fs.existsSync(legacyRulesPath)) {
|
|
350
|
+
try {
|
|
351
|
+
const content = fs.readFileSync(legacyRulesPath, "utf-8");
|
|
352
|
+
sections.push("### .cursorrules (legacy)");
|
|
353
|
+
sections.push("```");
|
|
354
|
+
sections.push(content.slice(0, 1e4));
|
|
355
|
+
if (content.length > 1e4) sections.push("... (truncated)");
|
|
356
|
+
sections.push("```");
|
|
357
|
+
} catch {
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
const claudeMdPath = path.join(workDir, "CLAUDE.md");
|
|
361
|
+
if (fs.existsSync(claudeMdPath)) {
|
|
362
|
+
try {
|
|
363
|
+
const content = fs.readFileSync(claudeMdPath, "utf-8");
|
|
364
|
+
sections.push("### CLAUDE.md");
|
|
365
|
+
sections.push("```markdown");
|
|
366
|
+
sections.push(content);
|
|
367
|
+
sections.push("```");
|
|
368
|
+
} catch {
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
const agentsMdPath = path.join(workDir, "AGENTS.md");
|
|
372
|
+
if (fs.existsSync(agentsMdPath)) {
|
|
373
|
+
try {
|
|
374
|
+
const content = fs.readFileSync(agentsMdPath, "utf-8");
|
|
375
|
+
sections.push("### AGENTS.md");
|
|
376
|
+
sections.push("```markdown");
|
|
377
|
+
sections.push(content);
|
|
378
|
+
sections.push("```");
|
|
379
|
+
} catch {
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
const agentsDir = path.join(workDir, ".agents");
|
|
383
|
+
if (fs.existsSync(agentsDir)) {
|
|
384
|
+
try {
|
|
385
|
+
const skillFiles = await collectSkillFiles(agentsDir);
|
|
386
|
+
for (const { relativePath, content } of skillFiles) {
|
|
387
|
+
sections.push(`### .agents/${relativePath}`);
|
|
388
|
+
sections.push("```markdown");
|
|
389
|
+
sections.push(content.slice(0, 5e3));
|
|
390
|
+
if (content.length > 5e3) sections.push("... (truncated)");
|
|
391
|
+
sections.push("```");
|
|
392
|
+
}
|
|
393
|
+
} catch {
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
const claudeDir = path.join(workDir, ".claude");
|
|
397
|
+
if (fs.existsSync(claudeDir)) {
|
|
398
|
+
try {
|
|
399
|
+
const claudeFiles = await readdir(claudeDir);
|
|
400
|
+
for (const cf of claudeFiles.filter((f) => f.endsWith(".json") || f.endsWith(".md"))) {
|
|
401
|
+
try {
|
|
402
|
+
const content = await readFile(path.join(claudeDir, cf), "utf-8");
|
|
403
|
+
sections.push(`### .claude/${cf}`);
|
|
404
|
+
sections.push("```");
|
|
405
|
+
sections.push(content.slice(0, 3e3));
|
|
406
|
+
if (content.length > 3e3) sections.push("... (truncated)");
|
|
407
|
+
sections.push("```");
|
|
408
|
+
} catch {
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
} catch {
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
const readmePath = path.join(workDir, "README.md");
|
|
415
|
+
if (fs.existsSync(readmePath)) {
|
|
416
|
+
try {
|
|
417
|
+
const content = fs.readFileSync(readmePath, "utf-8");
|
|
418
|
+
sections.push("### README.md");
|
|
419
|
+
sections.push("```markdown");
|
|
420
|
+
sections.push(content.slice(0, 15e3));
|
|
421
|
+
if (content.length > 15e3) sections.push("... (truncated)");
|
|
422
|
+
sections.push("```");
|
|
423
|
+
} catch {
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
const docsDir = path.join(workDir, "docs");
|
|
427
|
+
if (fs.existsSync(docsDir)) {
|
|
428
|
+
try {
|
|
429
|
+
const docFiles = await readdir(docsDir);
|
|
430
|
+
const mdFiles = docFiles.filter((f) => f.endsWith(".md"));
|
|
431
|
+
if (mdFiles.length > 0) {
|
|
432
|
+
sections.push("### docs/ directory");
|
|
433
|
+
for (const doc of mdFiles.slice(0, 10)) {
|
|
434
|
+
try {
|
|
435
|
+
const content = await readFile(path.join(docsDir, doc), "utf-8");
|
|
436
|
+
const firstLine = content.split("\n").find((l) => l.startsWith("#"))?.replace(/^#+\s*/, "") || doc;
|
|
437
|
+
sections.push(`- ${doc}: ${firstLine}`);
|
|
438
|
+
} catch {
|
|
439
|
+
sections.push(`- ${doc}`);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
} catch {
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
const entryFiles = ["src/index.ts", "src/main.ts", "src/app.ts", "src/index.js", "src/main.js", "src/app.js"];
|
|
447
|
+
for (const entry of entryFiles) {
|
|
448
|
+
const entryPath = path.join(workDir, entry);
|
|
449
|
+
if (fs.existsSync(entryPath)) {
|
|
450
|
+
try {
|
|
451
|
+
const content = fs.readFileSync(entryPath, "utf-8");
|
|
452
|
+
const lines = content.split("\n");
|
|
453
|
+
sections.push(`### ${entry} (entry point)`);
|
|
454
|
+
sections.push("```");
|
|
455
|
+
sections.push(lines.slice(0, 100).join("\n"));
|
|
456
|
+
if (lines.length > 100) sections.push("... (truncated)");
|
|
457
|
+
sections.push("```");
|
|
458
|
+
} catch {
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
try {
|
|
463
|
+
const { stdout } = await execFileAsync("find", [
|
|
464
|
+
workDir,
|
|
465
|
+
"-maxdepth",
|
|
466
|
+
"2",
|
|
467
|
+
"-not",
|
|
468
|
+
"-path",
|
|
469
|
+
"*/node_modules/*",
|
|
470
|
+
"-not",
|
|
471
|
+
"-path",
|
|
472
|
+
"*/.git/*",
|
|
473
|
+
"-not",
|
|
474
|
+
"-path",
|
|
475
|
+
"*/dist/*"
|
|
476
|
+
], { timeout: 1e4 });
|
|
477
|
+
const tree = stdout.split("\n").map((p) => p.replace(workDir, ".")).filter((p) => p && p !== ".").sort().slice(0, 100).join("\n");
|
|
478
|
+
sections.push("### Directory tree (depth=2)");
|
|
479
|
+
sections.push("```");
|
|
480
|
+
sections.push(tree);
|
|
481
|
+
sections.push("```");
|
|
482
|
+
} catch {
|
|
483
|
+
}
|
|
484
|
+
return sections.join("\n\n");
|
|
485
|
+
}
|
|
486
|
+
function parseJsonFromOutput(output) {
|
|
487
|
+
const jsonBlockMatch = output.match(/```json\s*\n([\s\S]*?)```/);
|
|
488
|
+
if (jsonBlockMatch) {
|
|
489
|
+
try {
|
|
490
|
+
return JSON.parse(jsonBlockMatch[1].trim());
|
|
491
|
+
} catch {
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
try {
|
|
495
|
+
return JSON.parse(output.trim());
|
|
496
|
+
} catch {
|
|
497
|
+
}
|
|
498
|
+
return null;
|
|
499
|
+
}
|
|
500
|
+
function deepMergeKnowledge(defaults, overrides) {
|
|
501
|
+
const result = { ...defaults };
|
|
502
|
+
for (const key of Object.keys(overrides)) {
|
|
503
|
+
const val = overrides[key];
|
|
504
|
+
if (val !== null && val !== void 0) {
|
|
505
|
+
if (typeof val === "object" && !Array.isArray(val) && typeof result[key] === "object" && !Array.isArray(result[key])) {
|
|
506
|
+
result[key] = deepMergeKnowledge(result[key], val);
|
|
507
|
+
} else {
|
|
508
|
+
result[key] = val;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
return result;
|
|
513
|
+
}
|
|
514
|
+
async function analyze(options) {
|
|
515
|
+
const { workDir, aiRunner, timeoutMs = 6e5, outputPath } = options;
|
|
516
|
+
logger2.info("Collecting static project info", { workDir });
|
|
517
|
+
const staticInfo = await collectStaticInfo(workDir);
|
|
518
|
+
logger2.info("Running AI analysis");
|
|
519
|
+
const prompt = buildAnalyzePrompt(staticInfo);
|
|
520
|
+
const result = await aiRunner.run({
|
|
521
|
+
prompt,
|
|
522
|
+
workDir,
|
|
523
|
+
timeoutMs
|
|
524
|
+
});
|
|
525
|
+
if (!result.success) {
|
|
526
|
+
throw new Error(`AI analysis failed: ${result.output.slice(0, 500)}`);
|
|
527
|
+
}
|
|
528
|
+
const parsed = parseJsonFromOutput(result.output);
|
|
529
|
+
if (!parsed) {
|
|
530
|
+
throw new Error(`Failed to parse AI output as JSON. Raw output:
|
|
531
|
+
${result.output.slice(0, 1e3)}`);
|
|
532
|
+
}
|
|
533
|
+
const merged = deepMergeKnowledge(
|
|
534
|
+
KNOWLEDGE_DEFAULTS,
|
|
535
|
+
parsed
|
|
536
|
+
);
|
|
537
|
+
merged.version = 1;
|
|
538
|
+
merged.generatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
539
|
+
merged.repoPath = workDir;
|
|
540
|
+
const savePath = outputPath ?? path.join(workDir, "knowledge.json");
|
|
541
|
+
fs.writeFileSync(savePath, JSON.stringify(merged, null, 2), "utf-8");
|
|
542
|
+
logger2.info("Knowledge saved", { path: savePath });
|
|
543
|
+
return merged;
|
|
544
|
+
}
|
|
545
|
+
async function analyzeIncremental(options) {
|
|
546
|
+
const { workDir, aiRunner, store, timeoutMs = 6e5 } = options;
|
|
547
|
+
const stats = store.getStats();
|
|
548
|
+
const since = stats.lastAnalyzedAt;
|
|
549
|
+
let changedFiles = [];
|
|
550
|
+
if (since) {
|
|
551
|
+
try {
|
|
552
|
+
const { stdout } = await execFileAsync("git", [
|
|
553
|
+
"diff",
|
|
554
|
+
"--name-only",
|
|
555
|
+
"--diff-filter=ACMR",
|
|
556
|
+
"--since=" + since,
|
|
557
|
+
"HEAD"
|
|
558
|
+
], { cwd: workDir, timeout: 1e4 });
|
|
559
|
+
changedFiles = stdout.trim().split("\n").filter(Boolean);
|
|
560
|
+
} catch {
|
|
561
|
+
logger2.warn("git diff failed, falling back to full analysis");
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
if (since && changedFiles.length === 0) {
|
|
565
|
+
logger2.info("No changes detected since last analysis, skipping");
|
|
566
|
+
return null;
|
|
567
|
+
}
|
|
568
|
+
logger2.info("Running incremental analysis", { changedFiles: changedFiles.length });
|
|
569
|
+
const staticInfo = await collectStaticInfo(workDir);
|
|
570
|
+
const existingMeta = store.getProjectMeta();
|
|
571
|
+
let prompt;
|
|
572
|
+
if (existingMeta && changedFiles.length > 0) {
|
|
573
|
+
prompt = buildIncrementalPrompt(staticInfo, existingMeta.content, changedFiles);
|
|
574
|
+
} else {
|
|
575
|
+
prompt = buildAnalyzePrompt(staticInfo);
|
|
576
|
+
}
|
|
577
|
+
const result = await aiRunner.run({ prompt, workDir, timeoutMs });
|
|
578
|
+
if (!result.success) {
|
|
579
|
+
throw new Error("AI analysis failed: " + result.output.slice(0, 500));
|
|
580
|
+
}
|
|
581
|
+
const parsed = parseJsonFromOutput(result.output);
|
|
582
|
+
if (!parsed) {
|
|
583
|
+
throw new Error("Failed to parse AI output as JSON");
|
|
584
|
+
}
|
|
585
|
+
const merged = deepMergeKnowledge(
|
|
586
|
+
KNOWLEDGE_DEFAULTS,
|
|
587
|
+
parsed
|
|
588
|
+
);
|
|
589
|
+
merged.version = 1;
|
|
590
|
+
merged.generatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
591
|
+
merged.repoPath = workDir;
|
|
592
|
+
const savePath = path.join(workDir, "knowledge.json");
|
|
593
|
+
fs.writeFileSync(savePath, JSON.stringify(merged, null, 2), "utf-8");
|
|
594
|
+
const markdown = projectKnowledgeToMarkdown(merged);
|
|
595
|
+
store.upsertProjectMeta(markdown, merged);
|
|
596
|
+
store.setLastAnalyzedAt(merged.generatedAt);
|
|
597
|
+
logger2.info("Incremental analysis complete", { changedFiles: changedFiles.length });
|
|
598
|
+
return { knowledge: merged, changedFiles };
|
|
599
|
+
}
|
|
600
|
+
var KNOWLEDGE_FILE_PATTERNS = [
|
|
601
|
+
".cursor/rules/",
|
|
602
|
+
"CLAUDE.md",
|
|
603
|
+
"AGENTS.md",
|
|
604
|
+
".cursorrules",
|
|
605
|
+
".agents/",
|
|
606
|
+
".claude/",
|
|
607
|
+
"README.md",
|
|
608
|
+
"docs/"
|
|
609
|
+
];
|
|
610
|
+
function buildIncrementalPrompt(staticInfo, existingKnowledge, changedFiles) {
|
|
611
|
+
const knowledgeFilesChanged = changedFiles.filter(
|
|
612
|
+
(f) => KNOWLEDGE_FILE_PATTERNS.some((p) => f.includes(p))
|
|
613
|
+
);
|
|
614
|
+
const focusHint = knowledgeFilesChanged.length > 0 ? `
|
|
615
|
+
|
|
616
|
+
**\u6CE8\u610F**\uFF1A\u4EE5\u4E0B Agent \u77E5\u8BC6\u6587\u4EF6\u53D1\u751F\u4E86\u53D8\u66F4\uFF0C\u8BF7\u91CD\u70B9\u66F4\u65B0 agentKnowledge\u3001businessContext\u3001architecture\u3001domainConcepts \u5B57\u6BB5\uFF1A
|
|
617
|
+
${knowledgeFilesChanged.map((f) => "- " + f).join("\n")}` : "";
|
|
618
|
+
const outputSection = buildAnalyzePrompt("").split("## \u8F93\u51FA\u8981\u6C42").slice(1).join("## \u8F93\u51FA\u8981\u6C42");
|
|
619
|
+
return [
|
|
620
|
+
"\u4F60\u662F\u4E00\u4E2A\u9879\u76EE\u5206\u6790\u4E13\u5BB6\u3002\u9879\u76EE\u4EE3\u7801\u5DF2\u53D1\u751F\u53D8\u66F4\uFF0C\u8BF7\u6839\u636E\u6700\u65B0\u4FE1\u606F\u66F4\u65B0\u77E5\u8BC6\u914D\u7F6E\u3002",
|
|
621
|
+
"\u4F60\u9700\u8981\u4FDD\u7559\u73B0\u6709\u77E5\u8BC6\u4E2D\u6B63\u786E\u7684\u90E8\u5206\uFF0C\u66F4\u65B0\u53D7\u53D8\u66F4\u5F71\u54CD\u7684\u90E8\u5206\uFF0C\u5E76\u786E\u4FDD\u4E1A\u52A1\u7406\u89E3\u548C Agent \u77E5\u8BC6\u59CB\u7EC8\u662F\u6700\u65B0\u7684\u3002",
|
|
622
|
+
focusHint,
|
|
623
|
+
"",
|
|
624
|
+
"## \u73B0\u6709\u77E5\u8BC6",
|
|
625
|
+
existingKnowledge,
|
|
626
|
+
"",
|
|
627
|
+
"## \u53D8\u66F4\u6587\u4EF6\u5217\u8868",
|
|
628
|
+
changedFiles.join("\n"),
|
|
629
|
+
"",
|
|
630
|
+
"## \u5F53\u524D\u9879\u76EE\u4FE1\u606F",
|
|
631
|
+
staticInfo,
|
|
632
|
+
"",
|
|
633
|
+
outputSection ? "## \u8F93\u51FA\u8981\u6C42" + outputSection : ""
|
|
634
|
+
].join("\n");
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
export {
|
|
638
|
+
KNOWLEDGE_DEFAULTS,
|
|
639
|
+
collectStaticInfo,
|
|
640
|
+
analyze,
|
|
641
|
+
analyzeIncremental
|
|
642
|
+
};
|
|
643
|
+
//# sourceMappingURL=chunk-5VUB3UUK.js.map
|