mcp-probe-kit 3.0.19 → 3.0.21

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.
Files changed (45) hide show
  1. package/README.md +12 -5
  2. package/build/index.js +3 -1
  3. package/build/lib/__tests__/agents-md-template.unit.test.js +2 -0
  4. package/build/lib/__tests__/memory-config.unit.test.js +9 -0
  5. package/build/lib/__tests__/memory-injection.unit.test.d.ts +1 -0
  6. package/build/lib/__tests__/memory-injection.unit.test.js +51 -0
  7. package/build/lib/__tests__/memory-orchestration.unit.test.d.ts +1 -0
  8. package/build/lib/__tests__/memory-orchestration.unit.test.js +84 -0
  9. package/build/lib/__tests__/memory-payload.unit.test.d.ts +1 -0
  10. package/build/lib/__tests__/memory-payload.unit.test.js +35 -0
  11. package/build/lib/agents-md-template.js +7 -5
  12. package/build/lib/memory-client.d.ts +8 -1
  13. package/build/lib/memory-client.js +53 -44
  14. package/build/lib/memory-config.d.ts +8 -0
  15. package/build/lib/memory-config.js +19 -0
  16. package/build/lib/memory-orchestration.d.ts +7 -2
  17. package/build/lib/memory-orchestration.js +81 -8
  18. package/build/lib/memory-payload.d.ts +21 -0
  19. package/build/lib/memory-payload.js +65 -0
  20. package/build/resources/ui-ux-data/metadata.json +1 -1
  21. package/build/schemas/index.d.ts +38 -9
  22. package/build/schemas/memory-tools.d.ts +38 -9
  23. package/build/schemas/memory-tools.js +24 -9
  24. package/build/tools/index.d.ts +1 -0
  25. package/build/tools/index.js +1 -0
  26. package/build/tools/memorize_asset.js +12 -0
  27. package/build/tools/scan_and_extract_patterns.js +7 -7
  28. package/build/tools/search_memory.d.ts +7 -0
  29. package/build/tools/search_memory.js +57 -0
  30. package/build/tools/start_bugfix.js +3 -3
  31. package/build/tools/start_feature.js +3 -3
  32. package/build/tools/start_ui.js +3 -3
  33. package/docs/data/tools.js +18 -0
  34. package/docs/i18n/all-tools/en.json +6 -1
  35. package/docs/i18n/all-tools/ja.json +2 -1
  36. package/docs/i18n/all-tools/ko.json +2 -1
  37. package/docs/i18n/all-tools/zh-CN.json +7 -2
  38. package/docs/i18n/en.json +5 -5
  39. package/docs/i18n/ja.json +2 -2
  40. package/docs/i18n/ko.json +2 -2
  41. package/docs/i18n/zh-CN.json +7 -7
  42. package/docs/memory-local-setup.md +1 -1
  43. package/docs/memory-local-setup.zh-CN.md +5 -2
  44. package/docs/pages/getting-started.html +3 -2
  45. package/package.json +2 -2
@@ -1,5 +1,35 @@
1
1
  import { createMemoryClient } from './memory-client.js';
