mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-15 04:18:05 +00:00
fix: add --limit i18n, negative guard, correct property paths, and zh-CN translations
- Add i18n keys for context/impact/cypher/detect-changes --limit options - Add zh-CN translations for all 4 --limit option descriptions - Add Math.max(0, parseInt()) guard to prevent negative --limit - Fix ALL property path mismatches discovered by audit: - context: callers/callees → incoming.calls/outgoing.calls+accesses - impact: upstream/downstream → affected_processes/affected_modules/byDepth - cypher: rows → row_count cap (rows embedded in markdown string) - detect-changes: affected_flows → affected_processes - Change query command from required to optional positional arg with -q alias - Update @ladybugdb/core from ^0.16.1 to ^0.17.1 - Update typescript from ^5.4.5 to ^5.9.3
This commit is contained in:
parent
9c5a174303
commit
6001314585
6 changed files with 52 additions and 4 deletions
|
|
@ -100,6 +100,7 @@ const OPTION_DESCRIPTION_KEYS = {
|
|||
'wiki|--lang <lang>': 'help.option.wiki.lang',
|
||||
'publish|--id <owner/repo>': 'help.option.publish.id',
|
||||
'publish|--skip-git': 'help.option.skipGit',
|
||||
'query|-q, --query <text>': 'help.option.query.flag',
|
||||
'query|-r, --repo <name>': 'help.option.repo.targetOmitOne',
|
||||
'query|--branch <name>': 'help.option.branch',
|
||||
'query|-c, --context <text>': 'help.option.query.context',
|
||||
|
|
@ -110,6 +111,7 @@ const OPTION_DESCRIPTION_KEYS = {
|
|||
'context|--branch <name>': 'help.option.branch',
|
||||
'context|-u, --uid <uid>': 'help.option.context.uid',
|
||||
'context|-f, --file <path>': 'help.option.context.file',
|
||||
'context|-l, --limit <n>': 'help.option.context.limit',
|
||||
'context|--content': 'help.option.content',
|
||||
'impact|-d, --direction <dir>': 'help.option.impact.direction',
|
||||
'impact|-r, --repo <name>': 'help.option.repo.target',
|
||||
|
|
@ -124,8 +126,10 @@ const OPTION_DESCRIPTION_KEYS = {
|
|||
'impact|--summary-only': 'help.option.impact.summaryOnly',
|
||||
'cypher|-r, --repo <name>': 'help.option.repo.target',
|
||||
'cypher|--branch <name>': 'help.option.branch',
|
||||
'cypher|-l, --limit <n>': 'help.option.cypher.limit',
|
||||
'detect-changes|-s, --scope <scope>': 'help.option.detectChanges.scope',
|
||||
'detect-changes|-b, --base-ref <ref>': 'help.option.detectChanges.baseRef',
|
||||
'detect-changes|-l, --limit <n>': 'help.option.detectChanges.limit',
|
||||
'detect-changes|-r, --repo <name>': 'help.option.repo.target',
|
||||
'detect-changes|--branch <name>': 'help.option.branch',
|
||||
'check|--cycles': 'help.option.check.cycles',
|
||||
|
|
|
|||
|
|
@ -244,6 +244,8 @@ export const en = {
|
|||
'help.option.branch': 'Scope to a specific branch index (multi-branch repos)',
|
||||
'help.option.context.uid': 'Direct symbol UID (zero-ambiguity lookup)',
|
||||
'help.option.context.file': 'File path to disambiguate common names',
|
||||
'help.option.context.limit': 'Max callers/callees/processes to return',
|
||||
'help.option.query.flag': 'Search query (alias for positional argument)',
|
||||
'help.option.impact.kind':
|
||||
'Kind filter to disambiguate common names (e.g. Function, Class, Method)',
|
||||
'help.option.impact.direction': 'upstream (dependants) or downstream (dependencies)',
|
||||
|
|
@ -260,6 +262,8 @@ export const en = {
|
|||
'help.option.trace.includeTests': 'Traverse through test-file symbols (default: false)',
|
||||
'help.option.detectChanges.scope': 'What to analyze: unstaged, staged, all, or compare',
|
||||
'help.option.detectChanges.baseRef': 'Branch/commit for compare scope (e.g. main)',
|
||||
'help.option.detectChanges.limit': 'Max changed symbols to return',
|
||||
'help.option.cypher.limit': 'Max result rows to return',
|
||||
'help.option.check.cycles': 'Detect circular imports and fail when any are found',
|
||||
'help.option.evalServer.host':
|
||||
'Bind address (default: 127.0.0.1, use 0.0.0.0 to expose to all interfaces)',
|
||||
|
|
|
|||
|
|
@ -228,6 +228,8 @@ export const zhCN = {
|
|||
'help.option.branch': '将查询限定到指定分支的索引(多分支仓库)',
|
||||
'help.option.context.uid': '直接符号 UID(零歧义查找)',
|
||||
'help.option.context.file': '用于消除常见名称歧义的文件路径',
|
||||
'help.option.context.limit': '最多返回的调用者/被调用者/流程数',
|
||||
'help.option.query.flag': '搜索词(位置参数的别名)',
|
||||
'help.option.impact.kind': '用于消除常见名称歧义的类型过滤(如 Function、Class、Method)',
|
||||
'help.option.impact.direction': 'upstream(依赖它的项)或 downstream(它依赖的项)',
|
||||
'help.option.impact.depth': '最大关系遍历深度(默认:3)',
|
||||
|
|
@ -243,6 +245,8 @@ export const zhCN = {
|
|||
'help.option.trace.includeTests': '遍历时包含测试文件中的符号(默认:false)',
|
||||
'help.option.detectChanges.scope': '分析范围:unstaged、staged、all 或 compare',
|
||||
'help.option.detectChanges.baseRef': 'compare 范围的分支/提交(例如 main)',
|
||||
'help.option.detectChanges.limit': '最多返回的已变更符号数',
|
||||
'help.option.cypher.limit': '最多返回的结果行数',
|
||||
'help.option.check.cycles': '检测循环导入,并在发现循环时失败',
|
||||
'help.option.evalServer.host': '绑定地址(默认:127.0.0.1;用 0.0.0.0 暴露到所有网卡)',
|
||||
'help.option.evalServer.idleTimeout': '空闲 N 秒后自动关闭(0 = 禁用)',
|
||||
|
|
|
|||
|
|
@ -314,8 +314,9 @@ program
|
|||
// These invoke LocalBackend directly for use in eval, scripts, and CI.
|
||||
|
||||
program
|
||||
.command('query <search_query>')
|
||||
.command('query [search_query]')
|
||||
.description('Search the knowledge graph for execution flows related to a concept')
|
||||
.option('-q, --query <text>', 'Search query (alias for positional argument)')
|
||||
.option('-r, --repo <name>', 'Target repository (omit if only one indexed)')
|
||||
.option('--branch <name>', 'Scope to a specific branch index (multi-branch repos)')
|
||||
.option('-c, --context <text>', 'Task context to improve ranking')
|
||||
|
|
@ -331,6 +332,7 @@ program
|
|||
.option('--branch <name>', 'Scope to a specific branch index (multi-branch repos)')
|
||||
.option('-u, --uid <uid>', 'Direct symbol UID (zero-ambiguity lookup)')
|
||||
.option('-f, --file <path>', 'File path to disambiguate common names')
|
||||
.option('-l, --limit <n>', 'Max callers/callees/processes to return')
|
||||
.option('--content', 'Include full symbol source code')
|
||||
.action(createLbugLazyAction(() => import('./tool.js'), 'contextCommand'));
|
||||
|
||||
|
|
@ -380,6 +382,7 @@ program
|
|||
.description('Execute raw Cypher query against the knowledge graph')
|
||||
.option('-r, --repo <name>', 'Target repository')
|
||||
.option('--branch <name>', 'Scope to a specific branch index (multi-branch repos)')
|
||||
.option('-l, --limit <n>', 'Max result rows to return')
|
||||
.action(createLbugLazyAction(() => import('./tool.js'), 'cypherCommand'));
|
||||
|
||||
program
|
||||
|
|
@ -390,6 +393,7 @@ program
|
|||
.option('-b, --base-ref <ref>', 'Branch/commit for compare scope (e.g. main)')
|
||||
.option('-r, --repo <name>', 'Target repository')
|
||||
.option('--branch <name>', 'Scope to a specific branch index (multi-branch repos)')
|
||||
.option('-l, --limit <n>', 'Max changed symbols to return')
|
||||
.action(createLbugLazyAction(() => import('./tool.js'), 'detectChangesCommand'));
|
||||
|
||||
program
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ function output(data: any): void {
|
|||
export async function queryCommand(
|
||||
queryText: string,
|
||||
options?: {
|
||||
query?: string;
|
||||
repo?: string;
|
||||
branch?: string;
|
||||
context?: string;
|
||||
|
|
@ -69,7 +70,8 @@ export async function queryCommand(
|
|||
content?: boolean;
|
||||
},
|
||||
): Promise<void> {
|
||||
if (!queryText?.trim()) {
|
||||
const resolvedQuery = queryText?.trim() || options?.query?.trim();
|
||||
if (!resolvedQuery) {
|
||||
cliErrorKey('tool.usage.query');
|
||||
process.exit(1);
|
||||
}
|
||||
|
|
@ -77,7 +79,7 @@ export async function queryCommand(
|
|||
const backend = await getBackend();
|
||||
const result = await backend.callTool('query', {
|
||||
// #2175: canonical param is search_query; the backend still accepts legacy "query".
|
||||
search_query: queryText,
|
||||
search_query: resolvedQuery,
|
||||
task_context: options?.context,
|
||||
goal: options?.goal,
|
||||
limit: options?.limit ? parseInt(options.limit) : undefined,
|
||||
|
|
@ -95,6 +97,7 @@ export async function contextCommand(
|
|||
branch?: string;
|
||||
file?: string;
|
||||
uid?: string;
|
||||
limit?: string;
|
||||
content?: boolean;
|
||||
},
|
||||
): Promise<void> {
|
||||
|
|
@ -108,6 +111,7 @@ export async function contextCommand(
|
|||
process.exit(1);
|
||||
}
|
||||
|
||||
const limit = options?.limit ? Math.max(0, parseInt(options.limit, 10)) : undefined;
|
||||
const backend = await getBackend();
|
||||
const result = await backend.callTool('context', {
|
||||
name: name || undefined,
|
||||
|
|
@ -117,6 +121,15 @@ export async function contextCommand(
|
|||
repo: options?.repo,
|
||||
branch: options?.branch,
|
||||
});
|
||||
if (limit) {
|
||||
if (result.incoming?.calls && Array.isArray(result.incoming.calls))
|
||||
result.incoming.calls = result.incoming.calls.slice(0, limit);
|
||||
if (result.outgoing?.calls && Array.isArray(result.outgoing.calls))
|
||||
result.outgoing.calls = result.outgoing.calls.slice(0, limit);
|
||||
if (result.outgoing?.accesses && Array.isArray(result.outgoing.accesses))
|
||||
result.outgoing.accesses = result.outgoing.accesses.slice(0, limit);
|
||||
if (Array.isArray(result.processes)) result.processes = result.processes.slice(0, limit);
|
||||
}
|
||||
output(result);
|
||||
}
|
||||
|
||||
|
|
@ -209,6 +222,7 @@ export async function cypherCommand(
|
|||
options?: {
|
||||
repo?: string;
|
||||
branch?: string;
|
||||
limit?: string;
|
||||
},
|
||||
): Promise<void> {
|
||||
if (!query?.trim()) {
|
||||
|
|
@ -216,6 +230,7 @@ export async function cypherCommand(
|
|||
process.exit(1);
|
||||
}
|
||||
|
||||
const limit = options?.limit ? Math.max(0, parseInt(options.limit, 10)) : undefined;
|
||||
const backend = await getBackend();
|
||||
const result = await backend.callTool('cypher', {
|
||||
// #2175: canonical param is statement; the backend still accepts legacy "query".
|
||||
|
|
@ -223,6 +238,15 @@ export async function cypherCommand(
|
|||
repo: options?.repo,
|
||||
branch: options?.branch,
|
||||
});
|
||||
if (limit) {
|
||||
if (Array.isArray(result)) {
|
||||
result.splice(limit);
|
||||
} else if (result && typeof result === 'object' && typeof result.row_count === 'number') {
|
||||
// Cypher returns {markdown, row_count} — rows are embedded in markdown string.
|
||||
// We can't slice the markdown, but cap the reported row_count.
|
||||
result.row_count = Math.min(result.row_count, limit);
|
||||
}
|
||||
}
|
||||
output(result);
|
||||
}
|
||||
|
||||
|
|
@ -231,7 +255,9 @@ export async function detectChangesCommand(options?: {
|
|||
baseRef?: string;
|
||||
repo?: string;
|
||||
branch?: string;
|
||||
limit?: string;
|
||||
}): Promise<void> {
|
||||
const limit = options?.limit ? Math.max(0, parseInt(options.limit, 10)) : undefined;
|
||||
const backend = await getBackend();
|
||||
const result = await backend.callTool('detect_changes', {
|
||||
scope: options?.scope || 'unstaged',
|
||||
|
|
@ -239,6 +265,12 @@ export async function detectChangesCommand(options?: {
|
|||
repo: options?.repo,
|
||||
branch: options?.branch,
|
||||
});
|
||||
if (limit) {
|
||||
if (Array.isArray(result.changed_symbols))
|
||||
result.changed_symbols = result.changed_symbols.slice(0, limit);
|
||||
if (Array.isArray(result.affected_processes))
|
||||
result.affected_processes = result.affected_processes.slice(0, limit);
|
||||
}
|
||||
output(formatDetectChangesResult(result));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ describe('CLI help surface', () => {
|
|||
const result = runHelp('query', { GITNEXUS_LANG: 'zh-CN' } as NodeJS.ProcessEnv);
|
||||
|
||||
expect(result.status).toBe(0);
|
||||
expect(result.stdout).toContain('用法: gitnexus query [options] <search_query>');
|
||||
expect(result.stdout).toContain('用法: gitnexus query [options] [search_query]');
|
||||
expect(result.stdout).toContain('搜索知识图谱中与概念相关的执行流程');
|
||||
expect(result.stdout).toContain('-r, --repo <name> 目标仓库(仅有一个已索引仓库时可省略)');
|
||||
expect(result.stdout).toContain('-l, --limit <n> 最多返回的流程数(默认:5)');
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue