homegraph 1.5.2 → 1.5.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/CHANGELOG.md +131 -0
- package/README.md +15 -8
- package/dist/arkui/index.d.ts +4 -0
- package/dist/arkui/index.d.ts.map +1 -0
- package/dist/arkui/index.js +23 -0
- package/dist/arkui/index.js.map +1 -0
- package/dist/arkui/migrate-passage.d.ts +28 -0
- package/dist/arkui/migrate-passage.d.ts.map +1 -0
- package/dist/arkui/migrate-passage.js +310 -0
- package/dist/arkui/migrate-passage.js.map +1 -0
- package/dist/arkui/migrate-semantics.d.ts +47 -0
- package/dist/arkui/migrate-semantics.d.ts.map +1 -0
- package/dist/arkui/migrate-semantics.js +229 -0
- package/dist/arkui/migrate-semantics.js.map +1 -0
- package/dist/arkui/migrate-snapshot.d.ts +79 -0
- package/dist/arkui/migrate-snapshot.d.ts.map +1 -0
- package/dist/arkui/migrate-snapshot.js +340 -0
- package/dist/arkui/migrate-snapshot.js.map +1 -0
- package/dist/bin/fatal-handler.js +2 -2
- package/dist/bin/homegraph.js +105 -156
- package/dist/bin/homegraph.js.map +1 -1
- package/dist/bin/node-version-check.d.ts +6 -15
- package/dist/bin/node-version-check.d.ts.map +1 -1
- package/dist/bin/node-version-check.js +8 -37
- package/dist/bin/node-version-check.js.map +1 -1
- package/dist/db/index.d.ts +36 -1
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +92 -6
- package/dist/db/index.js.map +1 -1
- package/dist/db/migrations.d.ts +1 -1
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +15 -1
- package/dist/db/migrations.js.map +1 -1
- package/dist/db/queries.d.ts +42 -0
- package/dist/db/queries.d.ts.map +1 -1
- package/dist/db/queries.js +177 -10
- package/dist/db/queries.js.map +1 -1
- package/dist/db/schema.sql +6 -1
- package/dist/db/sqlite-adapter.d.ts +8 -3
- package/dist/db/sqlite-adapter.d.ts.map +1 -1
- package/dist/db/sqlite-adapter.js +45 -3
- package/dist/db/sqlite-adapter.js.map +1 -1
- package/dist/extraction/extraction-version.d.ts +1 -1
- package/dist/extraction/extraction-version.js +1 -1
- package/dist/extraction/generated-detection.d.ts +42 -11
- package/dist/extraction/generated-detection.d.ts.map +1 -1
- package/dist/extraction/generated-detection.js +141 -20
- package/dist/extraction/generated-detection.js.map +1 -1
- package/dist/extraction/index.d.ts +42 -0
- package/dist/extraction/index.d.ts.map +1 -1
- package/dist/extraction/index.js +96 -0
- package/dist/extraction/index.js.map +1 -1
- package/dist/extraction/languages/arkts.d.ts +19 -2
- package/dist/extraction/languages/arkts.d.ts.map +1 -1
- package/dist/extraction/languages/arkts.js +460 -110
- package/dist/extraction/languages/arkts.js.map +1 -1
- package/dist/extraction/wasm-runtime-flags.d.ts.map +1 -1
- package/dist/extraction/wasm-runtime-flags.js +9 -6
- package/dist/extraction/wasm-runtime-flags.js.map +1 -1
- package/dist/graph-sources.d.ts +41 -0
- package/dist/graph-sources.d.ts.map +1 -0
- package/dist/graph-sources.js +82 -0
- package/dist/graph-sources.js.map +1 -0
- package/dist/index.d.ts +19 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +79 -9
- package/dist/index.js.map +1 -1
- package/dist/installer/index.d.ts.map +1 -1
- package/dist/installer/index.js +0 -48
- package/dist/installer/index.js.map +1 -1
- package/dist/installer/targets/antigravity.js +1 -1
- package/dist/installer/targets/antigravity.js.map +1 -1
- package/dist/installer/targets/deveco.js +1 -1
- package/dist/installer/targets/deveco.js.map +1 -1
- package/dist/installer/targets/hermes.d.ts +1 -1
- package/dist/installer/targets/hermes.js +2 -2
- package/dist/installer/targets/hermes.js.map +1 -1
- package/dist/installer/targets/opencode.js +1 -1
- package/dist/installer/targets/opencode.js.map +1 -1
- package/dist/installer/targets/shared.js +1 -1
- package/dist/installer/targets/shared.js.map +1 -1
- package/dist/mcp/daemon-paths.d.ts +5 -4
- package/dist/mcp/daemon-paths.d.ts.map +1 -1
- package/dist/mcp/daemon-paths.js +28 -13
- package/dist/mcp/daemon-paths.js.map +1 -1
- package/dist/mcp/daemon-registry.d.ts.map +1 -1
- package/dist/mcp/daemon-registry.js +4 -1
- package/dist/mcp/daemon-registry.js.map +1 -1
- package/dist/mcp/daemon.d.ts +1 -1
- package/dist/mcp/daemon.js +1 -1
- package/dist/mcp/engine.d.ts.map +1 -1
- package/dist/mcp/engine.js +12 -3
- package/dist/mcp/engine.js.map +1 -1
- package/dist/mcp/explore-dedup.d.ts +137 -0
- package/dist/mcp/explore-dedup.d.ts.map +1 -0
- package/dist/mcp/explore-dedup.js +236 -0
- package/dist/mcp/explore-dedup.js.map +1 -0
- package/dist/mcp/explore-session-state.d.ts +217 -0
- package/dist/mcp/explore-session-state.d.ts.map +1 -0
- package/dist/mcp/explore-session-state.js +322 -0
- package/dist/mcp/explore-session-state.js.map +1 -0
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +4 -7
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/proxy.d.ts.map +1 -1
- package/dist/mcp/proxy.js +5 -14
- package/dist/mcp/proxy.js.map +1 -1
- package/dist/mcp/query-worker.d.ts +1 -1
- package/dist/mcp/query-worker.js +1 -1
- package/dist/mcp/server-instructions.d.ts +7 -2
- package/dist/mcp/server-instructions.d.ts.map +1 -1
- package/dist/mcp/server-instructions.js +104 -28
- package/dist/mcp/server-instructions.js.map +1 -1
- package/dist/mcp/session.d.ts +14 -3
- package/dist/mcp/session.d.ts.map +1 -1
- package/dist/mcp/session.js +17 -14
- package/dist/mcp/session.js.map +1 -1
- package/dist/mcp/startup-handshake.d.ts +1 -1
- package/dist/mcp/startup-handshake.js +1 -1
- package/dist/mcp/tools.d.ts +117 -7
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +3056 -503
- package/dist/mcp/tools.js.map +1 -1
- package/dist/resolution/frameworks/arkts-napi.d.ts +14 -0
- package/dist/resolution/frameworks/arkts-napi.d.ts.map +1 -1
- package/dist/resolution/frameworks/arkts-napi.js +169 -49
- package/dist/resolution/frameworks/arkts-napi.js.map +1 -1
- package/dist/search/query-utils.d.ts +116 -4
- package/dist/search/query-utils.d.ts.map +1 -1
- package/dist/search/query-utils.js +869 -60
- package/dist/search/query-utils.js.map +1 -1
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/upgrade/index.d.ts +14 -26
- package/dist/upgrade/index.d.ts.map +1 -1
- package/dist/upgrade/index.js +28 -123
- package/dist/upgrade/index.js.map +1 -1
- package/dist/upgrade/remove-binary.d.ts +19 -19
- package/dist/upgrade/remove-binary.d.ts.map +1 -1
- package/dist/upgrade/remove-binary.js +20 -21
- package/dist/upgrade/remove-binary.js.map +1 -1
- package/dist/upgrade/update-check.d.ts +4 -3
- package/dist/upgrade/update-check.d.ts.map +1 -1
- package/dist/upgrade/update-check.js +4 -3
- package/dist/upgrade/update-check.js.map +1 -1
- package/package.json +12 -8
- package/dist/telemetry/index.d.ts +0 -143
- package/dist/telemetry/index.d.ts.map +0 -1
- package/dist/telemetry/index.js +0 -541
- package/dist/telemetry/index.js.map +0 -1
|
@@ -38,7 +38,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
38
38
|
};
|
|
39
39
|
})();
|
|
40
40
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
-
exports.IMPLEMENTATION_ENTRY_NAME_RE = exports.STOP_WORDS = exports.QUERY_SOURCE_FILE_EXT = void 0;
|
|
41
|
+
exports.IMPLEMENTATION_ENTRY_NAME_RE = exports.GENERIC_VERB_ANCHOR_NOISE = exports.STOP_WORDS = exports.FRAMEWORK_UI_DECORATOR_NAMES = exports.QUERY_SOURCE_FILE_EXT = void 0;
|
|
42
42
|
exports.normalizeNameToken = normalizeNameToken;
|
|
43
43
|
exports.extractFileBasenamesFromQuery = extractFileBasenamesFromQuery;
|
|
44
44
|
exports.extractPathSegmentsFromQuery = extractPathSegmentsFromQuery;
|
|
@@ -47,11 +47,20 @@ exports.extractKitModuleNamesFromQuery = extractKitModuleNamesFromQuery;
|
|
|
47
47
|
exports.extractKitSubmoduleNamesFromQuery = extractKitSubmoduleNamesFromQuery;
|
|
48
48
|
exports.queryAsKitModuleCapabilitySurvey = queryAsKitModuleCapabilitySurvey;
|
|
49
49
|
exports.isMemberLikeIdentifier = isMemberLikeIdentifier;
|
|
50
|
+
exports.queryAsCoNamedTypeMethodInteraction = queryAsCoNamedTypeMethodInteraction;
|
|
50
51
|
exports.queryHasNamedMemberFocus = queryHasNamedMemberFocus;
|
|
51
52
|
exports.queryAsNamedComponentAction = queryAsNamedComponentAction;
|
|
52
53
|
exports.queryAsOutOfRepoSdkCatalog = queryAsOutOfRepoSdkCatalog;
|
|
54
|
+
exports.queryShouldDeferToBuiltinTools = queryShouldDeferToBuiltinTools;
|
|
55
|
+
exports.homegraphDeferGuidance = homegraphDeferGuidance;
|
|
53
56
|
exports.queryShouldPreferExploreOverSearch = queryShouldPreferExploreOverSearch;
|
|
57
|
+
exports.shouldBuildHoverHandlerSurvey = shouldBuildHoverHandlerSurvey;
|
|
58
|
+
exports.isFrameworkUiDecoratorName = isFrameworkUiDecoratorName;
|
|
59
|
+
exports.queryLooksLikeUiComponentType = queryLooksLikeUiComponentType;
|
|
60
|
+
exports.queryAsFocusedUiCluster = queryAsFocusedUiCluster;
|
|
61
|
+
exports.queryAsComponentSurfaceSurvey = queryAsComponentSurfaceSurvey;
|
|
54
62
|
exports.shouldBuildKitModuleUsageSurvey = shouldBuildKitModuleUsageSurvey;
|
|
63
|
+
exports.queryAsksKitInstallDeps = queryAsksKitInstallDeps;
|
|
55
64
|
exports.extractMemberAccessFromQuery = extractMemberAccessFromQuery;
|
|
56
65
|
exports.extractImportSearchTerms = extractImportSearchTerms;
|
|
57
66
|
exports.fileMatchesQueryBasename = fileMatchesQueryBasename;
|
|
@@ -62,6 +71,22 @@ exports.queryNamesConfigFile = queryNamesConfigFile;
|
|
|
62
71
|
exports.hasSymbolFilterInQuery = hasSymbolFilterInQuery;
|
|
63
72
|
exports.hasImportInventoryFilter = hasImportInventoryFilter;
|
|
64
73
|
exports.queryAsApiUsageSurvey = queryAsApiUsageSurvey;
|
|
74
|
+
exports.extractFieldLikeSymbolsFromQuery = extractFieldLikeSymbolsFromQuery;
|
|
75
|
+
exports.queryAsDeclarationSiteSurvey = queryAsDeclarationSiteSurvey;
|
|
76
|
+
exports.queryAsInRepoSystemCapabilityHowto = queryAsInRepoSystemCapabilityHowto;
|
|
77
|
+
exports.queryAsReturnValueConsumerSurvey = queryAsReturnValueConsumerSurvey;
|
|
78
|
+
exports.queryAsConstantUsageSurvey = queryAsConstantUsageSurvey;
|
|
79
|
+
exports.queryAsFieldUsageSurvey = queryAsFieldUsageSurvey;
|
|
80
|
+
exports.queryAsNativeRenderThreadSurvey = queryAsNativeRenderThreadSurvey;
|
|
81
|
+
exports.queryAsDtsWrapSurvey = queryAsDtsWrapSurvey;
|
|
82
|
+
exports.queryAsAssignedFlagImpactSurvey = queryAsAssignedFlagImpactSurvey;
|
|
83
|
+
exports.queryAsNamedControlStateSyncSurvey = queryAsNamedControlStateSyncSurvey;
|
|
84
|
+
exports.extractListedTypeMethodsFromQuery = extractListedTypeMethodsFromQuery;
|
|
85
|
+
exports.queryAsModuleExportSurvey = queryAsModuleExportSurvey;
|
|
86
|
+
exports.queryAsModuleDependencySurvey = queryAsModuleDependencySurvey;
|
|
87
|
+
exports.queryLooksLikeLiteralOrCopyHunt = queryLooksLikeLiteralOrCopyHunt;
|
|
88
|
+
exports.queryAsTypeLifecycleSurvey = queryAsTypeLifecycleSurvey;
|
|
89
|
+
exports.shouldPreferMemberUsageInventory = shouldPreferMemberUsageInventory;
|
|
65
90
|
exports.extractApiUsageTokens = extractApiUsageTokens;
|
|
66
91
|
exports.shouldBuildApiUsageSurvey = shouldBuildApiUsageSurvey;
|
|
67
92
|
exports.queryAsCallerOrMethodSurvey = queryAsCallerOrMethodSurvey;
|
|
@@ -80,6 +105,7 @@ exports.shouldFocusOnQueryNamedDefs = shouldFocusOnQueryNamedDefs;
|
|
|
80
105
|
exports.queryAsInterpretationSurvey = queryAsInterpretationSurvey;
|
|
81
106
|
exports.queryAsTestOnlyInterpretation = queryAsTestOnlyInterpretation;
|
|
82
107
|
exports.extractMechanismEntrySeeds = extractMechanismEntrySeeds;
|
|
108
|
+
exports.queryAsDomainMechanismBag = queryAsDomainMechanismBag;
|
|
83
109
|
exports.shouldTryLightMechanismExplore = shouldTryLightMechanismExplore;
|
|
84
110
|
exports.shouldTryFastInventoryExplore = shouldTryFastInventoryExplore;
|
|
85
111
|
exports.shouldBuildInheritanceSurvey = shouldBuildInheritanceSurvey;
|
|
@@ -178,7 +204,9 @@ function extractKitModuleNamesFromQuery(query) {
|
|
|
178
204
|
}
|
|
179
205
|
return [...names];
|
|
180
206
|
}
|
|
181
|
-
/** Submodule tokens from
|
|
207
|
+
/** Submodule / named-export tokens from kit usage questions.
|
|
208
|
+
* Covers `util模块`, `util 模块`, and `@kit.Foo的bar` / `@kit.Foo bar` (export focus).
|
|
209
|
+
*/
|
|
182
210
|
function extractKitSubmoduleNamesFromQuery(query) {
|
|
183
211
|
const names = new Set();
|
|
184
212
|
for (const m of query.matchAll(/([a-z][a-z0-9_]{1,24})模块/gi)) {
|
|
@@ -189,6 +217,15 @@ function extractKitSubmoduleNamesFromQuery(query) {
|
|
|
189
217
|
if (m[1] && m[1].length >= 2)
|
|
190
218
|
names.add(m[1]);
|
|
191
219
|
}
|
|
220
|
+
// `@kit.ArkTS的taskpool` / `@kit.ArkTS的 foo` — named export, not a catalog.
|
|
221
|
+
for (const m of query.matchAll(/@kit\.[A-Za-z][A-Za-z0-9]*的\s*([a-z][a-zA-Z0-9_]{2,24})\b/gi)) {
|
|
222
|
+
if (m[1])
|
|
223
|
+
names.add(m[1]);
|
|
224
|
+
}
|
|
225
|
+
for (const m of query.matchAll(/@kit\.[A-Za-z][A-Za-z0-9]*[\s.]+([a-z][a-zA-Z0-9_]{2,24})\b/gi)) {
|
|
226
|
+
if (m[1] && !exports.STOP_WORDS.has(m[1].toLowerCase()))
|
|
227
|
+
names.add(m[1]);
|
|
228
|
+
}
|
|
192
229
|
return [...names];
|
|
193
230
|
}
|
|
194
231
|
/**
|
|
@@ -224,6 +261,29 @@ function isMemberLikeIdentifier(token) {
|
|
|
224
261
|
// camelCase property/method: first lower, later upper
|
|
225
262
|
return /^[a-z][a-zA-Z0-9]*[A-Z]/.test(token);
|
|
226
263
|
}
|
|
264
|
+
/**
|
|
265
|
+
* Owning Type + co-named PascalCase methods (CanPlace/Place ↔ BinaryGrid).
|
|
266
|
+
* Not Type.member dotted form — agents name methods as sibling Types.
|
|
267
|
+
* Must stay on compact explore — 「是怎么」alone would light-mechanism dump.
|
|
268
|
+
*/
|
|
269
|
+
function queryAsCoNamedTypeMethodInteraction(query) {
|
|
270
|
+
// "who calls Type's Set/Test/Fill" is a caller inventory, not body interaction.
|
|
271
|
+
if (queryAsCallerOrMethodSurvey(query))
|
|
272
|
+
return false;
|
|
273
|
+
const types = extractTypeNamesFromQuery(query).filter((t) => !isFrameworkUiDecoratorName(t));
|
|
274
|
+
if (types.length < 2 || types.length > 4)
|
|
275
|
+
return false;
|
|
276
|
+
const owners = types.filter((t) => t.length >= 8
|
|
277
|
+
|| /(?:Grid|Manager|Service|Controller|Render|Plugin|Layout|Handler|Provider|Store)/i.test(t));
|
|
278
|
+
const methods = types.filter((t) => !owners.includes(t));
|
|
279
|
+
if (owners.length < 1 || methods.length < 1)
|
|
280
|
+
return false;
|
|
281
|
+
if (/交互|是怎么|如何.*(?:用|调|连|互)|how\s+(?:do|does|are).{0,48}(?:interact|relate|use|call)|与.+交互|和.+交互/i.test(query)) {
|
|
282
|
+
return true;
|
|
283
|
+
}
|
|
284
|
+
// Method-looking PascalCase co-named with an owner — even without 交互.
|
|
285
|
+
return methods.some((m) => /^(?:Can|Is|Has|Get|Set|Place|Fill|Test|Put|Add|Remove|Update|Draw|Check|Find)/.test(m));
|
|
286
|
+
}
|
|
227
287
|
/**
|
|
228
288
|
* Named Type + member (dot form, or co-named Type + member-like token).
|
|
229
289
|
* Structural — no product/question nouns.
|
|
@@ -231,6 +291,8 @@ function isMemberLikeIdentifier(token) {
|
|
|
231
291
|
function queryHasNamedMemberFocus(query) {
|
|
232
292
|
if (extractMemberAccessFromQuery(query).length > 0)
|
|
233
293
|
return true;
|
|
294
|
+
if (queryAsCoNamedTypeMethodInteraction(query))
|
|
295
|
+
return true;
|
|
234
296
|
const types = extractTypeNamesFromQuery(query);
|
|
235
297
|
if (types.length === 0 || types.length > 3)
|
|
236
298
|
return false;
|
|
@@ -248,10 +310,10 @@ function queryAsNamedComponentAction(query) {
|
|
|
248
310
|
if (!looksUi)
|
|
249
311
|
return false;
|
|
250
312
|
const deps = extractDependencySymbolsFromQuery(query);
|
|
251
|
-
if (deps.some((d) => /^on[A-Z]/.test(d) || /^(click|tap|press)$/i.test(d)))
|
|
313
|
+
if (deps.some((d) => /^on[A-Z]/.test(d) || /^(click|tap|press|hover)$/i.test(d)))
|
|
252
314
|
return true;
|
|
253
315
|
// Optional thin intent — only with a UI-looking Type already present.
|
|
254
|
-
return
|
|
316
|
+
return /点击|单击|按下|按钮|悬停|hover|onClick|onTap|onHover|会发生什么|what\s+happens|when\s+(?:clicked|pressed|hovered)/i.test(query);
|
|
255
317
|
}
|
|
256
318
|
/**
|
|
257
319
|
* Out-of-repo SDK catalog (kept for survey omit logic — not as a refuse list).
|
|
@@ -264,6 +326,97 @@ function queryAsOutOfRepoSdkCatalog(query) {
|
|
|
264
326
|
return false;
|
|
265
327
|
return /@kit\.|\b[A-Z][A-Za-z0-9]*Kit\b/i.test(query);
|
|
266
328
|
}
|
|
329
|
+
function queryShouldDeferToBuiltinTools(query) {
|
|
330
|
+
const q = query.trim();
|
|
331
|
+
if (!q)
|
|
332
|
+
return null;
|
|
333
|
+
// Pre-existing catalog classifiers (@kit / *Kit + "what features/APIs").
|
|
334
|
+
// Checked before named-member heuristics — `@kit.X` can look like Type.member.
|
|
335
|
+
if (queryAsOutOfRepoSdkCatalog(q) || queryAsKitModuleCapabilitySurvey(q)) {
|
|
336
|
+
return 'sdk-catalog';
|
|
337
|
+
}
|
|
338
|
+
const hasType = extractTypeNamesFromQuery(q).length > 0;
|
|
339
|
+
const hasFile = extractFileBasenamesFromQuery(q).length > 0;
|
|
340
|
+
const hasMember = extractMemberAccessFromQuery(q).length > 0;
|
|
341
|
+
const hasKit = /@kit\.|@ohos\./i.test(q);
|
|
342
|
+
const hasCaps = /\b[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)+\b/.test(q);
|
|
343
|
+
const hasField = extractFieldLikeSymbolsFromQuery(q).length > 0;
|
|
344
|
+
const hasPath = extractPathSegmentsFromQuery(q).length > 0;
|
|
345
|
+
// Literal / layout / "import text from graphics package" hunts → Grep.
|
|
346
|
+
// No PascalCase Type — light-mechanism must not claim these.
|
|
347
|
+
if (!hasType
|
|
348
|
+
&& !hasFile
|
|
349
|
+
&& !hasMember
|
|
350
|
+
&& !hasKit
|
|
351
|
+
&& !hasCaps
|
|
352
|
+
&& !hasField
|
|
353
|
+
&& !hasPath
|
|
354
|
+
&& queryLooksLikeLiteralOrCopyHunt(q)) {
|
|
355
|
+
return 'concept-or-existence';
|
|
356
|
+
}
|
|
357
|
+
// Structural / in-repo usage surveys must still run.
|
|
358
|
+
if (queryAsMechanismSurvey(q) || queryAsCrossModuleFlowSurvey(q))
|
|
359
|
+
return null;
|
|
360
|
+
if (shouldBuildKitModuleUsageSurvey(q) || shouldBuildApiUsageSurvey(q))
|
|
361
|
+
return null;
|
|
362
|
+
if (shouldBuildCallerInventory(q) || shouldTryLightMechanismExplore(q))
|
|
363
|
+
return null;
|
|
364
|
+
if (queryAsNamedComponentAction(q) || queryHasNamedMemberFocus(q))
|
|
365
|
+
return null;
|
|
366
|
+
if (queryAsInterpretationSurvey(q) || queryAsLocalSymbolDetail(q))
|
|
367
|
+
return null;
|
|
368
|
+
if (queryHasFocusedNamedAnchors(q))
|
|
369
|
+
return null;
|
|
370
|
+
if (queryAsDeclarationSiteSurvey(q)
|
|
371
|
+
|| queryAsConstantUsageSurvey(q)
|
|
372
|
+
|| queryAsFieldUsageSurvey(q)
|
|
373
|
+
|| queryAsModuleExportSurvey(q)
|
|
374
|
+
|| queryAsModuleDependencySurvey(q)) {
|
|
375
|
+
return null;
|
|
376
|
+
}
|
|
377
|
+
// "Which files relate to <topic>?" with no Type/file anchor → Glob/Grep.
|
|
378
|
+
if (/哪些文件|有哪些.*文件|相关的?\s*文件|涉及.*文件|which\s+files?|files?\s+(?:are\s+)?related/i.test(q)
|
|
379
|
+
&& !hasType
|
|
380
|
+
&& !hasFile) {
|
|
381
|
+
return 'file-listing';
|
|
382
|
+
}
|
|
383
|
+
// Existence / concept-compare with no graph anchor → Grep/docs.
|
|
384
|
+
if (/有使用|是否使用|有没有使用|使用了.*吗|是否存在|有没有完整|有什么不同|区别|difference|vs\.?|versus|对比|does\s+(?:this\s+)?(?:project|repo)\s+have|is\s+there\s+(?:a\s+)?complete/i.test(q)
|
|
385
|
+
&& !hasType
|
|
386
|
+
&& !hasFile
|
|
387
|
+
&& !hasMember
|
|
388
|
+
&& !hasKit) {
|
|
389
|
+
return 'concept-or-existence';
|
|
390
|
+
}
|
|
391
|
+
// Hover / 悬停 without a named Type → inventory of hover handlers (not Skip).
|
|
392
|
+
if (shouldBuildHoverHandlerSurvey(q))
|
|
393
|
+
return null;
|
|
394
|
+
// Behavioral / interaction outcome with zero graph anchors → Grep (no symbol to seed).
|
|
395
|
+
// Do NOT include hover/悬停 here — those have a graph inventory path above.
|
|
396
|
+
if (!hasType
|
|
397
|
+
&& !hasFile
|
|
398
|
+
&& !hasMember
|
|
399
|
+
&& !hasKit
|
|
400
|
+
&& /会有什么|会发生什么|什么反应|what\s+happens|what\s+(?:is|are)\s+the\s+(?:reaction|response)|when\s+(?:the\s+)?user\b/i.test(q)) {
|
|
401
|
+
return 'concept-or-existence';
|
|
402
|
+
}
|
|
403
|
+
return null;
|
|
404
|
+
}
|
|
405
|
+
/** Short success-shaped reply when explore/search should not run. */
|
|
406
|
+
function homegraphDeferGuidance(kind, query) {
|
|
407
|
+
const q = query.trim().slice(0, 120);
|
|
408
|
+
const reasons = {
|
|
409
|
+
'sdk-catalog': 'Official SDK / @kit feature catalogs are outside this repo index — use SDK docs.',
|
|
410
|
+
'file-listing': 'Topic → file lists need Grep/Glob (keyword paths), not the symbol graph.',
|
|
411
|
+
'concept-or-existence': 'Concept compare / UI-behavior / existence checks without a named in-repo Type/file/@kit target — Grep (and docs) beat HomeGraph.',
|
|
412
|
+
};
|
|
413
|
+
return [
|
|
414
|
+
'Skip HomeGraph for this question shape — do **not** retry any `homegraph_*` tool for it.',
|
|
415
|
+
reasons[kind],
|
|
416
|
+
`Query: "${q}${query.trim().length > 120 ? '…' : ''}"`,
|
|
417
|
+
'Next: Grep / Glob / Read / SDK docs. Call HomeGraph only for in-repo wiring, callers/callees, or named-symbol flows.',
|
|
418
|
+
].join('\n');
|
|
419
|
+
}
|
|
267
420
|
/**
|
|
268
421
|
* Question already names files/symbols/@kit — prefer explore over FTS search.
|
|
269
422
|
*/
|
|
@@ -271,17 +424,95 @@ function queryShouldPreferExploreOverSearch(query) {
|
|
|
271
424
|
const q = query.trim();
|
|
272
425
|
if (!q)
|
|
273
426
|
return false;
|
|
427
|
+
if (queryLooksLikeLiteralOrCopyHunt(query))
|
|
428
|
+
return false;
|
|
274
429
|
if (/^[A-Za-z_][\w]*$/.test(q))
|
|
275
430
|
return true;
|
|
276
431
|
if (extractFileBasenamesFromQuery(query).length > 0
|
|
277
432
|
|| extractTypeNamesFromQuery(query).length > 0
|
|
278
433
|
|| extractMemberAccessFromQuery(query).length > 0
|
|
279
434
|
|| extractImportSearchTerms(query).length > 0
|
|
280
|
-
|| extractKitModuleNamesFromQuery(query).length > 0
|
|
435
|
+
|| extractKitModuleNamesFromQuery(query).length > 0
|
|
436
|
+
|| extractFieldLikeSymbolsFromQuery(query).length > 0
|
|
437
|
+
|| queryAsConstantUsageSurvey(query)
|
|
438
|
+
|| queryAsDeclarationSiteSurvey(query)
|
|
439
|
+
|| queryAsFieldUsageSurvey(query)
|
|
440
|
+
|| queryAsModuleExportSurvey(query)
|
|
441
|
+
|| queryAsModuleDependencySurvey(query)
|
|
442
|
+
|| queryAsDtsWrapSurvey(query)
|
|
443
|
+
|| shouldBuildApiUsageSurvey(query)
|
|
444
|
+
|| queryAsAssignedFlagImpactSurvey(query)
|
|
445
|
+
|| queryAsNativeRenderThreadSurvey(query)
|
|
446
|
+
|| queryAsInRepoSystemCapabilityHowto(query)
|
|
447
|
+
|| shouldBuildHoverHandlerSurvey(query)
|
|
448
|
+
|| queryAsDataSourceSurvey(query)
|
|
449
|
+
|| queryAsksKitInstallDeps(query)
|
|
450
|
+
|| queryAsTypeLifecycleSurvey(query)
|
|
451
|
+
|| shouldBuildCallerInventory(query)) {
|
|
281
452
|
return true;
|
|
282
453
|
}
|
|
283
454
|
return extractDependencySymbolsFromQuery(query).some((d) => isDistinctiveIdentifier(d));
|
|
284
455
|
}
|
|
456
|
+
/**
|
|
457
|
+
* In-repo pointer/hover handler inventory — no named Type yet, but the graph
|
|
458
|
+
* still has onHover / Hover* symbols. Soft-skip→Grep lost accuracy; inventory wins.
|
|
459
|
+
*/
|
|
460
|
+
function shouldBuildHoverHandlerSurvey(query) {
|
|
461
|
+
if (extractTypeNamesFromQuery(query).length > 0)
|
|
462
|
+
return false;
|
|
463
|
+
if (extractMemberAccessFromQuery(query).length > 0)
|
|
464
|
+
return false;
|
|
465
|
+
if (queryAsNamedComponentAction(query))
|
|
466
|
+
return false;
|
|
467
|
+
return /悬停|\bhover\b|onHover|hoverEffect|HoverAnimation|HoverConstants/i.test(query);
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Framework decorator / ambient UI names — agents paste `@CustomDialog` etc.
|
|
471
|
+
* Keep real *Page/*Dialog types; drop these when counting UI surfaces / anchors.
|
|
472
|
+
*/
|
|
473
|
+
exports.FRAMEWORK_UI_DECORATOR_NAMES = new Set([
|
|
474
|
+
'customdialog', 'component', 'entry', 'builder', 'preview', 'observed', 'observable',
|
|
475
|
+
'state', 'prop', 'link', 'objectlink', 'provide', 'consume', 'watch', 'builderparam',
|
|
476
|
+
]);
|
|
477
|
+
function isFrameworkUiDecoratorName(name) {
|
|
478
|
+
return exports.FRAMEWORK_UI_DECORATOR_NAMES.has(name.toLowerCase());
|
|
479
|
+
}
|
|
480
|
+
/** PascalCase names that look like UI surfaces (Page / View / … / ThemeHome). */
|
|
481
|
+
function queryLooksLikeUiComponentType(name) {
|
|
482
|
+
// `@CustomDialog` / bare `Component` match the suffix regex but are not app Types.
|
|
483
|
+
if (isFrameworkUiDecoratorName(name))
|
|
484
|
+
return false;
|
|
485
|
+
return /(Button|Component|View|Page|Dialog|Bar|Item|Panel|Menu|Chip|Card|Home)$/i.test(name);
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* 2–3 concrete UI Types named together (Page+Dialog, View+Panel, …).
|
|
489
|
+
* Must stay on compact explore — full findRelevantContext is a 15–30k / multi-minute
|
|
490
|
+
* dump for what is a local composition / resource question.
|
|
491
|
+
*/
|
|
492
|
+
function queryAsFocusedUiCluster(query) {
|
|
493
|
+
if (queryAsMechanismSurvey(query) || queryAsCrossModuleFlowSurvey(query))
|
|
494
|
+
return false;
|
|
495
|
+
const types = extractTypeNamesFromQuery(query).filter((t) => queryLooksLikeUiComponentType(t) && !isFrameworkUiDecoratorName(t));
|
|
496
|
+
return types.length >= 2 && types.length <= 3;
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Named Page/Component overview: which UI children / where does it navigate /
|
|
500
|
+
* how does Page embed Dialog. Needs component bodies, not full-graph explore.
|
|
501
|
+
*/
|
|
502
|
+
function queryAsComponentSurfaceSurvey(query) {
|
|
503
|
+
if (queryAsFocusedUiCluster(query))
|
|
504
|
+
return true;
|
|
505
|
+
const types = extractTypeNamesFromQuery(query).filter((t) => !isFrameworkUiDecoratorName(t));
|
|
506
|
+
if (types.length < 1 || types.length > 3)
|
|
507
|
+
return false;
|
|
508
|
+
if (!types.some(queryLooksLikeUiComponentType))
|
|
509
|
+
return false;
|
|
510
|
+
if (/使用了哪些|哪些UI|哪些组件|UI组件|跳转到|可以跳转|内嵌|嵌入|preview|加载|page\s+navigation|which\s+(?:ui\s+)?components|navigat|embed/i.test(query)) {
|
|
511
|
+
return true;
|
|
512
|
+
}
|
|
513
|
+
// Bare / near-bare `ThemeHome` / `FooPage` — agents search("ThemeHome") for overview.
|
|
514
|
+
return queryIsTypeNameFocus(query);
|
|
515
|
+
}
|
|
285
516
|
/**
|
|
286
517
|
* In-repo kit/import **usage** inventory (call sites / which files import).
|
|
287
518
|
*/
|
|
@@ -292,11 +523,23 @@ function shouldBuildKitModuleUsageSurvey(query) {
|
|
|
292
523
|
&& extractImportSearchTerms(query).length === 0) {
|
|
293
524
|
return false;
|
|
294
525
|
}
|
|
295
|
-
return /依赖|引用|哪里用|哪些代码|哪里调用|哪些.*(?:依赖|引用|使用)|import\s+sites?|usages?\b|\buses\b|call\s*sites?/i.test(query)
|
|
526
|
+
return (/依赖|引用|哪里用|哪些代码|哪里调用|哪些.*(?:依赖|引用|使用)|import\s+sites?|usages?\b|\buses\b|call\s*sites?/i.test(query)
|
|
527
|
+
// "调用 Kit 需要额外安装哪些依赖 / how to install deps for Kit"
|
|
528
|
+
|| queryAsksKitInstallDeps(query));
|
|
529
|
+
}
|
|
530
|
+
/** "需要额外安装哪些依赖" — kit survey must include oh-package, not only imports. */
|
|
531
|
+
function queryAsksKitInstallDeps(query) {
|
|
532
|
+
return (/额外安装|还需.*依赖|需要.*依赖|引入.*依赖|其他参数和依赖|other\s+(?:params?.{0,24})?deps?/i.test(query)
|
|
533
|
+
|| /install(?:ing)?\s+(?:extra\s+)?deps?|which\s+deps?|need(?:s)?\s+(?:other\s+)?deps?/i.test(query));
|
|
296
534
|
}
|
|
297
535
|
/**
|
|
298
536
|
* Member-access patterns from a query — `obj.method`, `Type.method`, or `.member`.
|
|
537
|
+
* Skips `@kit.X` / `@ohos.X` module paths (those are imports, not Type.member).
|
|
299
538
|
*/
|
|
539
|
+
/** Shared-object / binary suffixes — not Type.member (libfoo.so → member "so"). */
|
|
540
|
+
const FILE_EXT_MEMBER_NOISE = new Set([
|
|
541
|
+
'so', 'dll', 'dylib', 'a', 'lib', 'exe', 'apk', 'hap', 'bin', 'wasm', 'o', 'obj',
|
|
542
|
+
]);
|
|
300
543
|
function extractMemberAccessFromQuery(query) {
|
|
301
544
|
const results = [];
|
|
302
545
|
const seen = new Set();
|
|
@@ -304,12 +547,21 @@ function extractMemberAccessFromQuery(query) {
|
|
|
304
547
|
const dotted = m[1];
|
|
305
548
|
if (!dotted || seen.has(dotted))
|
|
306
549
|
continue;
|
|
550
|
+
const idx = m.index ?? 0;
|
|
551
|
+
// `@kit.ArkTS` / `@ohos.foo` — module specifier, not receiver.member
|
|
552
|
+
if (idx > 0 && query[idx - 1] === '@')
|
|
553
|
+
continue;
|
|
554
|
+
if (/^(?:kit|ohos)\./i.test(dotted))
|
|
555
|
+
continue;
|
|
307
556
|
const parts = dotted.split('.');
|
|
308
557
|
if (parts.length < 2)
|
|
309
558
|
continue;
|
|
310
559
|
const member = parts[parts.length - 1];
|
|
311
560
|
if (member.length < 2)
|
|
312
561
|
continue;
|
|
562
|
+
// `libeffectrender.so` / `foo.dll` — not a member access.
|
|
563
|
+
if (FILE_EXT_MEMBER_NOISE.has(member.toLowerCase()))
|
|
564
|
+
continue;
|
|
313
565
|
seen.add(dotted);
|
|
314
566
|
results.push({
|
|
315
567
|
receiver: parts.slice(0, -1).join('.'),
|
|
@@ -319,12 +571,29 @@ function extractMemberAccessFromQuery(query) {
|
|
|
319
571
|
}
|
|
320
572
|
for (const m of query.matchAll(/\.([A-Za-z_][\w]*)\b/g)) {
|
|
321
573
|
const member = m[1];
|
|
574
|
+
const idx = m.index ?? 0;
|
|
575
|
+
// Skip the `.X` inside `@kit.X` / `@ohos.X`
|
|
576
|
+
const before = query.slice(0, idx);
|
|
577
|
+
if (/@(?:kit|ohos)$/i.test(before))
|
|
578
|
+
continue;
|
|
579
|
+
if (FILE_EXT_MEMBER_NOISE.has(member.toLowerCase()))
|
|
580
|
+
continue;
|
|
322
581
|
const dotted = `.${member}`;
|
|
323
582
|
if (seen.has(dotted))
|
|
324
583
|
continue;
|
|
325
584
|
seen.add(dotted);
|
|
326
585
|
results.push({ member, dotted });
|
|
327
586
|
}
|
|
587
|
+
// C++ / ArkTS qualified `Type::method` — same shape as dotted member access.
|
|
588
|
+
for (const m of query.matchAll(/\b([A-Za-z_][\w]*)::([A-Za-z_][\w]*)\b/g)) {
|
|
589
|
+
const receiver = m[1];
|
|
590
|
+
const member = m[2];
|
|
591
|
+
const dotted = `${receiver}::${member}`;
|
|
592
|
+
if (seen.has(dotted) || member.length < 2)
|
|
593
|
+
continue;
|
|
594
|
+
seen.add(dotted);
|
|
595
|
+
results.push({ receiver, member, dotted });
|
|
596
|
+
}
|
|
328
597
|
return results;
|
|
329
598
|
}
|
|
330
599
|
/** Terms for targeted import-node FTS (kit modules and their @kit.* paths). */
|
|
@@ -436,22 +705,49 @@ exports.STOP_WORDS = new Set([
|
|
|
436
705
|
* Lowercase API / import symbol names in a dependency question (taskpool, formInfo).
|
|
437
706
|
* Used to filter import sites to the symbol actually asked about, not every @kit.ArkTS import.
|
|
438
707
|
*/
|
|
708
|
+
/**
|
|
709
|
+
* Generic verbs agents put in rewritten how-implemented bags ("xml parse").
|
|
710
|
+
* Not useful as dependency/import inventory filters or local-detail anchors —
|
|
711
|
+
* they match every `parse`/`load` method and drown the distinctive token (xml).
|
|
712
|
+
*/
|
|
713
|
+
exports.GENERIC_VERB_ANCHOR_NOISE = new Set([
|
|
714
|
+
'parse', 'parsing', 'load', 'save', 'read', 'write', 'update', 'delete', 'create',
|
|
715
|
+
'init', 'handle', 'process', 'run', 'start', 'stop', 'open', 'close', 'convert',
|
|
716
|
+
'get', 'set', 'add', 'remove', 'list', 'show', 'find',
|
|
717
|
+
// Lifetime / allocator verbs — agents ask "where new/delete" and these must not
|
|
718
|
+
// become explore seeds (AnimateEx.new / RdbStoreHelper.delete).
|
|
719
|
+
'new', 'pointer', 'alloc', 'allocate', 'dealloc', 'deallocate', 'free', 'release',
|
|
720
|
+
// Inventory / NL fillers agents leave in rewritten bags (not real symbols).
|
|
721
|
+
'usage', 'usages', 'use', 'uses', 'using', 'api', 'apis', 'endpoint', 'endpoints',
|
|
722
|
+
'project', 'codebase', 'repo', 'documentation', 'document', 'docs', '说明',
|
|
723
|
+
// Shared-lib / GL thread NL leftovers (not symbols).
|
|
724
|
+
'context', 'opengl', 'gles', 'glesv3', 'egl',
|
|
725
|
+
]);
|
|
439
726
|
function extractDependencySymbolsFromQuery(query) {
|
|
440
727
|
const symbols = new Set();
|
|
441
728
|
for (const ma of extractMemberAccessFromQuery(query)) {
|
|
442
729
|
if (ma.member.length >= 3 && !exports.STOP_WORDS.has(ma.member.toLowerCase())) {
|
|
443
|
-
|
|
730
|
+
if (!exports.GENERIC_VERB_ANCHOR_NOISE.has(ma.member.toLowerCase()))
|
|
731
|
+
symbols.add(ma.member);
|
|
444
732
|
}
|
|
445
733
|
}
|
|
446
|
-
for (const
|
|
734
|
+
for (const f of extractFieldLikeSymbolsFromQuery(query))
|
|
735
|
+
symbols.add(f);
|
|
736
|
+
// ≥3-char lowercase tokens (includes xml); drop generic verbs.
|
|
737
|
+
for (const m of query.matchAll(/\b([a-z][a-zA-Z0-9]{2,})\b/g)) {
|
|
447
738
|
const sym = m[1];
|
|
448
|
-
if (
|
|
449
|
-
|
|
739
|
+
if (exports.STOP_WORDS.has(sym.toLowerCase()))
|
|
740
|
+
continue;
|
|
741
|
+
if (exports.GENERIC_VERB_ANCHOR_NOISE.has(sym.toLowerCase()))
|
|
742
|
+
continue;
|
|
743
|
+
symbols.add(sym);
|
|
450
744
|
}
|
|
451
745
|
// Lowercase API tokens (statfs, napi_wrap) when the query is clearly about code.
|
|
452
746
|
if (queryMentionsCodeContext(query)) {
|
|
453
747
|
for (const m of query.matchAll(/\b([a-z][a-z0-9_]{4,})\b/g)) {
|
|
454
748
|
const sym = m[1];
|
|
749
|
+
if (exports.GENERIC_VERB_ANCHOR_NOISE.has(sym))
|
|
750
|
+
continue;
|
|
455
751
|
if (!exports.STOP_WORDS.has(sym) && isDistinctiveIdentifier(sym))
|
|
456
752
|
symbols.add(sym);
|
|
457
753
|
else if (!exports.STOP_WORDS.has(sym) && sym.length >= 6)
|
|
@@ -495,7 +791,252 @@ function hasImportInventoryFilter(query) {
|
|
|
495
791
|
}
|
|
496
792
|
/** Where-is-API-used / call-site intent (statfs, snake_case APIs, "哪里使用了 X"). */
|
|
497
793
|
function queryAsApiUsageSurvey(query) {
|
|
498
|
-
return (/哪里使用|何处使用|哪些地方使用|在哪里使用|什么地方使用|项目中.*使用|使用了.*API|API端点|调用.*API
|
|
794
|
+
return (/哪里使用|何处使用|哪些地方使用|在哪里使用|什么地方使用|项目中.*使用|使用了.*API|API端点|调用.*API|使用了哪些调用|哪些调用方法|调用方法|使用了哪些方法|哪些组件使用|哪些.*使用了|使用了\s*\.|自定义绘制|where\s+(?:is|are).+(?:used|called)|which\s+(?:files?|code|components?)\s+(?:use|call)/i.test(query)
|
|
795
|
+
// Agent rewrites (Telephony API usages / call methods in the project).
|
|
796
|
+
|| /\bAPI\s+usages?\b/i.test(query)
|
|
797
|
+
|| /\busages?\s+(?:of|for|in)\b/i.test(query)
|
|
798
|
+
|| /\bcall\s+methods?\b/i.test(query)
|
|
799
|
+
|| /\b(?:used|called)\s+(?:methods?|APIs?)\b/i.test(query)
|
|
800
|
+
|| /\bin(?:\s+the)?\s+project\b.{0,40}\b(?:API|usages?|methods?|calls?)\b/i.test(query)
|
|
801
|
+
|| /\b(?:API|usages?|methods?|calls?)\b.{0,40}\bin(?:\s+the)?\s+project\b/i.test(query));
|
|
802
|
+
}
|
|
803
|
+
/**
|
|
804
|
+
* Member / field symbols agents paste for cross-file usage hunts (`m_eglMutex`,
|
|
805
|
+
* `drawModifier`). Distinct from PascalCase Types.
|
|
806
|
+
*/
|
|
807
|
+
function extractFieldLikeSymbolsFromQuery(query) {
|
|
808
|
+
const out = new Set();
|
|
809
|
+
for (const m of query.matchAll(/\b(m_[A-Za-z][\w]{2,})\b/g)) {
|
|
810
|
+
if (m[1])
|
|
811
|
+
out.add(m[1]);
|
|
812
|
+
}
|
|
813
|
+
for (const m of query.matchAll(/\b([A-Za-z][\w]*(?:Mutex|Lock))\b/g)) {
|
|
814
|
+
if (m[1] && m[1].length >= 4)
|
|
815
|
+
out.add(m[1]);
|
|
816
|
+
}
|
|
817
|
+
return [...out];
|
|
818
|
+
}
|
|
819
|
+
/** Named Type + declaration / id / native-binding sites across files. */
|
|
820
|
+
function queryAsDeclarationSiteSurvey(query) {
|
|
821
|
+
const types = extractTypeNamesFromQuery(query).filter((t) => !isFrameworkUiDecoratorName(t));
|
|
822
|
+
if (types.length < 1 || types.length > 3)
|
|
823
|
+
return false;
|
|
824
|
+
return (/在哪些文件|哪些文件.*(?:声明|定义|出现)|被声明|声明了|id\s*分别|各自绑定|绑定到|which\s+files?.{0,80}(?:declar|defin|appear)|where\s+(?:is|are).{0,40}declar/i.test(query)
|
|
825
|
+
// Agent English rewrites: "XComponent declaration id native render binding"
|
|
826
|
+
|| /\bdeclarations?\b/i.test(query)
|
|
827
|
+
|| /\bdeclared\b/i.test(query)
|
|
828
|
+
|| (/\bids?\b/i.test(query) && /\b(?:bind|binding|native|renderer|xcomponent)\b/i.test(query)));
|
|
829
|
+
}
|
|
830
|
+
/**
|
|
831
|
+
* How-to get a system setting/capability *as used in this repo* (language/locale/…).
|
|
832
|
+
* Must NOT become a light-mechanism dump of every `language` import.
|
|
833
|
+
*/
|
|
834
|
+
function queryAsInRepoSystemCapabilityHowto(query) {
|
|
835
|
+
if (extractTypeNamesFromQuery(query).some((t) => /Manager|Service|Controller/i.test(t))) {
|
|
836
|
+
// Named Manager data-source / lifecycle owns those questions.
|
|
837
|
+
if (queryAsDataSourceSurvey(query) || queryAsTypeLifecycleSurvey(query))
|
|
838
|
+
return false;
|
|
839
|
+
}
|
|
840
|
+
return (/如何获取系统|怎样获取系统|怎么获取系统|获取系统当前|系统当前设置|系统.*语言|当前设置的语言/i.test(query)
|
|
841
|
+
|| /how\s+to\s+get\s+(?:the\s+)?system\s+(?:language|locale|setting)/i.test(query)
|
|
842
|
+
|| (/\b(?:language|locale|i18n)\b/i.test(query)
|
|
843
|
+
&& /(?:获取|当前设置|get\s+system|system\s+(?:language|locale))/i.test(query)));
|
|
844
|
+
}
|
|
845
|
+
/**
|
|
846
|
+
* "Who uses the return value of Type.member / fn" — callers of the member, not a
|
|
847
|
+
* create→get flow dump or an import flood on leftover words like `state`.
|
|
848
|
+
*/
|
|
849
|
+
function queryAsReturnValueConsumerSurvey(query) {
|
|
850
|
+
const hasMember = extractMemberAccessFromQuery(query).length > 0
|
|
851
|
+
|| extractLocalDetailAnchors(query).some((n) => isMemberLikeIdentifier(n));
|
|
852
|
+
if (!hasMember && extractTypeNamesFromQuery(query).length === 0)
|
|
853
|
+
return false;
|
|
854
|
+
return (/返回结果被|返回值.*(?:被|由).*(?:使用|调用)|其返回.*使用|返回结果.*哪些/i.test(query)
|
|
855
|
+
|| /who\s+uses\s+the\s+(?:return|result)|return(?:ed)?\s+(?:value|result).{0,80}(?:used|consum)/i.test(query)
|
|
856
|
+
|| /哪些其他函数使用|被项目中哪些.{0,20}函数使用|which\s+(?:other\s+)?functions?\s+use/i.test(query));
|
|
857
|
+
}
|
|
858
|
+
/** ALL_CAPS constants — where used / which scenarios (not "what does this macro mean"). */
|
|
859
|
+
function queryAsConstantUsageSurvey(query) {
|
|
860
|
+
const caps = [...query.matchAll(/\b([A-Z][A-Z0-9]*(?:_[A-Z0-9]+)+)\b/g)].map((m) => m[1]);
|
|
861
|
+
// Enum-style `Type.MEMBER` / `audio.Type.RINGTONE` — ALL_CAPS member (with or without `_`).
|
|
862
|
+
const dottedCaps = [
|
|
863
|
+
...query.matchAll(/\.[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*\b/g),
|
|
864
|
+
]
|
|
865
|
+
.map((m) => m[0].slice(1))
|
|
866
|
+
.filter((s) => s === s.toUpperCase() && s.length >= 3);
|
|
867
|
+
const all = [...new Set([...caps, ...dottedCaps])];
|
|
868
|
+
if (all.length === 0)
|
|
869
|
+
return false;
|
|
870
|
+
return /用于|场景|哪里用|哪些.*用|依赖|调用|where\s+(?:is|are).+used|which\s+(?:scenarios?|functions?)|what\s+(?:are\s+)?(?:they|these)\s+for|which\s+methods?.{0,20}(?:call|depend)/i.test(query);
|
|
871
|
+
}
|
|
872
|
+
/** Field / mutex / lock — which other functions also touch it. */
|
|
873
|
+
function queryAsFieldUsageSurvey(query) {
|
|
874
|
+
if (extractFieldLikeSymbolsFromQuery(query).length === 0)
|
|
875
|
+
return false;
|
|
876
|
+
return (/哪些函数|还会用到|用到这个|哪些.*(?:用到|使用)|who\s+(?:else\s+)?(?:uses|locks)|which\s+functions?.{0,40}(?:use|lock|mutex)|\bmutex\b|这[个把]锁/i.test(query)
|
|
877
|
+
// Lifetime: where is m_foo new'd / delete'd / freed.
|
|
878
|
+
|| /new\s*出来|被\s*new|delete\s*掉|被\s*delete|new\s*\/\s*delete|(?:哪里|哪些地方).{0,12}(?:new|delete)|(?:new|delete).{0,20}(?:哪里|哪些)|被释放|释放掉|allocat|deallocat|where.{0,40}(?:new|delete|allocat|free)/i.test(query));
|
|
879
|
+
}
|
|
880
|
+
/**
|
|
881
|
+
* Native shared lib + GL/EGL thread questions (`libfoo.so` … OpenGL … 哪个线程).
|
|
882
|
+
* Light-mechanism (CMake + EGLCore/PluginRender), not `.so` member survey.
|
|
883
|
+
*/
|
|
884
|
+
function queryAsNativeRenderThreadSurvey(query) {
|
|
885
|
+
const hasLib = /\b\w+\.(?:so|dll|dylib)\b/i.test(query)
|
|
886
|
+
|| /\blib\w+\b/i.test(query);
|
|
887
|
+
const hasGl = /\b(?:GLES(?:v3)?|EGL|OpenGL)\b/i.test(query);
|
|
888
|
+
const hasThread = /线程|thread|UI\s*线程|主线程|JS\s*主?线程/i.test(query);
|
|
889
|
+
return (hasLib || hasGl) && hasThread;
|
|
890
|
+
}
|
|
891
|
+
/** Named `.d.ts` wrap — what calls / imports it in-repo. */
|
|
892
|
+
function queryAsDtsWrapSurvey(query) {
|
|
893
|
+
if (!/\.d\.ts\b/i.test(query) && extractFileBasenamesFromQuery(query).length === 0) {
|
|
894
|
+
return false;
|
|
895
|
+
}
|
|
896
|
+
if (!/\.d\.ts\b/i.test(query))
|
|
897
|
+
return false;
|
|
898
|
+
return /封装|wrap(?:s|ped)?|调用|哪里|功能|where|called|uses?|import/i.test(query);
|
|
899
|
+
}
|
|
900
|
+
/**
|
|
901
|
+
* Assigned flag / boolean field impact on later call timing
|
|
902
|
+
* (`isChangeSurface = true` … 如何影响 … 时序).
|
|
903
|
+
*/
|
|
904
|
+
function queryAsAssignedFlagImpactSurvey(query) {
|
|
905
|
+
const hasAssign = /=\s*(?:true|false)\b/i.test(query)
|
|
906
|
+
|| /设置\s*\w+.*=/.test(query)
|
|
907
|
+
|| /里设置\s+\w+/i.test(query)
|
|
908
|
+
|| /\bsets?\s+\w+\s*=\s*(?:true|false)\b/i.test(query);
|
|
909
|
+
const hasImpact = /影响|时序|后续|how\s+(?:does|will).{0,40}affect|affect.{0,40}timing/i.test(query);
|
|
910
|
+
if (!hasAssign || !hasImpact)
|
|
911
|
+
return false;
|
|
912
|
+
return extractLocalDetailAnchors(query).length >= 1;
|
|
913
|
+
}
|
|
914
|
+
/**
|
|
915
|
+
* Named Toggle/control kept consistent across surfaces — which module guarantees it.
|
|
916
|
+
*/
|
|
917
|
+
function queryAsNamedControlStateSyncSurvey(query) {
|
|
918
|
+
const types = extractTypeNamesFromQuery(query).filter((t) => !isFrameworkUiDecoratorName(t));
|
|
919
|
+
if (types.length < 1 || types.length > 2)
|
|
920
|
+
return false;
|
|
921
|
+
return (/状态一致|保持一致|三处|哪个模块保证|who\s+keeps|consistent\s+state|state\s+sync|guarantees?\s+it|which\s+module\s+guarantees/i.test(query)
|
|
922
|
+
|| (/Toggle|Switch|开关/.test(query) && /一致|保证|模块|consistent|guarantees?/i.test(query)));
|
|
923
|
+
}
|
|
924
|
+
/**
|
|
925
|
+
* Methods listed beside a Type for caller inventories
|
|
926
|
+
* (`BinaryGrid … Set、Test 或 Fill` — including short verbs normally treated as noise).
|
|
927
|
+
*/
|
|
928
|
+
function extractListedTypeMethodsFromQuery(query) {
|
|
929
|
+
if (!queryAsCallerOrMethodSurvey(query))
|
|
930
|
+
return [];
|
|
931
|
+
const types = extractTypeNamesFromQuery(query);
|
|
932
|
+
if (types.length === 0)
|
|
933
|
+
return [];
|
|
934
|
+
// Owning Type(s): longer CamelCase — short Set/Test/Fill are method tokens, not owners.
|
|
935
|
+
const owners = new Set(types.filter((t) => t.length >= 6 || /(?:Grid|Manager|Service|Controller|Render|Plugin|Layout)/i.test(t)));
|
|
936
|
+
if (owners.size === 0) {
|
|
937
|
+
// Fall back to longest type name as owner.
|
|
938
|
+
const longest = [...types].sort((a, b) => b.length - a.length)[0];
|
|
939
|
+
if (longest)
|
|
940
|
+
owners.add(longest);
|
|
941
|
+
}
|
|
942
|
+
const out = new Set();
|
|
943
|
+
// `Set、Test 或 Fill` / `Set, Test, or Fill` — list of PascalCase methods.
|
|
944
|
+
for (const m of query.matchAll(/\b([A-Z][A-Za-z0-9]{1,})(?:\s*[、,]\s*([A-Z][A-Za-z0-9]{1,}))+(?:\s*(?:或|or)\s*([A-Z][A-Za-z0-9]{1,}))?/g)) {
|
|
945
|
+
for (let i = 1; i < m.length; i++) {
|
|
946
|
+
const name = m[i];
|
|
947
|
+
if (name && !owners.has(name) && name.length >= 2)
|
|
948
|
+
out.add(name);
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
// `的 Set` / `methods Set` / `调用了 Set` (owner already required above).
|
|
952
|
+
for (const m of query.matchAll(/(?:的|of|模板类的|类的|methods?)\s+([A-Z][A-Za-z0-9]{1,})\b/g)) {
|
|
953
|
+
const name = m[1];
|
|
954
|
+
if (!owners.has(name) && name.length >= 2)
|
|
955
|
+
out.add(name);
|
|
956
|
+
}
|
|
957
|
+
return [...out].slice(0, 8);
|
|
958
|
+
}
|
|
959
|
+
/** Path module + NAPI / exported API surface (or named Type + NAPI/expose). */
|
|
960
|
+
function queryAsModuleExportSurvey(query) {
|
|
961
|
+
const napi = /NAPI|napi|暴露了哪些|暴露哪些|暴露给|expose(?:d|s)?\s+to|napi_module_register|哪些\s*API|API\s*接口|exports?\s+(?:which|what)|which\s+(?:APIs?|exports?)/i.test(query);
|
|
962
|
+
if (!napi)
|
|
963
|
+
return false;
|
|
964
|
+
if (extractPathSegmentsFromQuery(query).length > 0)
|
|
965
|
+
return true;
|
|
966
|
+
// "LayoutRotatePacking … NAPI expose to ArkTS" — no path segment required.
|
|
967
|
+
if (extractTypeNamesFromQuery(query).length > 0)
|
|
968
|
+
return true;
|
|
969
|
+
return false;
|
|
970
|
+
}
|
|
971
|
+
/** Multi-module path interdependence (A/B/C… mutual deps). */
|
|
972
|
+
function queryAsModuleDependencySurvey(query) {
|
|
973
|
+
const paths = extractPathSegmentsFromQuery(query);
|
|
974
|
+
const moduleTokens = query.match(/\b[A-Za-z][\w]*(?:common|service|component|constants)\b/gi) ?? [];
|
|
975
|
+
const circular = /循环依赖|circular\s+depend|互为依赖/i.test(query);
|
|
976
|
+
// "commonconstants … 循环依赖" — one module token + cycle intent is enough.
|
|
977
|
+
if (circular && (paths.length + moduleTokens.length >= 1 || /\b[a-z][a-z0-9_]{5,}\b/.test(query))) {
|
|
978
|
+
return true;
|
|
979
|
+
}
|
|
980
|
+
if (paths.length + moduleTokens.length < 2)
|
|
981
|
+
return false;
|
|
982
|
+
return /相互依赖|互相依赖|之间.*依赖|依赖关系|depend(?:ency|encies| on each other)|cross-?depend/i.test(query);
|
|
983
|
+
}
|
|
984
|
+
/**
|
|
985
|
+
* Single named Type + state/lifecycle/callback surface — needs the type body,
|
|
986
|
+
* not a thin callers stub.
|
|
987
|
+
*/
|
|
988
|
+
/**
|
|
989
|
+
* Repo-wide literal / copy / "imported text object" hunts — Grep territory.
|
|
990
|
+
* Shape-only: no PascalCase Type / file / member / kit anchors.
|
|
991
|
+
*/
|
|
992
|
+
function queryLooksLikeLiteralOrCopyHunt(query) {
|
|
993
|
+
if (extractTypeNamesFromQuery(query).length > 0)
|
|
994
|
+
return false;
|
|
995
|
+
if (extractFileBasenamesFromQuery(query).length > 0)
|
|
996
|
+
return false;
|
|
997
|
+
if (extractMemberAccessFromQuery(query).length > 0)
|
|
998
|
+
return false;
|
|
999
|
+
if (extractKitModuleNamesFromQuery(query).length > 0)
|
|
1000
|
+
return false;
|
|
1001
|
+
if (extractFieldLikeSymbolsFromQuery(query).length > 0)
|
|
1002
|
+
return false;
|
|
1003
|
+
return (/全仓|全搜|字面量|中文\s*(?:text|字符串)|绑了.*(?:text|文案)|literal\s+strings?/i.test(query)
|
|
1004
|
+
|| /从.{0,16}包.{0,40}(?:导入|import).{0,20}\btext\b|导入的\s*text\s*对象|imported\s+text\s+objects?/i.test(query));
|
|
1005
|
+
}
|
|
1006
|
+
function queryAsTypeLifecycleSurvey(query) {
|
|
1007
|
+
if (queryAsCrossModuleFlowSurvey(query))
|
|
1008
|
+
return false;
|
|
1009
|
+
// "状态来源" is a data-source inventory, not a lifecycle body dump.
|
|
1010
|
+
if (/状态来源|status\s+source|state\s+source/i.test(query))
|
|
1011
|
+
return false;
|
|
1012
|
+
// Release ↔ destructor compare may name CB + Manager + Render.
|
|
1013
|
+
if (/析构|destructor/i.test(query)
|
|
1014
|
+
&& /Release|做了哪些|有没有重复|跟.+做的事|same\s+(?:work|things?)|overlap/i.test(query)) {
|
|
1015
|
+
return extractLocalDetailAnchors(query).length >= 1;
|
|
1016
|
+
}
|
|
1017
|
+
const types = extractTypeNamesFromQuery(query).filter((t) => !isFrameworkUiDecoratorName(t));
|
|
1018
|
+
if (types.length < 1 || types.length > 2)
|
|
1019
|
+
return false;
|
|
1020
|
+
return /状态机|状态变化|状态转换|状态.*回调|回调.*状态|foreground|background|lifecycle|state\s*machine|哪些状态|state\s+change|how\s+(?:are|is)\s+.+states?\s+(?:unified|distinguished)/i.test(query);
|
|
1021
|
+
}
|
|
1022
|
+
/**
|
|
1023
|
+
* Member-access inventory ("which files use .drawModifier") — not Type×method
|
|
1024
|
+
* interaction / Export fail wiring / Release↔dtor (those need compact bodies).
|
|
1025
|
+
*/
|
|
1026
|
+
function shouldPreferMemberUsageInventory(query) {
|
|
1027
|
+
if (queryAsCoNamedTypeMethodInteraction(query))
|
|
1028
|
+
return false;
|
|
1029
|
+
if (queryAsTypeLifecycleSurvey(query))
|
|
1030
|
+
return false;
|
|
1031
|
+
if (queryAsFieldUsageSurvey(query))
|
|
1032
|
+
return true;
|
|
1033
|
+
if (extractMemberAccessFromQuery(query).length === 0)
|
|
1034
|
+
return false;
|
|
1035
|
+
// Conditional wiring / interaction / purpose → compact, not member-file list.
|
|
1036
|
+
if (/失败时|还会被|是怎么|交互|析构|destructor|做了哪些|什么作用|做什么|purpose|what\s+does/i.test(query)) {
|
|
1037
|
+
return false;
|
|
1038
|
+
}
|
|
1039
|
+
return /哪些|哪里|where|which|使用了|谁用|call\s*sites?/i.test(query);
|
|
499
1040
|
}
|
|
500
1041
|
/** API / SDK tokens named in the query — lowercase deps + PascalCase modules (Telephony). */
|
|
501
1042
|
function extractApiUsageTokens(query) {
|
|
@@ -505,18 +1046,46 @@ function extractApiUsageTokens(query) {
|
|
|
505
1046
|
tokens.add(d);
|
|
506
1047
|
}
|
|
507
1048
|
for (const t of extractTypeNamesFromQuery(query)) {
|
|
508
|
-
if (t.length >= 4)
|
|
1049
|
+
if (t.length >= 4 && !isFrameworkUiDecoratorName(t))
|
|
509
1050
|
tokens.add(t);
|
|
510
1051
|
}
|
|
511
|
-
|
|
1052
|
+
for (const ma of extractMemberAccessFromQuery(query)) {
|
|
1053
|
+
if (ma.member.length >= 3)
|
|
1054
|
+
tokens.add(ma.member);
|
|
1055
|
+
}
|
|
1056
|
+
for (const f of extractFieldLikeSymbolsFromQuery(query))
|
|
1057
|
+
tokens.add(f);
|
|
1058
|
+
for (const m of query.matchAll(/\b([A-Z][A-Z0-9]*(?:_[A-Z0-9]+)+)\b/g)) {
|
|
1059
|
+
if (m[1] && m[1].length >= 6)
|
|
1060
|
+
tokens.add(m[1]);
|
|
1061
|
+
}
|
|
1062
|
+
// When a PascalCase SDK/module token is present (Telephony, DrawContext), drop
|
|
1063
|
+
// short lowercase bag noise agents add (`call`/`radio`/`usage`) — those flood
|
|
1064
|
+
// false-positive files and tank precision.
|
|
1065
|
+
const primary = [...tokens].filter((t) => (/^[A-Z]/.test(t) && t.length >= 4)
|
|
1066
|
+
|| t.startsWith('@')
|
|
1067
|
+
|| /^(?:statfs|napi_\w+)$/i.test(t)
|
|
1068
|
+
|| extractFieldLikeSymbolsFromQuery(query).includes(t)
|
|
1069
|
+
|| extractMemberAccessFromQuery(query).some((m) => m.member === t || m.dotted === t));
|
|
1070
|
+
if (primary.length > 0)
|
|
1071
|
+
return primary.slice(0, 8);
|
|
1072
|
+
return [...tokens].filter((t) => t.length >= 4 && !exports.GENERIC_VERB_ANCHOR_NOISE.has(t.toLowerCase())).slice(0, 8);
|
|
512
1073
|
}
|
|
513
1074
|
function shouldBuildApiUsageSurvey(query) {
|
|
1075
|
+
// Declaration-site surveys have their own section — do NOT also claim API-usage
|
|
1076
|
+
// (that used to fire after an empty declaration scan and dump include hits).
|
|
1077
|
+
if (queryAsDeclarationSiteSurvey(query))
|
|
1078
|
+
return false;
|
|
1079
|
+
if (queryAsConstantUsageSurvey(query))
|
|
1080
|
+
return true;
|
|
1081
|
+
if (queryAsFieldUsageSurvey(query))
|
|
1082
|
+
return true;
|
|
514
1083
|
return queryAsApiUsageSurvey(query) && extractApiUsageTokens(query).length > 0;
|
|
515
1084
|
}
|
|
516
1085
|
/** Caller / method survey intent — not every PascalCase token. */
|
|
517
1086
|
function queryAsCallerOrMethodSurvey(query) {
|
|
518
|
-
return (
|
|
519
|
-
|| /哪些方法|which\s+methods|methods?\s+(?:are\s+)?called/i.test(query)
|
|
1087
|
+
return (/哪里调用|何处调用|谁调用|调用了|被调用|callers?\s+of|who\s+calls|called\s+by|哪些.*调用|外部.*调用|\bexternal\b/i.test(query)
|
|
1088
|
+
|| /哪些方法|which\s+methods|methods?\s+(?:are\s+)?called|which\s+files?.{0,20}(?:call|invoke)/i.test(query)
|
|
520
1089
|
// Agents often write "Type … methods … callers" / bare "callers" without "of".
|
|
521
1090
|
|| /\bcallers?\b/i.test(query)
|
|
522
1091
|
|| /methods?.{0,40}\bcall/i.test(query));
|
|
@@ -563,6 +1132,9 @@ function shouldBuildCallerInventory(query) {
|
|
|
563
1132
|
&& /使用了哪些调用|哪些调用方法|调用方法|使用了哪些方法/.test(query)) {
|
|
564
1133
|
return false;
|
|
565
1134
|
}
|
|
1135
|
+
// Return-value consumers: list callers of the named member/fn.
|
|
1136
|
+
if (queryAsReturnValueConsumerSurvey(query))
|
|
1137
|
+
return true;
|
|
566
1138
|
// Require real caller/method intent — bare PascalCase alone is NOT enough
|
|
567
1139
|
// (that emptied inventory → blocked compact → 15K full explore on callbacks).
|
|
568
1140
|
return queryAsCallerOrMethodSurvey(query);
|
|
@@ -570,24 +1142,55 @@ function shouldBuildCallerInventory(query) {
|
|
|
570
1142
|
/** Symbols to list callers for — types, free functions (SortWidgets), snake_case APIs. */
|
|
571
1143
|
function extractCallerSurveySymbols(query) {
|
|
572
1144
|
const names = new Set(extractTypeNamesFromQuery(query));
|
|
573
|
-
|
|
574
|
-
|
|
1145
|
+
const wantMembers = queryAsCallerOrMethodSurvey(query) || queryAsReturnValueConsumerSurvey(query);
|
|
1146
|
+
if (!wantMembers)
|
|
1147
|
+
return [...names].filter((n) => n.length >= 3);
|
|
575
1148
|
for (const d of extractDependencySymbolsFromQuery(query)) {
|
|
576
1149
|
if (d.length >= 4)
|
|
577
1150
|
names.add(d);
|
|
578
1151
|
}
|
|
579
|
-
|
|
1152
|
+
for (const ma of extractMemberAccessFromQuery(query)) {
|
|
1153
|
+
names.add(ma.member);
|
|
1154
|
+
if (ma.receiver)
|
|
1155
|
+
names.add(ma.receiver);
|
|
1156
|
+
}
|
|
1157
|
+
for (const a of extractLocalDetailAnchors(query)) {
|
|
1158
|
+
if (isMemberLikeIdentifier(a) || /^(?:get|set|is|has|create|on)[A-Z]/.test(a)) {
|
|
1159
|
+
names.add(a);
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
// Type + listed methods (BinaryGrid Set/Test/Fill) — keep short verbs co-named with a Type.
|
|
1163
|
+
for (const m of extractListedTypeMethodsFromQuery(query))
|
|
1164
|
+
names.add(m);
|
|
1165
|
+
// "通过 getConnectionState 获取…" — bare camelCase after 通过/via is the consumer target.
|
|
1166
|
+
for (const m of query.matchAll(/(?:通过|经由|via|using|call(?:ing)?)\s*([a-z][a-zA-Z0-9]{3,})\b/g)) {
|
|
1167
|
+
if (m[1] && (/^(?:get|set|is|has|create|on)[A-Z]/.test(m[1]) || isMemberLikeIdentifier(m[1]))) {
|
|
1168
|
+
names.add(m[1]);
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
const all = [...names].filter((n) => n.length >= 3);
|
|
1172
|
+
if (!queryAsReturnValueConsumerSurvey(query))
|
|
1173
|
+
return all;
|
|
1174
|
+
// Prefer the member whose return value is consumed over a preceding create/factory.
|
|
1175
|
+
const preferred = all.filter((n) => /^(?:get|is|has)[A-Z]/.test(n) || /State|Result|Status|Value$/i.test(n));
|
|
1176
|
+
if (preferred.length === 0)
|
|
1177
|
+
return all;
|
|
1178
|
+
const rest = all.filter((n) => !preferred.includes(n));
|
|
1179
|
+
return [...preferred, ...rest];
|
|
580
1180
|
}
|
|
581
1181
|
/** Cross-module call-chain intent (A → B → engine). */
|
|
582
1182
|
function queryAsCrossModuleFlowSurvey(query) {
|
|
583
1183
|
const types = extractTypeNamesFromQuery(query);
|
|
584
1184
|
if (types.length < 2)
|
|
585
1185
|
return false;
|
|
586
|
-
|
|
1186
|
+
// Note: bare 渲染 alone is too common (flag-impact / UI surface) — require a
|
|
1187
|
+
// real cross-hop cue with it.
|
|
1188
|
+
return (/经过|跨模块|调用链|链路|流程|到达|落到|再到|落盘|then\s+to|across\s+modules/i.test(query)
|
|
1189
|
+
|| (/渲染/.test(query) && /跨模块|经过|再到|落到|链路|call\s*chain/i.test(query)));
|
|
587
1190
|
}
|
|
588
1191
|
/** Data-source / upstream-service intent (来源于哪个服务 / which service). */
|
|
589
1192
|
function queryAsDataSourceSurvey(query) {
|
|
590
|
-
return
|
|
1193
|
+
return /来源于|数据来源|状态来源|来自哪个|哪个系统服务|来自什么服务|data\s+source|status\s+source|state\s+source|which\s+service|来源.*服务|如何统一或区分/i.test(query);
|
|
591
1194
|
}
|
|
592
1195
|
/**
|
|
593
1196
|
* Local one/few-symbol behavior or contract — NOT multi-file mechanism / inventory.
|
|
@@ -611,6 +1214,8 @@ function extractLocalDetailAnchors(query) {
|
|
|
611
1214
|
if (m[1] && m[1].length >= 4)
|
|
612
1215
|
names.add(m[1]);
|
|
613
1216
|
}
|
|
1217
|
+
for (const f of extractFieldLikeSymbolsFromQuery(query))
|
|
1218
|
+
names.add(f);
|
|
614
1219
|
// Drop path/extension/verb noise that long NL explores otherwise seed on
|
|
615
1220
|
// (`cpp`, `calls`, `include`, `render`…) — that ballooned neighbor fan-out.
|
|
616
1221
|
const ANCHOR_NOISE = new Set([
|
|
@@ -619,6 +1224,16 @@ function extractLocalDetailAnchors(query) {
|
|
|
619
1224
|
'calls', 'call', 'calling', 'called', 'callers', 'caller', 'include', 'includes', 'import', 'imports',
|
|
620
1225
|
'render', 'frame', 'sync', 'thread', 'subthread', 'layout', 'method', 'methods',
|
|
621
1226
|
'function', 'functions', 'file', 'files', 'src', 'main', 'define', 'visible',
|
|
1227
|
+
'usage', 'usages', 'api', 'apis', 'project', 'codebase', 'repo',
|
|
1228
|
+
'language', 'locale', 'i18n', 'radio', 'state', 'communication', 'binding',
|
|
1229
|
+
'renderer', 'native', 'declaration', 'declarations', 'declared',
|
|
1230
|
+
// Generic UI nouns agents leave in NL (not the PascalCase Type).
|
|
1231
|
+
'dialog', 'page', 'view', 'button', 'component', 'card', 'icon', 'background',
|
|
1232
|
+
'animation', 'hover', 'preview', 'image', 'resource', 'network', 'application',
|
|
1233
|
+
'text', 'layout', 'layouts', 'string', 'strings', 'constant', 'constants',
|
|
1234
|
+
// Shared-lib / GL leftovers after stripping `.so`.
|
|
1235
|
+
'so', 'dll', 'dylib', 'libeffectrender', 'glesv3', 'opengl', 'context',
|
|
1236
|
+
...exports.GENERIC_VERB_ANCHOR_NOISE,
|
|
622
1237
|
]);
|
|
623
1238
|
const ranked = [...names].filter((n) => n.length >= 3 && !ANCHOR_NOISE.has(n.toLowerCase()));
|
|
624
1239
|
// Prefer PascalCase / dotted members first — they're the real anchors.
|
|
@@ -626,7 +1241,13 @@ function extractLocalDetailAnchors(query) {
|
|
|
626
1241
|
const score = (s) => (/^[A-Z]/.test(s) ? 2 : 0) + (s.includes('.') ? 1 : 0) + Math.min(s.length, 20) / 20;
|
|
627
1242
|
return score(b) - score(a) || a.localeCompare(b);
|
|
628
1243
|
});
|
|
629
|
-
|
|
1244
|
+
// Drop framework decorator names when a concrete UI Type is also present
|
|
1245
|
+
// (`@CustomDialog` + WallpaperApplyDialog → keep only the Apply* types).
|
|
1246
|
+
const hasConcreteUi = ranked.some((n) => queryLooksLikeUiComponentType(n) && !isFrameworkUiDecoratorName(n));
|
|
1247
|
+
const filtered = hasConcreteUi
|
|
1248
|
+
? ranked.filter((n) => !isFrameworkUiDecoratorName(n))
|
|
1249
|
+
: ranked;
|
|
1250
|
+
return filtered.slice(0, 4);
|
|
630
1251
|
}
|
|
631
1252
|
/**
|
|
632
1253
|
* Caller survey that also asks how a co-named type becomes visible / used.
|
|
@@ -638,8 +1259,8 @@ function queryNeedsCoNamedUseBridge(query) {
|
|
|
638
1259
|
const anchors = extractLocalDetailAnchors(query);
|
|
639
1260
|
if (anchors.length < 2)
|
|
640
1261
|
return false;
|
|
641
|
-
// Narrow intent
|
|
642
|
-
return /定义可见|确保.*可见|头文件可见|definition\s+visible|visible\s+definition|how\s+.+\s+visible
|
|
1262
|
+
// Narrow intent — how a co-named type becomes visible / included.
|
|
1263
|
+
return /定义可见|确保.*可见|头文件可见|definition\s+visible|visible\s+definition|how\s+.+\s+visible|makes?\s+.+\s+visible|如何确保.*可见/i.test(query);
|
|
643
1264
|
}
|
|
644
1265
|
function queryAsLocalSymbolDetail(query) {
|
|
645
1266
|
if (queryAsCrossModuleFlowSurvey(query))
|
|
@@ -648,7 +1269,25 @@ function queryAsLocalSymbolDetail(query) {
|
|
|
648
1269
|
return false;
|
|
649
1270
|
if (shouldBuildKitModuleUsageSurvey(query))
|
|
650
1271
|
return false;
|
|
651
|
-
|
|
1272
|
+
// Cross-file API / declaration / constant / field inventories — not definition-only.
|
|
1273
|
+
if (shouldBuildApiUsageSurvey(query) && !queryAsTypeLifecycleSurvey(query))
|
|
1274
|
+
return false;
|
|
1275
|
+
if (queryAsModuleExportSurvey(query) || queryAsModuleDependencySurvey(query))
|
|
1276
|
+
return false;
|
|
1277
|
+
if (queryAsInRepoSystemCapabilityHowto(query))
|
|
1278
|
+
return false;
|
|
1279
|
+
if (queryAsReturnValueConsumerSurvey(query))
|
|
1280
|
+
return false;
|
|
1281
|
+
if (queryAsDeclarationSiteSurvey(query))
|
|
1282
|
+
return false;
|
|
1283
|
+
// lib*.so + GL thread → light-mechanism, not compact OpenGL/context seeds.
|
|
1284
|
+
if (queryAsNativeRenderThreadSurvey(query))
|
|
1285
|
+
return false;
|
|
1286
|
+
// Assigned flag impact → compact body. Named Toggle sync may have zero FTS
|
|
1287
|
+
// hits for the Type — inventory owns that shape instead.
|
|
1288
|
+
if (queryAsAssignedFlagImpactSurvey(query))
|
|
1289
|
+
return true;
|
|
1290
|
+
if (queryAsNamedControlStateSyncSurvey(query))
|
|
652
1291
|
return false;
|
|
653
1292
|
// Caller + co-named visibility → compact (body + callers), not inventory-only.
|
|
654
1293
|
if (queryNeedsCoNamedUseBridge(query))
|
|
@@ -660,8 +1299,19 @@ function queryAsLocalSymbolDetail(query) {
|
|
|
660
1299
|
// Named UI control + event: compact body + callees (not import inventory).
|
|
661
1300
|
if (queryAsNamedComponentAction(query))
|
|
662
1301
|
return true;
|
|
663
|
-
//
|
|
664
|
-
if (
|
|
1302
|
+
// Page/Component surface or 2–3 UI Type cluster — body, not full-graph explore.
|
|
1303
|
+
if (queryAsComponentSurfaceSurvey(query) || queryAsFocusedUiCluster(query))
|
|
1304
|
+
return true;
|
|
1305
|
+
// Named Type + state/lifecycle surface — full type body.
|
|
1306
|
+
if (queryAsTypeLifecycleSurvey(query))
|
|
1307
|
+
return true;
|
|
1308
|
+
// Release vs destructor / multi-method compare on named anchors.
|
|
1309
|
+
if (extractLocalDetailAnchors(query).length >= 2
|
|
1310
|
+
&& /析构|destructor|有没有重复|是否重复|跟.+做的事|做了哪些事情/i.test(query)) {
|
|
1311
|
+
return true;
|
|
1312
|
+
}
|
|
1313
|
+
// Type.member / Type + isFoo co-named — even if the agent used 怎么/如何 NL.
|
|
1314
|
+
if (queryHasNamedMemberFocus(query))
|
|
665
1315
|
return true;
|
|
666
1316
|
if (queryAsMechanismSurvey(query))
|
|
667
1317
|
return false;
|
|
@@ -689,7 +1339,12 @@ function queryHasFocusedNamedAnchors(query) {
|
|
|
689
1339
|
if (shouldTryFastInventoryExplore(query))
|
|
690
1340
|
return false;
|
|
691
1341
|
const anchors = extractLocalDetailAnchors(query);
|
|
692
|
-
|
|
1342
|
+
if (anchors.length < 1 || anchors.length > 3)
|
|
1343
|
+
return false;
|
|
1344
|
+
// Require a real code anchor (PascalCase Type / member-like), not leftover
|
|
1345
|
+
// English topic nouns that survived domain extraction (application, …).
|
|
1346
|
+
return (extractMemberAccessFromQuery(query).length > 0
|
|
1347
|
+
|| anchors.some((a) => /^[A-Z]/.test(a) || isMemberLikeIdentifier(a)));
|
|
693
1348
|
}
|
|
694
1349
|
/**
|
|
695
1350
|
* Prefer a tight explore budget: local-detail questions, or named-symbol
|
|
@@ -702,13 +1357,14 @@ function shouldUseCompactExploreBudget(query) {
|
|
|
702
1357
|
// do not shrink those into a definition-only budget.
|
|
703
1358
|
if (shouldTryFastInventoryExplore(query))
|
|
704
1359
|
return false;
|
|
705
|
-
if (queryAsLocalSymbolDetail(query))
|
|
1360
|
+
if (queryAsLocalSymbolDetail(query) || queryAsFocusedUiCluster(query) || queryAsComponentSurfaceSurvey(query)) {
|
|
706
1361
|
return true;
|
|
1362
|
+
}
|
|
707
1363
|
if (queryIsTypeNameFocus(query))
|
|
708
1364
|
return false;
|
|
709
|
-
const types = extractTypeNamesFromQuery(query);
|
|
1365
|
+
const types = extractTypeNamesFromQuery(query).filter((t) => !isFrameworkUiDecoratorName(t));
|
|
710
1366
|
const deps = extractDependencySymbolsFromQuery(query);
|
|
711
|
-
return types.length + deps.length >= 1 && types.length <=
|
|
1367
|
+
return types.length + deps.length >= 1 && types.length <= 3;
|
|
712
1368
|
}
|
|
713
1369
|
/** Keep rendering to files that define symbols named in the query. */
|
|
714
1370
|
function shouldFocusOnQueryNamedDefs(query, hasFlowPath, multiAnchorQuery) {
|
|
@@ -762,21 +1418,124 @@ function extractMechanismEntrySeeds(query) {
|
|
|
762
1418
|
seeds.add(term);
|
|
763
1419
|
}
|
|
764
1420
|
}
|
|
1421
|
+
// Shared-lib + GLES/EGL thread — seed the usual native GL owners (not `.so` / Context).
|
|
1422
|
+
if (queryAsNativeRenderThreadSurvey(query)) {
|
|
1423
|
+
seeds.add('EGLCore');
|
|
1424
|
+
seeds.add('PluginRender');
|
|
1425
|
+
if (/\bCMakeLists\b|\.so\b|链接|link/i.test(query))
|
|
1426
|
+
seeds.add('CMakeLists');
|
|
1427
|
+
}
|
|
1428
|
+
// Theme pack download→parse→install — agents often omit PascalCase names.
|
|
1429
|
+
if (/主题|theme\s*pack|theme\s*package/i.test(query) && /安装|解析|下载|install|parse|download/i.test(query)) {
|
|
1430
|
+
for (const s of [
|
|
1431
|
+
'ThemePackParser', 'ThemePackageInstaller', 'SkinInstaller', 'IconsInstaller', 'FontInstaller',
|
|
1432
|
+
]) {
|
|
1433
|
+
seeds.add(s);
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
// Notification subscribe/manage howto — same pattern (CJK domain, no Type named).
|
|
1437
|
+
if (/通知|notification/i.test(query) && /订阅|subscribe|管理|manage|多线程|multithread/i.test(query)) {
|
|
1438
|
+
for (const s of ['NotificationManager', 'NotificationSubscriber', 'AnsManager', 'SubscribeCallback']) {
|
|
1439
|
+
seeds.add(s);
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
// XML parse howto — seed the real API, not bare `xml` (which floods every Xml* path).
|
|
1443
|
+
if (/\bxml\b|xml解析|解析xml/i.test(query) && /解析|parse|convert|实现/i.test(query)) {
|
|
1444
|
+
for (const s of ['convertxml', 'XmlParseUtil', 'ConvertXML', 'fastConvertToJSObject']) {
|
|
1445
|
+
seeds.add(s);
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
765
1448
|
return [...seeds].filter((s) => s.length >= 3).slice(0, 12);
|
|
766
1449
|
}
|
|
767
1450
|
/**
|
|
768
1451
|
* Lightweight mechanism explore — seed symbols + flow spine only, no full
|
|
769
1452
|
* findRelevantContext (keeps MCP calls fast and avoids agent grep fallback).
|
|
1453
|
+
*
|
|
1454
|
+
* Domain-mechanism *bag*: agents often strip the how-phrase and keep only
|
|
1455
|
+
* keywords (`xml parse`, `foo convert`). Structural — distinctive ASCII token
|
|
1456
|
+
* plus an action verb or a CJK domain token; named Types take other paths.
|
|
770
1457
|
*/
|
|
1458
|
+
function queryAsDomainMechanismBag(query) {
|
|
1459
|
+
if (queryAsMechanismSurvey(query))
|
|
1460
|
+
return false;
|
|
1461
|
+
if (queryAsInterpretationSurvey(query))
|
|
1462
|
+
return false;
|
|
1463
|
+
// Named Type / Type.member / UI control → compact / inventory / click-flow.
|
|
1464
|
+
if (extractTypeNamesFromQuery(query).length > 0)
|
|
1465
|
+
return false;
|
|
1466
|
+
if (extractMemberAccessFromQuery(query).length > 0)
|
|
1467
|
+
return false;
|
|
1468
|
+
if (queryAsNamedComponentAction(query))
|
|
1469
|
+
return false;
|
|
1470
|
+
// Hover/悬停 bags without a how-implemented cue are UI-behavior, not mechanism.
|
|
1471
|
+
if (/悬停|\bhover\b|onHover/i.test(query)
|
|
1472
|
+
&& !/\b(?:parse|implement|manage|handle|process|subscribe|convert)\b/i.test(query)) {
|
|
1473
|
+
return false;
|
|
1474
|
+
}
|
|
1475
|
+
const domain = extractDomainSearchTerms(query);
|
|
1476
|
+
const distinct = domain.filter((t) => /^[A-Za-z][A-Za-z0-9._-]{2,}$/.test(t) && !exports.GENERIC_VERB_ANCHOR_NOISE.has(t.toLowerCase()));
|
|
1477
|
+
if (distinct.length === 0)
|
|
1478
|
+
return false;
|
|
1479
|
+
const hasActionVerb = domain.some((t) => exports.GENERIC_VERB_ANCHOR_NOISE.has(t.toLowerCase()))
|
|
1480
|
+
|| /\b(?:parse|implement|manage|handle|process|subscribe|convert|encode|decode)(?:s|d|ing)?\b/i.test(query);
|
|
1481
|
+
// Remaining CJK tokens are the topic half of a rewritten how-question bag.
|
|
1482
|
+
const hasCjkDomain = domain.some((t) => /[\u4e00-\u9fff]/.test(t));
|
|
1483
|
+
return hasActionVerb || hasCjkDomain;
|
|
1484
|
+
}
|
|
771
1485
|
function shouldTryLightMechanismExplore(query) {
|
|
772
1486
|
if (queryAsCrossModuleFlowSurvey(query))
|
|
773
1487
|
return false;
|
|
774
1488
|
if (queryAsInterpretationSurvey(query))
|
|
775
1489
|
return false;
|
|
776
|
-
//
|
|
777
|
-
if (
|
|
778
|
-
return
|
|
779
|
-
|
|
1490
|
+
// Literal / copy hunts → Grep (never light dump).
|
|
1491
|
+
if (queryLooksLikeLiteralOrCopyHunt(query))
|
|
1492
|
+
return false;
|
|
1493
|
+
// System-setting howto → lean capability inventory, not every `language` import.
|
|
1494
|
+
if (queryAsInRepoSystemCapabilityHowto(query))
|
|
1495
|
+
return false;
|
|
1496
|
+
// Return-value consumers → callers of the member, not a seed+flow dump.
|
|
1497
|
+
if (queryAsReturnValueConsumerSurvey(query))
|
|
1498
|
+
return false;
|
|
1499
|
+
// Manager data/status source → inventory, not light-mechanism.
|
|
1500
|
+
if (queryAsDataSourceSurvey(query))
|
|
1501
|
+
return false;
|
|
1502
|
+
// Named UI control + event → compact (body + callees + usage sites), not light-mechanism.
|
|
1503
|
+
if (queryAsNamedComponentAction(query))
|
|
1504
|
+
return false;
|
|
1505
|
+
if (queryAsAssignedFlagImpactSurvey(query) || queryAsNamedControlStateSyncSurvey(query)) {
|
|
1506
|
+
return false;
|
|
1507
|
+
}
|
|
1508
|
+
// Kit in-repo usage / extra-deps → kit inventory, not a mechanism dump.
|
|
1509
|
+
if (shouldBuildKitModuleUsageSurvey(query))
|
|
1510
|
+
return false;
|
|
1511
|
+
// Caller + "how is Type visible" → compact (callers + include), not light.
|
|
1512
|
+
if (queryNeedsCoNamedUseBridge(query))
|
|
1513
|
+
return false;
|
|
1514
|
+
// Named Type.member / UI cluster / local pinpoint → compact, even if NL has 怎么/如何.
|
|
1515
|
+
if (queryHasNamedMemberFocus(query)
|
|
1516
|
+
|| queryAsFocusedUiCluster(query)
|
|
1517
|
+
|| queryAsComponentSurfaceSurvey(query)
|
|
1518
|
+
|| queryAsLocalSymbolDetail(query)) {
|
|
1519
|
+
return false;
|
|
1520
|
+
}
|
|
1521
|
+
// Declaration / constant / field / module-export inventories own these shapes.
|
|
1522
|
+
if (queryAsDeclarationSiteSurvey(query)
|
|
1523
|
+
|| queryAsConstantUsageSurvey(query)
|
|
1524
|
+
|| queryAsFieldUsageSurvey(query)
|
|
1525
|
+
|| queryAsModuleExportSurvey(query)
|
|
1526
|
+
|| queryAsModuleDependencySurvey(query)
|
|
1527
|
+
|| queryAsTypeLifecycleSurvey(query)
|
|
1528
|
+
|| shouldBuildApiUsageSurvey(query)
|
|
1529
|
+
|| queryAsDtsWrapSurvey(query)) {
|
|
1530
|
+
return false;
|
|
1531
|
+
}
|
|
1532
|
+
// lib*.so + GLES/EGL + which thread → CMake/EGLCore spine, not `.so` member dump.
|
|
1533
|
+
if (queryAsNativeRenderThreadSurvey(query))
|
|
1534
|
+
return true;
|
|
1535
|
+
if (queryAsDomainMechanismBag(query)) {
|
|
1536
|
+
if (queryLooksLikeLiteralOrCopyHunt(query))
|
|
1537
|
+
return false;
|
|
1538
|
+
return extractDomainSearchTerms(query).length >= 1;
|
|
780
1539
|
}
|
|
781
1540
|
if (!queryAsMechanismSurvey(query))
|
|
782
1541
|
return false;
|
|
@@ -793,38 +1552,76 @@ function shouldTryFastInventoryExplore(query) {
|
|
|
793
1552
|
return false;
|
|
794
1553
|
if (queryAsInterpretationSurvey(query))
|
|
795
1554
|
return false;
|
|
1555
|
+
if (queryLooksLikeLiteralOrCopyHunt(query))
|
|
1556
|
+
return false;
|
|
796
1557
|
// Caller paths alone cannot answer "which call makes Type X visible" — compact.
|
|
797
1558
|
if (queryNeedsCoNamedUseBridge(query))
|
|
798
1559
|
return false;
|
|
799
|
-
//
|
|
800
|
-
|
|
801
|
-
|
|
1560
|
+
// Type lifecycle / Release↔destructor compares need bodies, not path lists.
|
|
1561
|
+
if (queryAsTypeLifecycleSurvey(query))
|
|
1562
|
+
return false;
|
|
1563
|
+
// Type×method interaction (CanPlace/Place ↔ Grid) → compact, not member inventory.
|
|
1564
|
+
if (queryAsCoNamedTypeMethodInteraction(query))
|
|
1565
|
+
return false;
|
|
1566
|
+
// Import / kit-usage / domain / API / config / data-source listings win even if
|
|
1567
|
+
// a dotted `@kit.X` once looked like Type.member (defense in depth).
|
|
1568
|
+
// Member-pattern inventories only when the question is a usage listing.
|
|
1569
|
+
if (shouldBuildKitModuleUsageSurvey(query)
|
|
1570
|
+
|| shouldBuildApiUsageSurvey(query)
|
|
1571
|
+
|| shouldBuildDomainFileSurvey(query)
|
|
1572
|
+
|| shouldBuildConfigSection(query)
|
|
1573
|
+
|| queryAsDataSourceSurvey(query)
|
|
1574
|
+
|| shouldBuildHoverHandlerSurvey(query)
|
|
1575
|
+
|| queryAsModuleExportSurvey(query)
|
|
1576
|
+
|| queryAsModuleDependencySurvey(query)
|
|
1577
|
+
|| queryAsDtsWrapSurvey(query)
|
|
1578
|
+
|| queryAsNamedControlStateSyncSurvey(query)
|
|
1579
|
+
|| shouldPreferMemberUsageInventory(query)
|
|
1580
|
+
|| queryAsInRepoSystemCapabilityHowto(query)
|
|
1581
|
+
|| queryAsReturnValueConsumerSurvey(query)
|
|
1582
|
+
|| queryAsDeclarationSiteSurvey(query)) {
|
|
1583
|
+
return true;
|
|
1584
|
+
}
|
|
1585
|
+
// One named symbol / UI action / Type.member / component surface — inventory is wrong.
|
|
1586
|
+
if (queryAsLocalSymbolDetail(query)
|
|
1587
|
+
|| queryHasNamedMemberFocus(query)
|
|
1588
|
+
|| queryAsNamedComponentAction(query)
|
|
1589
|
+
|| queryAsComponentSurfaceSurvey(query)
|
|
1590
|
+
|| queryAsFocusedUiCluster(query)) {
|
|
802
1591
|
return false;
|
|
803
1592
|
}
|
|
804
1593
|
const types = extractTypeNamesFromQuery(query);
|
|
805
|
-
if (types.length >= 2 && !queryAsCallerOrMethodSurvey(query))
|
|
1594
|
+
if (types.length >= 2 && !queryAsCallerOrMethodSurvey(query) && !queryAsInheritanceSurvey(query)) {
|
|
806
1595
|
return false;
|
|
1596
|
+
}
|
|
807
1597
|
const inventoryDeps = extractDependencySymbolsFromQuery(query).filter((d) => !isMemberLikeIdentifier(d));
|
|
808
|
-
return (
|
|
809
|
-
||
|
|
810
|
-
|
|
811
|
-
|| (hasImportInventoryFilter(query)
|
|
812
|
-
&& (inventoryDeps.length > 0 || extractKitModuleNamesFromQuery(query).length > 0)
|
|
813
|
-
&& inventoryDeps.length > 0)
|
|
1598
|
+
return ((hasImportInventoryFilter(query)
|
|
1599
|
+
&& (inventoryDeps.length > 0 || extractKitModuleNamesFromQuery(query).length > 0)
|
|
1600
|
+
&& inventoryDeps.length > 0)
|
|
814
1601
|
|| shouldBuildCallerInventory(query)
|
|
815
|
-
|| shouldBuildInheritanceSurvey(query)
|
|
816
|
-
|| shouldBuildMemberSurvey(query)
|
|
817
|
-
|| shouldBuildConfigSection(query)
|
|
818
|
-
|| queryAsDataSourceSurvey(query));
|
|
1602
|
+
|| shouldBuildInheritanceSurvey(query));
|
|
819
1603
|
}
|
|
820
1604
|
function shouldBuildInheritanceSurvey(query) {
|
|
821
1605
|
if (queryAsInheritanceSurvey(query) && extractTypeNamesFromQuery(query).length > 0)
|
|
822
1606
|
return true;
|
|
1607
|
+
// UI Page/Component overview needs the body — not an empty subtype list.
|
|
1608
|
+
if (queryAsComponentSurfaceSurvey(query))
|
|
1609
|
+
return false;
|
|
823
1610
|
// Bare / near-bare type queries — agent search("Foo") for subtypes/overview.
|
|
824
|
-
|
|
1611
|
+
if (queryIsTypeNameFocus(query)) {
|
|
1612
|
+
const types = extractTypeNamesFromQuery(query);
|
|
1613
|
+
if (types.some(queryLooksLikeUiComponentType))
|
|
1614
|
+
return false;
|
|
1615
|
+
return true;
|
|
1616
|
+
}
|
|
1617
|
+
return false;
|
|
825
1618
|
}
|
|
826
1619
|
function shouldBuildMemberSurvey(query) {
|
|
827
|
-
|
|
1620
|
+
const members = extractMemberAccessFromQuery(query);
|
|
1621
|
+
if (members.length > 0)
|
|
1622
|
+
return true;
|
|
1623
|
+
// Field/mutex co-use without a leading dot still needs the text-usage inventory.
|
|
1624
|
+
return queryAsFieldUsageSurvey(query);
|
|
828
1625
|
}
|
|
829
1626
|
function shouldBuildConfigSection(query) {
|
|
830
1627
|
return queryNamesConfigFile(query);
|
|
@@ -851,28 +1648,28 @@ function extractDomainSearchTerms(query) {
|
|
|
851
1648
|
terms.delete(kit);
|
|
852
1649
|
terms.delete(kit.charAt(0).toLowerCase() + kit.slice(1));
|
|
853
1650
|
}
|
|
1651
|
+
// Always keep ASCII code tokens (xml, parse, subscribe…) — mechanism NL often
|
|
1652
|
+
// mixes them with Chinese and used to drop them unless a @kit/path was present.
|
|
1653
|
+
for (const m of query.matchAll(/\b([A-Za-z][A-Za-z0-9]{2,})\b/g)) {
|
|
1654
|
+
const w = m[1];
|
|
1655
|
+
if (!exports.STOP_WORDS.has(w.toLowerCase()))
|
|
1656
|
+
terms.add(w);
|
|
1657
|
+
}
|
|
854
1658
|
const stripped = query
|
|
855
1659
|
.replace(/[@#][\w.]+/g, ' ')
|
|
856
|
-
.replace(
|
|
1660
|
+
.replace(/哪些文件|有哪些|什么|如何|怎样|怎么|项目中|项目里|项目|涉及|相关的?|文件|模块|功能|吗|?|\?|有使用|是否|有没有|使用|不同|区别|对比|这个|那个|是怎样|是如何|怎么|如何|它与|它和|实现|的/g, ' ')
|
|
857
1661
|
.replace(/\s+/g, ' ')
|
|
858
1662
|
.trim();
|
|
859
|
-
for (const m of stripped.matchAll(/[\u4e00-\u9fff]{2,
|
|
1663
|
+
for (const m of stripped.matchAll(/[\u4e00-\u9fff]{2,8}/g)) {
|
|
860
1664
|
let t = m[0].replace(/^与/, '');
|
|
861
1665
|
if (t.length >= 2)
|
|
862
1666
|
terms.add(t);
|
|
863
1667
|
}
|
|
864
|
-
if (queryMentionsCodeContext(query)) {
|
|
865
|
-
for (const m of query.matchAll(/\b([a-z][a-zA-Z0-9]{4,})\b/g)) {
|
|
866
|
-
const w = m[1];
|
|
867
|
-
if (!exports.STOP_WORDS.has(w.toLowerCase()))
|
|
868
|
-
terms.add(w);
|
|
869
|
-
}
|
|
870
|
-
}
|
|
871
1668
|
return [...terms].filter((t) => t.length >= 2).slice(0, 12);
|
|
872
1669
|
}
|
|
873
1670
|
/** How/implementation/mechanism intent — needs entry symbols + flow, not flat file list. */
|
|
874
1671
|
function queryAsMechanismSurvey(query) {
|
|
875
|
-
return /如何(?:实现|获取|做|处理|管理)|怎样(?:实现|获取|做)|怎么(?:实现|获取|做)|是如何|是怎么|how\s+(?:is|does|are|to\s+(?:get|implement|work))|机制|流程|架构|多线程|多进程|multithread|multi-thread
|
|
1672
|
+
return /如何(?:实现|获取|做|处理|管理)|怎样(?:实现|获取|做)|怎么(?:实现|获取|做)|是如何|是怎么|how\s+(?:is|does|are|to\s+(?:get|implement|work))|机制|流程|架构|多线程|多进程|multithread|multi-thread|会走到哪些|步骤中会|解析和安装|下载完|下载后/i.test(query);
|
|
876
1673
|
}
|
|
877
1674
|
/**
|
|
878
1675
|
* Broad domain survey — related files, usage existence, or concept comparison.
|
|
@@ -881,6 +1678,8 @@ function queryAsMechanismSurvey(query) {
|
|
|
881
1678
|
function queryAsDomainFileSurvey(query) {
|
|
882
1679
|
if (queryAsKitModuleCapabilitySurvey(query))
|
|
883
1680
|
return false;
|
|
1681
|
+
if (queryLooksLikeLiteralOrCopyHunt(query))
|
|
1682
|
+
return false;
|
|
884
1683
|
if (queryAsCallerOrMethodSurvey(query))
|
|
885
1684
|
return false;
|
|
886
1685
|
if (shouldBuildApiUsageSurvey(query))
|
|
@@ -893,6 +1692,16 @@ function queryAsDomainFileSurvey(query) {
|
|
|
893
1692
|
return false;
|
|
894
1693
|
if (queryAsMechanismSurvey(query))
|
|
895
1694
|
return false;
|
|
1695
|
+
// Module dep → dedicated cycle survey. Module NAPI export → dedicated export
|
|
1696
|
+
// survey (must NOT become a 50-file domain dump of every "API"/"NAPI" token).
|
|
1697
|
+
if (queryAsModuleDependencySurvey(query))
|
|
1698
|
+
return true;
|
|
1699
|
+
if (queryAsModuleExportSurvey(query) || queryAsDtsWrapSurvey(query))
|
|
1700
|
+
return false;
|
|
1701
|
+
// Step / "which code runs" flow questions are mechanism — not domain file lists.
|
|
1702
|
+
if (/会走到|步骤中|解析和安装|下载完|下载后|call\s*chain|which\s+code\s+(?:runs|paths?)/i.test(query)) {
|
|
1703
|
+
return false;
|
|
1704
|
+
}
|
|
896
1705
|
const listing = /哪些文件|有哪些.*文件|相关的?\s*文件|涉及.*文件|which\s+files?|files?\s+(?:are\s+)?related/i.test(query);
|
|
897
1706
|
const usage = /有使用|是否使用|有没有使用|使用了.*吗|is\s+.+\s+used/i.test(query);
|
|
898
1707
|
const compare = /有什么不同|区别|difference|vs\.?|versus|对比/i.test(query);
|