2
- export async function loadMemoryInjectionContext(query) {
2
+ import { getMemoryConfig } from './memory-config.js';
3
+ function kindSearchPreferences(kind) {
4
+ switch (kind) {
5
+ case 'bugfix':
6
+ return { preferTypes: ['bugfix'], preferTags: ['bugfix', 'root-cause'] };
7
+ case 'ui':
8
+ return { preferTypes: ['component', 'pattern'], preferTags: ['ui', 'pattern'] };
9
+ case 'feature':
10
+ return { preferTypes: ['pattern', 'code'], preferTags: ['feature', 'pattern'] };
11
+ default:
12
+ return { preferTypes: [], preferTags: [] };
13
+ }
14
+ }
15
+ export function truncateInjectionText(value, maxChars) {
16
+ if (value.length <= maxChars) {
17
+ return value;
18
+ }
19
+ return `${value.slice(0, Math.max(0, maxChars - 3))}...`;
20
+ }
21
+ async function loadFullAssets(results) {
22
+ const client = createMemoryClient();
23
+ if (!client.isReadEnabled() || results.length === 0) {
24
+ return {};
25
+ }
26
+ const entries = await Promise.all(results.map(async (item) => {
27
+ const asset = await client.getAsset(item.id);
28
+ return asset ? [item.id, asset] : null;
29
+ }));
30
+ return Object.fromEntries(entries.filter((entry) => entry !== null));
31
+ }
32
+ export async function loadMemoryInjectionContext(query, kind = 'default') {
3
33
  const client = createMemoryClient();
4
34
  if (!client.isEnabled()) {
5
35
  return {
@@ -8,16 +38,23 @@ export async function loadMemoryInjectionContext(query) {
8
38
  degraded: false,
9
39
  query,
10
40
  results: [],
41
+ assetsById: {},
11
42
  };
12
43
  }
13
44
  try {
14
- const results = await client.search(query);
45
+ const prefs = kindSearchPreferences(kind);
46
+ const results = await client.search(query, {
47
+ preferTypes: prefs.preferTypes,
48
+ preferTags: prefs.preferTags,
49
+ });
50
+ const assetsById = await loadFullAssets(results);
15
51
  return {
16
52
  enabled: true,
17
53
  available: true,
18
54
  degraded: false,
19
55
  query,
20
56
  results,
57
+ assetsById,
21
58
  };
22
59
  }
23
60
  catch (error) {
@@ -27,6 +64,7 @@ export async function loadMemoryInjectionContext(query) {
27
64
  degraded: true,
28
65
  query,
29
66
  results: [],
67
+ assetsById: {},
30
68
  error: error instanceof Error ? error.message : String(error),
31
69
  };
32
70
  }
@@ -39,7 +77,44 @@ function formatMemoryResultLabel(item) {
39
77
  : '历史资产';
40
78
  return `${item.name} [${item.type}] (${kind})`;
41
79
  }
80
+ export function shouldShowSourceInSearch(item, config = getMemoryConfig()) {
81
+ if (config.searchShowSource) {
82
+ return Boolean(item.sourcePath);
83
+ }
84
+ if (!config.repoId || !item.sourceProject || !item.sourcePath) {
85
+ return false;
86
+ }
87
+ return item.sourceProject === config.repoId;
88
+ }
89
+ function formatSourceHint(item, config) {
90
+ if (!shouldShowSourceInSearch(item, config)) {
91
+ return '';
92
+ }
93
+ return `\n - 来源: ${item.sourcePath}`;
94
+ }
95
+ function formatAssetBody(asset, config) {
96
+ const lines = [
97
+ `### ${asset.name}`,
98
+ `- asset_id: ${asset.id}`,
99
+ asset.description ? `- 描述: ${asset.description}` : '',
100
+ asset.usage ? `- 适用: ${asset.usage}` : '',
101
+ asset.tags.length > 0 ? `- 标签: ${asset.tags.join(', ')}` : '',
102
+ '',
103
+ truncateInjectionText(asset.content, config.injectionContentMaxChars),
104
+ ].filter(Boolean);
105
+ return lines.join('\n');
106
+ }
107
+ function formatResultBlock(item, index, context, config) {
108
+ const label = formatMemoryResultLabel(item);
109
+ const asset = context.assetsById[item.id];
110
+ const header = `${index + 1}. ${label} score=${item.score.toFixed(3)}\n - 摘要: ${item.summary}${formatSourceHint(item, config)}`;
111
+ if (asset?.content) {
112
+ return `${header}\n\n${formatAssetBody(asset, config)}\n`;
113
+ }
114
+ return `${header}\n - 全文加载失败,可手动: read_memory_asset {"asset_id": "${item.id}"}\n`;
115
+ }
42
116
  export function renderMemoryGuideSection(context) {
117
+ const config = getMemoryConfig();
43
118
  if (!context.enabled) {
44
119
  return '';
45
120
  }
@@ -49,13 +124,11 @@ export function renderMemoryGuideSection(context) {
49
124
  if (context.results.length === 0) {
50
125
  return `\n\n## 🧠 记忆系统\n- 状态: 已启用\n- 检索结果: 未找到高相关记录(含历史 Bug 修复与可复用模式)\n- 处理: 继续主流程;Bug 修复验证通过后必须 \`memorize_asset\` 沉淀;功能/UI 有可复用产出再沉淀\n`;
51
126
  }
127
+ const loadedCount = context.results.filter((item) => context.assetsById[item.id]?.content).length;
52
128
  const items = context.results
53
- .map((item, index) => {
54
- const label = formatMemoryResultLabel(item);
55
- return `${index + 1}. ${label} score=${item.score.toFixed(3)}\n - 摘要: ${item.summary}\n - 读取: read_memory_asset {\"asset_id\": \"${item.id}\"}${item.sourcePath ? `\n - 来源: ${item.sourcePath}` : ''}`;
56
- })
129
+ .map((item, index) => formatResultBlock(item, index, context, config))
57
130
  .join('\n');
58
- return `\n\n## 🧠 记忆系统\n- 状态: 已启用\n- 指令: 开干前先复用下列记录(含历史 Bug 现象/根因/改法);相关条目用 \`read_memory_asset\` 读全文,避免重复踩坑\n- 检索结果:\n${items}\n`;
131
+ return `\n\n## 🧠 记忆系统\n- 状态: 已启用\n- 指令: 下列为已自动加载的历史经验全文(${loadedCount}/${context.results.length} 条);开干前直接复用,无需再调 \`read_memory_asset\`\n- 检索结果:\n${items}`;
59
132
  }
60
133
  export function buildMemoryPlanStep(kind = 'default') {
61
134
  if (kind === 'bugfix') {
@@ -68,7 +141,7 @@ export function buildMemoryPlanStep(kind = 'default') {
68
141
  type: 'bugfix',
69
142
  description: '[现象、报错信息、复现条件]',
70
143
  summary: '[检索用:关键词 + 根因 + 修复要点,一句话]',
71
- content: '【现象】...\n【根因】...\n【修复】具体改动文件与关键代码/配置\n【验证】如何确认已修好',
144
+ content: '【现象】...\n【根因】...\n【修复】具体改动与关键代码/配置\n【验证】如何确认已修好',
72
145
  usage: '[再次遇到何种症状时可参考]',
73
146
  tags: ['bugfix', 'root-cause'],
74
147
  confidence: 0.85,
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Unify legacy Qdrant payloads (kind/title/source) with the current asset schema.
3
+ */
4
+ export declare function normalizeMemoryPayload(payload: Record<string, unknown>): Record<string, unknown>;
5
+ export declare function payloadToMemoryFields(payload: Record<string, unknown>): {
6
+ id: string;
7
+ name: string;
8
+ type: string;
9
+ description: string;
10
+ summary: string;
11
+ content: string;
12
+ tags: string[];
13
+ confidence: number;
14
+ sourceProject?: string;
15
+ sourcePath?: string;
16
+ usage?: string;
17
+ contentHash?: string;
18
+ normalizedContentHash?: string;
19
+ createdAt: string;
20
+ updatedAt: string;
21
+ };
@@ -0,0 +1,65 @@
1
+ function truncate(value, maxChars) {
2
+ if (value.length <= maxChars) {
3
+ return value;
4
+ }
5
+ return `${value.slice(0, Math.max(0, maxChars - 3))}...`;
6
+ }
7
+ /**
8
+ * Unify legacy Qdrant payloads (kind/title/source) with the current asset schema.
9
+ */
10
+ export function normalizeMemoryPayload(payload) {
11
+ const normalized = { ...payload };
12
+ if (!normalized.name && typeof normalized.title === 'string') {
13
+ normalized.name = normalized.title;
14
+ }
15
+ if (!normalized.type && typeof normalized.kind === 'string') {
16
+ const kind = normalized.kind;
17
+ normalized.type = kind === 'extracted_pattern' ? 'pattern' : kind;
18
+ }
19
+ if (!normalized.description) {
20
+ if (typeof normalized.title === 'string') {
21
+ normalized.description = normalized.title;
22
+ }
23
+ else if (typeof normalized.source === 'string') {
24
+ normalized.description = `Legacy memory from ${normalized.source}`;
25
+ }
26
+ }
27
+ if (!normalized.summary && typeof normalized.content === 'string') {
28
+ normalized.summary = truncate(normalized.content, 280);
29
+ }
30
+ if (!normalized.createdAt && typeof normalized.created_at === 'string') {
31
+ normalized.createdAt = normalized.created_at;
32
+ }
33
+ if (!normalized.updatedAt) {
34
+ if (typeof normalized.updated_at === 'string') {
35
+ normalized.updatedAt = normalized.updated_at;
36
+ }
37
+ else if (typeof normalized.createdAt === 'string') {
38
+ normalized.updatedAt = normalized.createdAt;
39
+ }
40
+ }
41
+ return normalized;
42
+ }
43
+ export function payloadToMemoryFields(payload) {
44
+ const p = normalizeMemoryPayload(payload);
45
+ const tags = Array.isArray(p.tags)
46
+ ? p.tags.filter((item) => typeof item === 'string' && item.trim().length > 0)
47
+ : [];
48
+ return {
49
+ id: String(p.id || ''),
50
+ name: String(p.name || ''),
51
+ type: String(p.type || ''),
52
+ description: String(p.description || ''),
53
+ summary: String(p.summary || ''),
54
+ content: String(p.content || ''),
55
+ tags,
56
+ confidence: typeof p.confidence === 'number' && Number.isFinite(p.confidence) ? p.confidence : 0.5,
57
+ sourceProject: typeof p.sourceProject === 'string' ? p.sourceProject : undefined,
58
+ sourcePath: typeof p.sourcePath === 'string' ? p.sourcePath : undefined,
59
+ usage: typeof p.usage === 'string' ? p.usage : undefined,
60
+ contentHash: typeof p.contentHash === 'string' ? p.contentHash : undefined,
61
+ normalizedContentHash: typeof p.normalizedContentHash === 'string' ? p.normalizedContentHash : undefined,
62
+ createdAt: String(p.createdAt || ''),
63
+ updatedAt: String(p.updatedAt || ''),
64
+ };
65
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": "2.2.3",
3
- "syncedAt": "2026-05-26T08:30:56.969Z",
3
+ "syncedAt": "2026-05-27T08:58:13.736Z",
4
4
  "source": "uipro-cli",
5
5
  "format": "json"
6
6
  }
@@ -688,6 +688,35 @@ export declare const allToolSchemas: ({
688
688
  };
689
689
  required: never[];
690
690
  };
691
+ } | {
692
+ readonly name: "search_memory";
693
+ readonly description: "按语义检索共享记忆库。适合在 start_* 之外主动查找历史 Bug 修复或可复用模式;命中后用 read_memory_asset 读取全文。";
694
+ readonly inputSchema: {
695
+ readonly type: "object";
696
+ readonly properties: {
697
+ readonly query: {
698
+ readonly type: "string";
699
+ readonly description: "检索 query(现象、报错、关键词、功能描述等)";
700
+ };
701
+ readonly type: {
702
+ readonly type: "string";
703
+ readonly description: "优先匹配的资产类型,如 bugfix、pattern、component";
704
+ };
705
+ readonly tags: {
706
+ readonly type: "array";
707
+ readonly items: {
708
+ readonly type: "string";
709
+ };
710
+ readonly description: "优先匹配的标签";
711
+ };
712
+ readonly limit: {
713
+ readonly type: "number";
714
+ readonly description: "返回条数,默认 MEMORY_SEARCH_LIMIT";
715
+ };
716
+ };
717
+ readonly required: readonly ["query"];
718
+ readonly additionalProperties: true;
719
+ };
691
720
  } | {
692
721
  readonly name: "read_memory_asset";
693
722
  readonly description: "当编排阶段已检索到记忆摘要,且 AI 需要查看完整沉淀代码或详细规范时使用。根据 asset_id 读取记忆资产详情。";
@@ -704,7 +733,7 @@ export declare const allToolSchemas: ({
704
733
  };
705
734
  } | {
706
735
  readonly name: "memorize_asset";
707
- readonly description: "沉淀可检索资产到记忆系统:可复用代码/模式;Bug 修复后必须写入 type=bugfix(现象、根因、改法、tags bugfix)。";
736
+ readonly description: "沉淀可检索资产到共享记忆库。Bug 修复后必须 type=bugfix,content 含【现象】【根因】【修复】【验证】。跨仓库共享时勿填 source_project/source_path,路径写入 content 即可。";
708
737
  readonly inputSchema: {
709
738
  readonly type: "object";
710
739
  readonly properties: {
@@ -714,7 +743,7 @@ export declare const allToolSchemas: ({
714
743
  };
715
744
  readonly type: {
716
745
  readonly type: "string";
717
- readonly description: "资产类型,如 code/component/pattern/spec";
746
+ readonly description: "资产类型:bugfix / pattern / component / code 等";
718
747
  };
719
748
  readonly description: {
720
749
  readonly type: "string";
@@ -722,11 +751,11 @@ export declare const allToolSchemas: ({
722
751
  };
723
752
  readonly summary: {
724
753
  readonly type: "string";
725
- readonly description: "用于检索的凝练摘要";
754
+ readonly description: "检索用一句话摘要(关键词 + 根因/要点)";
726
755
  };
727
756
  readonly content: {
728
757
  readonly type: "string";
729
- readonly description: "完整内容";
758
+ readonly description: "完整内容(bugfix 建议结构化四段)";
730
759
  };
731
760
  readonly code_snippet: {
732
761
  readonly type: "string";
@@ -734,15 +763,15 @@ export declare const allToolSchemas: ({
734
763
  };
735
764
  readonly file_path: {
736
765
  readonly type: "string";
737
- readonly description: "来源文件路径";
766
+ readonly description: "已废弃:勿用于跨仓库沉淀,路径写入 content";
738
767
  };
739
768
  readonly source_project: {
740
769
  readonly type: "string";
741
- readonly description: "来源项目";
770
+ readonly description: "已废弃:仅同仓库追溯时可选";
742
771
  };
743
772
  readonly source_path: {
744
773
  readonly type: "string";
745
- readonly description: "来源路径";
774
+ readonly description: "已废弃:仅同仓库追溯时可选";
746
775
  };
747
776
  readonly usage: {
748
777
  readonly type: "string";
@@ -757,7 +786,7 @@ export declare const allToolSchemas: ({
757
786
  readonly items: {
758
787
  readonly type: "string";
759
788
  };
760
- readonly description: "标签列表";
789
+ readonly description: "标签列表,如 bugfix, root-cause";
761
790
  };
762
791
  };
763
792
  readonly required: readonly ["name", "description", "summary"];
@@ -779,7 +808,7 @@ export declare const allToolSchemas: ({
779
808
  };
780
809
  readonly project_name: {
781
810
  readonly type: "string";
782
- readonly description: "来源项目名";
811
+ readonly description: "已废弃,扫描结果不再写入 source_project";
783
812
  };
784
813
  readonly directory_path: {
785
814
  readonly type: "string";
@@ -1,4 +1,33 @@
1
1
  export declare const memoryToolSchemas: readonly [{
2
+ readonly name: "search_memory";
3
+ readonly description: "按语义检索共享记忆库。适合在 start_* 之外主动查找历史 Bug 修复或可复用模式;命中后用 read_memory_asset 读取全文。";
4
+ readonly inputSchema: {
5
+ readonly type: "object";
6
+ readonly properties: {
7
+ readonly query: {
8
+ readonly type: "string";
9
+ readonly description: "检索 query(现象、报错、关键词、功能描述等)";
10
+ };
11
+ readonly type: {
12
+ readonly type: "string";
13
+ readonly description: "优先匹配的资产类型,如 bugfix、pattern、component";
14
+ };
15
+ readonly tags: {
16
+ readonly type: "array";
17
+ readonly items: {
18
+ readonly type: "string";
19
+ };
20
+ readonly description: "优先匹配的标签";
21
+ };
22
+ readonly limit: {
23
+ readonly type: "number";
24
+ readonly description: "返回条数,默认 MEMORY_SEARCH_LIMIT";
25
+ };
26
+ };
27
+ readonly required: readonly ["query"];
28
+ readonly additionalProperties: true;
29
+ };
30
+ }, {
2
31
  readonly name: "read_memory_asset";
3
32
  readonly description: "当编排阶段已检索到记忆摘要,且 AI 需要查看完整沉淀代码或详细规范时使用。根据 asset_id 读取记忆资产详情。";
4
33
  readonly inputSchema: {
@@ -14,7 +43,7 @@ export declare const memoryToolSchemas: readonly [{
14
43
  };
15
44
  }, {
16
45
  readonly name: "memorize_asset";
17
- readonly description: "沉淀可检索资产到记忆系统:可复用代码/模式;Bug 修复后必须写入 type=bugfix(现象、根因、改法、tags bugfix)。";
46
+ readonly description: "沉淀可检索资产到共享记忆库。Bug 修复后必须 type=bugfix,content 含【现象】【根因】【修复】【验证】。跨仓库共享时勿填 source_project/source_path,路径写入 content 即可。";
18
47
  readonly inputSchema: {
19
48
  readonly type: "object";
20
49
  readonly properties: {
@@ -24,7 +53,7 @@ export declare const memoryToolSchemas: readonly [{
24
53
  };
25
54
  readonly type: {
26
55
  readonly type: "string";
27
- readonly description: "资产类型,如 code/component/pattern/spec";
56
+ readonly description: "资产类型:bugfix / pattern / component / code 等";
28
57
  };
29
58
  readonly description: {
30
59
  readonly type: "string";
@@ -32,11 +61,11 @@ export declare const memoryToolSchemas: readonly [{
32
61
  };
33
62
  readonly summary: {
34
63
  readonly type: "string";
35
- readonly description: "用于检索的凝练摘要";
64
+ readonly description: "检索用一句话摘要(关键词 + 根因/要点)";
36
65
  };
37
66
  readonly content: {
38
67
  readonly type: "string";
39
- readonly description: "完整内容";
68
+ readonly description: "完整内容(bugfix 建议结构化四段)";
40
69
  };
41
70
  readonly code_snippet: {
42
71
  readonly type: "string";
@@ -44,15 +73,15 @@ export declare const memoryToolSchemas: readonly [{
44
73
  };
45
74
  readonly file_path: {
46
75
  readonly type: "string";
47
- readonly description: "来源文件路径";
76
+ readonly description: "已废弃:勿用于跨仓库沉淀,路径写入 content";
48
77
  };
49
78
  readonly source_project: {
50
79
  readonly type: "string";
51
- readonly description: "来源项目";
80
+ readonly description: "已废弃:仅同仓库追溯时可选";
52
81
  };
53
82
  readonly source_path: {
54
83
  readonly type: "string";
55
- readonly description: "来源路径";
84
+ readonly description: "已废弃:仅同仓库追溯时可选";
56
85
  };
57
86
  readonly usage: {
58
87
  readonly type: "string";
@@ -67,7 +96,7 @@ export declare const memoryToolSchemas: readonly [{
67
96
  readonly items: {
68
97
  readonly type: "string";
69
98
  };
70
- readonly description: "标签列表";
99
+ readonly description: "标签列表,如 bugfix, root-cause";
71
100
  };
72
101
  };
73
102
  readonly required: readonly ["name", "description", "summary"];
@@ -89,7 +118,7 @@ export declare const memoryToolSchemas: readonly [{
89
118
  };
90
119
  readonly project_name: {
91
120
  readonly type: "string";
92
- readonly description: "来源项目名";
121
+ readonly description: "已废弃,扫描结果不再写入 source_project";
93
122
  };
94
123
  readonly directory_path: {
95
124
  readonly type: "string";
@@ -1,4 +1,19 @@
1
1
  export const memoryToolSchemas = [
2
+ {
3
+ name: 'search_memory',
4
+ description: '按语义检索共享记忆库。适合在 start_* 之外主动查找历史 Bug 修复或可复用模式;命中后用 read_memory_asset 读取全文。',
5
+ inputSchema: {
6
+ type: 'object',
7
+ properties: {
8
+ query: { type: 'string', description: '检索 query(现象、报错、关键词、功能描述等)' },
9
+ type: { type: 'string', description: '优先匹配的资产类型,如 bugfix、pattern、component' },
10
+ tags: { type: 'array', items: { type: 'string' }, description: '优先匹配的标签' },
11
+ limit: { type: 'number', description: '返回条数,默认 MEMORY_SEARCH_LIMIT' },
12
+ },
13
+ required: ['query'],
14
+ additionalProperties: true,
15
+ },
16
+ },
2
17
  {
3
18
  name: 'read_memory_asset',
4
19
  description: '当编排阶段已检索到记忆摘要,且 AI 需要查看完整沉淀代码或详细规范时使用。根据 asset_id 读取记忆资产详情。',
@@ -16,22 +31,22 @@ export const memoryToolSchemas = [
16
31
  },
17
32
  {
18
33
  name: 'memorize_asset',
19
- description: '沉淀可检索资产到记忆系统:可复用代码/模式;Bug 修复后必须写入 type=bugfix(现象、根因、改法、tags bugfix)。',
34
+ description: '沉淀可检索资产到共享记忆库。Bug 修复后必须 type=bugfix,content 含【现象】【根因】【修复】【验证】。跨仓库共享时勿填 source_project/source_path,路径写入 content 即可。',
20
35
  inputSchema: {
21
36
  type: 'object',
22
37
  properties: {
23
38
  name: { type: 'string', description: '资产名称' },
24
- type: { type: 'string', description: '资产类型,如 code/component/pattern/spec' },
39
+ type: { type: 'string', description: '资产类型:bugfix / pattern / component / code 等' },
25
40
  description: { type: 'string', description: '资产描述' },
26
- summary: { type: 'string', description: '用于检索的凝练摘要' },
27
- content: { type: 'string', description: '完整内容' },
41
+ summary: { type: 'string', description: '检索用一句话摘要(关键词 + 根因/要点)' },
42
+ content: { type: 'string', description: '完整内容(bugfix 建议结构化四段)' },
28
43
  code_snippet: { type: 'string', description: '代码片段,content 的别名' },
29
- file_path: { type: 'string', description: '来源文件路径' },
30
- source_project: { type: 'string', description: '来源项目' },
31
- source_path: { type: 'string', description: '来源路径' },
44
+ file_path: { type: 'string', description: '已废弃:勿用于跨仓库沉淀,路径写入 content' },
45
+ source_project: { type: 'string', description: '已废弃:仅同仓库追溯时可选' },
46
+ source_path: { type: 'string', description: '已废弃:仅同仓库追溯时可选' },
32
47
  usage: { type: 'string', description: '适用场景/使用方式' },
33
48
  confidence: { type: 'number', description: '置信度,0-1' },
34
- tags: { type: 'array', items: { type: 'string' }, description: '标签列表' },
49
+ tags: { type: 'array', items: { type: 'string' }, description: '标签列表,如 bugfix, root-cause' },
35
50
  },
36
51
  required: ['name', 'description', 'summary'],
37
52
  additionalProperties: true,
@@ -45,7 +60,7 @@ export const memoryToolSchemas = [
45
60
  properties: {
46
61
  content: { type: 'string', description: '待分析的代码或文本内容。传入该字段时走单段分析模式' },
47
62
  file_path: { type: 'string', description: '来源文件路径。单段分析时作为来源路径使用' },
48
- project_name: { type: 'string', description: '来源项目名' },
63
+ project_name: { type: 'string', description: '已废弃,扫描结果不再写入 source_project' },
49
64
  directory_path: { type: 'string', description: '要扫描的目录路径。最佳实践是传相对 `project_root` 的路径,例如 `app/utils`;如果拿不到 `project_root`,才传目录绝对路径。不要传带项目名的半相对路径,例如 `font-miniapp-api/app/utils`。' },
50
65
  project_root: { type: 'string', description: '项目根目录绝对路径。目录扫描时建议始终传入;传入后,`directory_path` 应写成相对项目根的路径。' },
51
66
  max_files: { type: 'number', description: '最多扫描多少个文件,默认 30,最大 200' },
@@ -16,6 +16,7 @@ export { interview } from "./interview.js";
16
16
  export { askUser } from "./ask_user.js";
17
17
  export { uiDesignSystem, uiSearch, syncUiData } from "./ui-ux-tools.js";
18
18
  export { startUi } from "./start_ui.js";
19
+ export { searchMemory } from "./search_memory.js";
19
20
  export { readMemoryAsset } from "./read_memory_asset.js";
20
21
  export { memorizeAsset } from "./memorize_asset.js";
21
22
  export { scanAndExtractPatterns } from "./scan_and_extract_patterns.js";
@@ -20,6 +20,7 @@ export { askUser } from "./ask_user.js";
20
20
  export { uiDesignSystem, uiSearch, syncUiData } from "./ui-ux-tools.js";
21
21
  export { startUi } from "./start_ui.js";
22
22
  // 记忆工具
23
+ export { searchMemory } from "./search_memory.js";
23
24
  export { readMemoryAsset } from "./read_memory_asset.js";
24
25
  export { memorizeAsset } from "./memorize_asset.js";
25
26
  export { scanAndExtractPatterns } from "./scan_and_extract_patterns.js";
@@ -42,6 +42,17 @@ export async function memorizeAsset(args) {
42
42
  if (!client.isEnabled()) {
43
43
  return okStructured('记忆服务未开启,已跳过沉淀。', { enabled: false, stored: false });
44
44
  }
45
+ const warnings = [];
46
+ if (type === 'bugfix') {
47
+ const requiredSections = ['【现象】', '【根因】', '【修复】'];
48
+ const missing = requiredSections.filter((section) => !content.includes(section));
49
+ if (missing.length > 0) {
50
+ warnings.push(`建议 content 包含 ${missing.join('、')},便于跨仓库检索与复用`);
51
+ }
52
+ }
53
+ if (sourceProject || sourcePath) {
54
+ warnings.push('跨仓库共享记忆时请勿依赖 source_project/source_path;路径请写入 content 正文(可选)');
55
+ }
45
56
  const asset = await client.upsertAsset({
46
57
  name,
47
58
  type,
@@ -58,6 +69,7 @@ export async function memorizeAsset(args) {
58
69
  enabled: true,
59
70
  stored: true,
60
71
  asset,
72
+ warnings: warnings.length > 0 ? warnings : undefined,
61
73
  });
62
74
  }
63
75
  catch (error) {
@@ -108,21 +108,22 @@ function summarizeContent(content, maxChars = 200) {
108
108
  .trim()
109
109
  .slice(0, maxChars);
110
110
  }
111
- function buildPattern(content, filePath, projectName) {
111
+ function buildPattern(content, filePath) {
112
112
  const normalized = content.trim();
113
113
  const candidateNames = collectCandidateNames(normalized);
114
114
  const primaryName = candidateNames[0] || (filePath ? path.basename(filePath) : 'snippet');
115
115
  const type = detectPatternType(normalized, filePath);
116
116
  const summary = summarizeContent(normalized);
117
+ const fileHint = filePath ? `(摘录自 ${filePath})` : '';
117
118
  return {
118
119
  name: primaryName,
119
120
  type,
120
- description: filePath ? `从 ${filePath} 提取的可复用模式` : '从代码片段提取的可复用模式',
121
+ description: filePath
122
+ ? `从 ${filePath} 提取的可复用模式${fileHint}`
123
+ : '从代码片段提取的可复用模式',
121
124
  summary,
122
125
  content: normalized,
123
126
  tags: inferTags(normalized, filePath),
124
- sourcePath: filePath || undefined,
125
- sourceProject: projectName || undefined,
126
127
  confidence: filePath ? 0.62 : 0.55,
127
128
  candidateNames,
128
129
  };
@@ -271,7 +272,6 @@ export async function scanAndExtractPatterns(args) {
271
272
  });
272
273
  const content = getString(parsed.content);
273
274
  const filePath = getString(parsed.file_path);
274
- const projectName = getString(parsed.project_name);
275
275
  const directoryPath = getString(parsed.directory_path);
276
276
  const projectRoot = resolveWorkspaceRoot(getString(parsed.project_root));
277
277
  const maxFiles = Math.max(1, Math.min(200, getNumber(parsed.max_files, 30)));
@@ -282,7 +282,7 @@ export async function scanAndExtractPatterns(args) {
282
282
  .map((item) => item.startsWith('.') ? item.toLowerCase() : `.${item.toLowerCase()}`)
283
283
  : DEFAULT_INCLUDE_EXTENSIONS);
284
284
  if (content) {
285
- const pattern = buildPattern(content, filePath, projectName || undefined);
285
+ const pattern = buildPattern(content, filePath);
286
286
  return okStructured(`已提取 1 个候选模式${filePath ? `: ${filePath}` : ''}`, {
287
287
  mode: 'single',
288
288
  patterns: [pattern],
@@ -331,7 +331,7 @@ export async function scanAndExtractPatterns(args) {
331
331
  continue;
332
332
  }
333
333
  const relativePath = toRelativePath(absoluteFile, projectRoot).replace(/\\/g, '/');
334
- patterns.push(buildPattern(normalized, relativePath, projectName || path.basename(projectRoot)));
334
+ patterns.push(buildPattern(normalized, relativePath));
335
335
  }
336
336
  return okStructured(`已扫描 ${files.length} 个文件,提取 ${patterns.length} 个候选模式`, {
337
337
  mode: 'directory',
@@ -0,0 +1,7 @@
1
+ export declare function searchMemory(args: unknown): Promise<import("../lib/response.js").ToolResponse | {
2
+ content: Array<{
3
+ type: string;
4
+ text: string;
5
+ }>;
6
+ isError: true;
7
+ }>;