nexus-agents 2.77.2 → 2.77.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-6UDFAXUI.js → chunk-AFGRQB4H.js} +5 -3
- package/dist/{chunk-6UDFAXUI.js.map → chunk-AFGRQB4H.js.map} +1 -1
- package/dist/{chunk-BC3M4VLP.js → chunk-BMOPMCFZ.js} +5 -2
- package/dist/chunk-BMOPMCFZ.js.map +1 -0
- package/dist/{chunk-CPPZCNAS.js → chunk-EEW7VFFF.js} +3 -3
- package/dist/{chunk-X3BU5MIG.js → chunk-FYAQBYHM.js} +2 -2
- package/dist/{chunk-RFITLMH4.js → chunk-LIY6WZNR.js} +24 -212
- package/dist/chunk-LIY6WZNR.js.map +1 -0
- package/dist/{chunk-VEF6DCQU.js → chunk-MV4R2ZIJ.js} +204 -4
- package/dist/chunk-MV4R2ZIJ.js.map +1 -0
- package/dist/{chunk-N3HOBUU4.js → chunk-S6MEYRYZ.js} +30 -21
- package/dist/{chunk-N3HOBUU4.js.map → chunk-S6MEYRYZ.js.map} +1 -1
- package/dist/{chunk-ZKOBXAPK.js → chunk-WXVN4K3D.js} +2 -2
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +30 -17
- package/dist/cli.js.map +1 -1
- package/dist/{consensus-vote-UR3JU7RI.js → consensus-vote-AWBFYF5S.js} +3 -3
- package/dist/{expert-bridge-DWBO2HXZ.js → expert-bridge-NX2MGOBQ.js} +2 -2
- package/dist/{factory-LXOVC44K.js → factory-JI6PSWGR.js} +2 -2
- package/dist/index.d.ts +0 -2
- package/dist/index.js +8 -8
- package/dist/{repo-analyze-HWMXSK5C.js → repo-analyze-QGLXEFVJ.js} +2 -2
- package/dist/{repo-security-plan-EIL2BV3S.js → repo-security-plan-X5CRZ2YY.js} +3 -3
- package/dist/{setup-command-ZIG5JJAE.js → setup-command-DB3DOE6K.js} +4 -4
- package/package.json +1 -1
- package/dist/chunk-BC3M4VLP.js.map +0 -1
- package/dist/chunk-RFITLMH4.js.map +0 -1
- package/dist/chunk-VEF6DCQU.js.map +0 -1
- /package/dist/{chunk-CPPZCNAS.js.map → chunk-EEW7VFFF.js.map} +0 -0
- /package/dist/{chunk-X3BU5MIG.js.map → chunk-FYAQBYHM.js.map} +0 -0
- /package/dist/{chunk-ZKOBXAPK.js.map → chunk-WXVN4K3D.js.map} +0 -0
- /package/dist/{consensus-vote-UR3JU7RI.js.map → consensus-vote-AWBFYF5S.js.map} +0 -0
- /package/dist/{expert-bridge-DWBO2HXZ.js.map → expert-bridge-NX2MGOBQ.js.map} +0 -0
- /package/dist/{factory-LXOVC44K.js.map → factory-JI6PSWGR.js.map} +0 -0
- /package/dist/{repo-analyze-HWMXSK5C.js.map → repo-analyze-QGLXEFVJ.js.map} +0 -0
- /package/dist/{repo-security-plan-EIL2BV3S.js.map → repo-security-plan-X5CRZ2YY.js.map} +0 -0
- /package/dist/{setup-command-ZIG5JJAE.js.map → setup-command-DB3DOE6K.js.map} +0 -0
|
@@ -190,7 +190,10 @@ function analyzeRepo(metadata, topLevelEntries, workflowEntries) {
|
|
|
190
190
|
packageManager: detectPackageManager(topLevelEntries),
|
|
191
191
|
ciProvider,
|
|
192
192
|
securityTooling: secTooling,
|
|
193
|
-
|
|
193
|
+
// Match `Dockerfile`, `Dockerfile.<purpose>` (e.g. `Dockerfile.sandbox`),
|
|
194
|
+
// and docker-compose variants. Pre-#2730 the check was exact-match only,
|
|
195
|
+
// so a repo with three legitimate `Dockerfile.*` files reported false.
|
|
196
|
+
hasDockerfile: topLevelEntries.some((e) => e === "Dockerfile" || e.startsWith("Dockerfile.")) || topLevelEntries.includes("docker-compose.yml") || topLevelEntries.includes("docker-compose.yaml"),
|
|
194
197
|
hasHelmCharts: topLevelEntries.includes("Chart.yaml") || topLevelEntries.includes("charts") || topLevelEntries.includes("helm"),
|
|
195
198
|
hasMakefile: topLevelEntries.includes("Makefile"),
|
|
196
199
|
hasTests,
|
|
@@ -356,4 +359,4 @@ export {
|
|
|
356
359
|
analyzeRepo,
|
|
357
360
|
analyzeGitHubRepo
|
|
358
361
|
};
|
|
359
|
-
//# sourceMappingURL=chunk-
|
|
362
|
+
//# sourceMappingURL=chunk-BMOPMCFZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/mcp/tools/repo-analyze.ts"],"sourcesContent":["/* eslint-disable max-lines -- cohesive module, governance allows 400-600 */\n/**\n * nexus-agents/mcp - Repository Analyze Logic\n *\n * Inspects a GitHub repository and returns structured analysis\n * including language, tooling, CI, security, and gap identification.\n *\n * @module mcp/tools/repo-analyze\n * (Source: Issue #1074)\n */\n\nimport type { RepoAnalyzeInput, RepoAnalysis } from './repo-analyze-types.js';\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/** Normalize \"owner/repo\" from either \"owner/repo\" or full GitHub URL. */\nexport function normalizeRepoId(input: string): string {\n const urlMatch = /github\\.com\\/([^/]+\\/[^/]+?)(?:\\.git)?(?:\\/|$)/.exec(input);\n const matched = urlMatch?.[1] ?? '';\n if (matched.length > 0) return matched;\n if (/^[^/]+\\/[^/]+$/.test(input)) return input;\n throw new Error(`Invalid repo format: \"${input}\". Use \"owner/name\" or a GitHub URL.`);\n}\n\n/** Package manager detection rules: [files, manager]. First match wins. */\nconst PACKAGE_MANAGER_RULES: ReadonlyArray<readonly [readonly string[], string]> = [\n [['pnpm-lock.yaml'], 'pnpm'],\n [['yarn.lock'], 'yarn'],\n [['package-lock.json', 'package.json'], 'npm'],\n [['Cargo.toml'], 'cargo'],\n [['go.mod'], 'go'],\n [['requirements.txt', 'pyproject.toml'], 'pip'],\n [['Gemfile'], 'bundler'],\n [['pom.xml'], 'maven'],\n [['build.gradle', 'build.gradle.kts'], 'gradle'],\n];\n\n/** Detect package manager from top-level files. */\nexport function detectPackageManager(entries: readonly string[]): string | null {\n for (const [files, manager] of PACKAGE_MANAGER_RULES) {\n if (files.some((f) => entries.includes(f))) return manager;\n }\n return null;\n}\n\n/** Detect CI provider from directory structure. */\nexport function detectCiProvider(entries: readonly string[]): string | null {\n if (entries.includes('.github')) return 'github-actions';\n if (entries.includes('.gitlab-ci.yml')) return 'gitlab-ci';\n if (entries.includes('Jenkinsfile')) return 'jenkins';\n if (entries.includes('.circleci')) return 'circleci';\n if (entries.includes('.travis.yml')) return 'travis';\n if (entries.includes('azure-pipelines.yml')) return 'azure-devops';\n if (entries.includes('concourse')) return 'concourse';\n return null;\n}\n\n/** Tool names detectable from CI workflow filenames (#1674). */\nconst WORKFLOW_SECURITY_PATTERNS: ReadonlyArray<readonly [string, string]> = [\n ['semgrep', 'semgrep'],\n ['codeql', 'codeql'],\n ['grype', 'grype'],\n ['snyk', 'snyk'],\n];\n\n/** Detect security tools from .github/workflows/ filenames. */\nfunction detectWorkflowSecurity(\n workflowEntries: readonly string[],\n existing: readonly string[]\n): readonly string[] {\n const wfLower = workflowEntries.map((w) => w.toLowerCase());\n const found: string[] = [];\n for (const [pattern, tool] of WORKFLOW_SECURITY_PATTERNS) {\n if (!existing.includes(tool) && wfLower.some((w) => w.includes(pattern))) {\n found.push(tool);\n }\n }\n return found;\n}\n\n/** Detect security tooling from root files and CI workflow filenames (#1674). */\nexport function detectSecurityTooling(\n entries: readonly string[],\n workflowEntries?: readonly string[]\n): readonly string[] {\n const tools: string[] = [];\n if (entries.includes('.semgrep.yml') || entries.includes('.semgrep')) tools.push('semgrep');\n if (entries.includes('.snyk')) tools.push('snyk');\n if (entries.includes('SECURITY.md')) tools.push('security-policy');\n if (entries.includes('.grype.yaml')) tools.push('grype');\n if (entries.includes('CODEOWNERS')) tools.push('codeowners');\n if (workflowEntries !== undefined) {\n tools.push(...detectWorkflowSecurity(workflowEntries, tools));\n }\n return tools;\n}\n\n/** Detect framework from package manager config. */\nexport function detectFramework(entries: readonly string[]): string | null {\n if (entries.includes('helmfile.yaml') || entries.includes('helmfile.yaml.gotmpl'))\n return 'helmfile';\n if (entries.includes('next.config.js') || entries.includes('next.config.ts')) return 'nextjs';\n if (entries.includes('angular.json')) return 'angular';\n if (entries.includes('vite.config.ts') || entries.includes('vite.config.js')) return 'vite';\n if (entries.includes('tsconfig.json') && entries.includes('package.json')) return 'typescript';\n return null;\n}\n\n/** Gap detection rules: [files-any-present, gap message]. */\nconst GAP_RULES: ReadonlyArray<readonly [readonly string[], string]> = [\n [['SECURITY.md'], 'No SECURITY.md policy'],\n [['CODEOWNERS'], 'No CODEOWNERS file'],\n [['LICENSE', 'LICENSE.md'], 'No LICENSE file'],\n [\n ['.semgrep.yml', '.semgrep', '.grype.yaml', '.snyk'],\n 'No SAST/SCA security scanning configured',\n ],\n // Test detection handled separately via detectTestInfra (supports monorepo + co-located patterns)\n [['.gitignore'], 'No .gitignore file'],\n];\n\n/** Scanner recommendation per language. Canonical source: secure-language-stacks. */\ninterface LanguageScanners {\n readonly sast: readonly string[];\n readonly sca: readonly string[];\n}\n\nconst LANGUAGE_SCANNER_MATRIX: Readonly<Record<string, LanguageScanners>> = {\n TypeScript: {\n sast: ['semgrep (p/typescript, p/nodejs)', 'eslint-plugin-security'],\n sca: ['osv-scanner', 'npm audit'],\n },\n JavaScript: {\n sast: ['semgrep (p/javascript, p/nodejs)', 'eslint-plugin-security'],\n sca: ['osv-scanner', 'npm audit'],\n },\n Python: {\n sast: ['semgrep (p/python)', 'bandit'],\n sca: ['osv-scanner', 'pip-audit'],\n },\n Java: {\n sast: ['semgrep (p/java)', 'spotbugs + find-sec-bugs'],\n sca: ['osv-scanner', 'OWASP dependency-check'],\n },\n Go: {\n sast: ['semgrep (p/golang)', 'gosec'],\n sca: ['osv-scanner', 'govulncheck'],\n },\n Rust: {\n sast: ['semgrep (p/rust)'],\n sca: ['osv-scanner', 'cargo-audit'],\n },\n 'C++': {\n sast: ['semgrep (p/c)', 'cppcheck'],\n sca: ['osv-scanner'],\n },\n C: {\n sast: ['semgrep (p/c)', 'cppcheck'],\n sca: ['osv-scanner'],\n },\n Kotlin: {\n sast: ['semgrep (p/kotlin)', 'detekt'],\n sca: ['osv-scanner', 'OWASP dependency-check'],\n },\n Swift: {\n sast: ['semgrep (p/swift)'],\n sca: ['osv-scanner'],\n },\n Ruby: {\n sast: ['semgrep (p/ruby)', 'brakeman'],\n sca: ['osv-scanner', 'bundler-audit'],\n },\n PHP: {\n sast: ['semgrep (p/php)', 'phpstan'],\n sca: ['osv-scanner', 'composer audit'],\n },\n Shell: {\n sast: ['semgrep (p/bash)', 'shellcheck'],\n sca: [],\n },\n HCL: {\n sast: ['semgrep (p/terraform)', 'tfsec'],\n sca: ['osv-scanner'],\n },\n};\n\n/** Generate language-specific scanner recommendations when SAST/SCA is missing. */\nexport function getLanguageRecommendations(\n language: string | null,\n securityTooling: readonly string[]\n): readonly string[] {\n if (language === null) return [];\n const scanners = LANGUAGE_SCANNER_MATRIX[language];\n if (scanners === undefined) return [];\n\n const hasSast = securityTooling.includes('semgrep') || securityTooling.includes('snyk');\n const hasSca =\n securityTooling.includes('osv-scanner') ||\n securityTooling.includes('grype') ||\n securityTooling.includes('snyk');\n\n const recs: string[] = [];\n if (!hasSast && scanners.sast.length > 0) {\n const tools = scanners.sast.join(', ');\n recs.push(`${language} project missing SAST: ${tools}`);\n }\n if (!hasSca && scanners.sca.length > 0) {\n const tools = scanners.sca.join(', ');\n recs.push(`${language} project missing SCA: ${tools}`);\n }\n return recs;\n}\n\n/** SAST tool names that suppress the generic gap message. */\nconst SAST_TOOLS = new Set(['semgrep', 'codeql', 'snyk']);\nconst SAST_GAP_MSG = 'No SAST/SCA security scanning configured';\n\n/** Remove the SAST/SCA gap if any SAST tool was detected (#1674). */\nfunction removeSastGapIfToolDetected(gaps: string[], secTools: readonly string[]): void {\n if (secTools.some((t) => SAST_TOOLS.has(t))) {\n const idx = gaps.indexOf(SAST_GAP_MSG);\n if (idx !== -1) gaps.splice(idx, 1);\n }\n}\n\n/** Identify gaps in repository best practices. */\nexport function identifyGaps(\n entries: readonly string[],\n ciProvider: string | null,\n language?: string | null,\n securityTooling?: readonly string[]\n): readonly string[] {\n const gaps: string[] = [];\n if (ciProvider === null) gaps.push('No CI/CD configuration detected');\n for (const [files, message] of GAP_RULES) {\n if (!files.some((f) => entries.includes(f))) gaps.push(message);\n }\n // Test detection: uses detectTestInfra for monorepo + co-located pattern support (#1130)\n if (!detectTestInfra(entries)) gaps.push('No test directory detected');\n\n // Remove SAST/SCA gap if workflow-level security was detected (#1674)\n removeSastGapIfToolDetected(gaps, securityTooling ?? []);\n\n // Language-specific recommendations when generic SAST/SCA gap detected\n const hasGenericSecGap = gaps.includes('No SAST/SCA security scanning configured');\n if (\n hasGenericSecGap &&\n language !== null &&\n language !== undefined &&\n securityTooling !== undefined\n ) {\n const langRecs = getLanguageRecommendations(language, securityTooling);\n gaps.push(...langRecs);\n }\n\n return gaps;\n}\n\n// ============================================================================\n// Core\n// ============================================================================\n\n/** GitHub repo metadata from the API. */\nexport interface GhRepoMetadata {\n readonly name: string;\n readonly full_name: string;\n readonly description: string | null;\n readonly language: string | null;\n readonly default_branch: string;\n readonly stargazers_count: number;\n readonly license: { readonly spdx_id: string } | null;\n}\n\n/** Analyze a GitHub repository given its metadata and file tree. */\nexport function analyzeRepo(\n metadata: GhRepoMetadata,\n topLevelEntries: readonly string[],\n workflowEntries?: readonly string[]\n): RepoAnalysis {\n const ciProvider = detectCiProvider(topLevelEntries);\n const secTooling = detectSecurityTooling(topLevelEntries, workflowEntries);\n const hasTests = detectTestInfra(topLevelEntries);\n\n return {\n name: metadata.full_name,\n language: metadata.language,\n framework: detectFramework(topLevelEntries),\n packageManager: detectPackageManager(topLevelEntries),\n ciProvider,\n securityTooling: secTooling,\n // Match `Dockerfile`, `Dockerfile.<purpose>` (e.g. `Dockerfile.sandbox`),\n // and docker-compose variants. Pre-#2730 the check was exact-match only,\n // so a repo with three legitimate `Dockerfile.*` files reported false.\n hasDockerfile:\n topLevelEntries.some((e) => e === 'Dockerfile' || e.startsWith('Dockerfile.')) ||\n topLevelEntries.includes('docker-compose.yml') ||\n topLevelEntries.includes('docker-compose.yaml'),\n hasHelmCharts:\n topLevelEntries.includes('Chart.yaml') ||\n topLevelEntries.includes('charts') ||\n topLevelEntries.includes('helm'),\n hasMakefile: topLevelEntries.includes('Makefile'),\n hasTests,\n license: metadata.license?.spdx_id ?? null,\n description: metadata.description,\n defaultBranch: metadata.default_branch,\n stars: metadata.stargazers_count,\n topLevelEntries: [...topLevelEntries],\n gaps: identifyGaps(topLevelEntries, ciProvider, metadata.language, secTooling),\n };\n}\n\n/** Non-code languages to exclude when detecting primary language. */\nconst MARKUP_LANGUAGES = new Set([\n 'HTML',\n 'CSS',\n 'SCSS',\n 'Less',\n 'Markdown',\n 'Roff',\n 'SVG',\n 'XML',\n 'XSLT',\n 'Mustache',\n 'Handlebars',\n 'EJS',\n]);\n\n/** Detect primary language from GitHub languages API (byte counts). */\nfunction detectPrimaryLanguage(\n languages: Record<string, number>,\n fallback: string | null\n): string | null {\n const sorted = Object.entries(languages)\n .filter(([lang]) => !MARKUP_LANGUAGES.has(lang))\n .sort((a, b) => b[1] - a[1]);\n const top = sorted[0];\n return top !== undefined ? top[0] : fallback;\n}\n\n/** Check for test infrastructure beyond top-level directories. */\nfunction detectTestInfra(entries: readonly string[]): boolean {\n const testDirs = ['tests', 'test', '__tests__', 'spec'];\n if (testDirs.some((d) => entries.includes(d))) return true;\n // Check for test config files (co-located test pattern, monorepos)\n const testConfigs = [\n 'vitest.config.ts',\n 'vitest.config.js',\n 'vitest.config.mts',\n 'vitest.workspace.ts',\n 'vitest.workspace.js',\n 'jest.config.ts',\n 'jest.config.js',\n 'jest.config.mjs',\n 'cypress.config.ts',\n 'cypress.config.js',\n 'playwright.config.ts',\n '.mocharc.yml',\n '.mocharc.json',\n ];\n if (testConfigs.some((c) => entries.includes(c))) return true;\n // Monorepo: packages/ dir + package.json implies co-located tests\n return entries.includes('packages') && entries.includes('package.json');\n}\n\n/** Infer code language from project files when GitHub reports markup. */\nfunction inferLanguageFromEntries(\n entries: readonly string[],\n fallback: string | null\n): string | null {\n if (entries.includes('tsconfig.json')) return 'TypeScript';\n if (entries.includes('Cargo.toml')) return 'Rust';\n if (entries.includes('go.mod')) return 'Go';\n if (entries.includes('pyproject.toml') || entries.includes('setup.py')) return 'Python';\n if (entries.includes('pom.xml') || entries.includes('build.gradle')) return 'Java';\n if (entries.includes('Gemfile')) return 'Ruby';\n if (entries.includes('package.json')) return 'JavaScript';\n return fallback;\n}\n\ntype ExecFileFn = (\n cmd: string,\n args: string[],\n options?: { timeout?: number }\n) => Promise<{ stdout: string }>;\n\n/** Lazy-load promisified execFile. */\nasync function getExecFile(): Promise<ExecFileFn> {\n const { execFile } = await import('node:child_process');\n const { promisify } = await import('node:util');\n return promisify(execFile);\n}\n\n/** Fetch repo metadata and languages via GitHub API. */\nasync function fetchRepoData(\n repoId: string,\n exec: ExecFileFn\n): Promise<{ metadata: GhRepoMetadata; entries: string[] }> {\n const { stdout: metaJson } = await exec(\n 'gh',\n [\n 'api',\n `repos/${repoId}`,\n '--jq',\n '{name: .name, full_name: .full_name, description: .description, language: .language, default_branch: .default_branch, stargazers_count: .stargazers_count, license: .license}',\n ],\n { timeout: 30_000 }\n );\n let metadata: GhRepoMetadata;\n try {\n metadata = JSON.parse(metaJson.trim()) as GhRepoMetadata;\n } catch {\n throw new Error(`Failed to parse repo metadata for ${repoId}: ${metaJson.slice(0, 200)}`);\n }\n const { stdout: contentsJson } = await exec(\n 'gh',\n ['api', `repos/${repoId}/contents`, '--jq', '[.[].name]'],\n { timeout: 30_000 }\n );\n let entries: string[];\n try {\n const parsed: unknown = JSON.parse(contentsJson.trim());\n entries = Array.isArray(parsed) ? parsed.filter((e): e is string => typeof e === 'string') : [];\n } catch {\n throw new Error(`Failed to parse repo contents for ${repoId}: ${contentsJson.slice(0, 200)}`);\n }\n return { metadata, entries };\n}\n\n/** Resolve NOASSERTION license via the GitHub license API. */\nasync function resolveLicense(repoId: string, exec: ExecFileFn): Promise<string | null> {\n try {\n const { stdout } = await exec(\n 'gh',\n ['api', `repos/${repoId}/license`, '--jq', '.license.spdx_id'],\n { timeout: 15_000 }\n );\n const spdxId = stdout.trim();\n if (spdxId !== '' && spdxId !== 'null' && spdxId !== 'NOASSERTION') {\n return spdxId;\n }\n } catch {\n // Keep NOASSERTION if license API also fails\n }\n return null;\n}\n\n/** Resolve primary language, falling back to entry inference for markup repos. */\nasync function resolveLanguage(\n repoId: string,\n entries: readonly string[],\n metadata: GhRepoMetadata,\n exec: ExecFileFn\n): Promise<string | null> {\n let languages: Record<string, number> = {};\n try {\n const { stdout } = await exec('gh', ['api', `repos/${repoId}/languages`], { timeout: 15_000 });\n languages = JSON.parse(stdout.trim()) as Record<string, number>;\n } catch {\n /* fall back to metadata.language */\n }\n const primary = detectPrimaryLanguage(languages, metadata.language);\n if (primary === null || MARKUP_LANGUAGES.has(primary)) {\n return inferLanguageFromEntries(entries, primary);\n }\n return primary;\n}\n\n/** Fetch workflow filenames from .github/workflows/ (#1674). Best-effort. */\nasync function fetchWorkflowEntries(repoId: string, exec: ExecFileFn): Promise<readonly string[]> {\n try {\n const { stdout } = await exec(\n 'gh',\n ['api', `repos/${repoId}/contents/.github/workflows`, '--jq', '[.[].name]'],\n { timeout: 15_000 }\n );\n const parsed: unknown = JSON.parse(stdout.trim());\n return Array.isArray(parsed) ? parsed.filter((e): e is string => typeof e === 'string') : [];\n } catch {\n return []; // No workflows directory or API error — graceful fallback\n }\n}\n\n/** Fetch repo data from GitHub and produce analysis. */\nexport async function analyzeGitHubRepo(input: RepoAnalyzeInput): Promise<RepoAnalysis> {\n const repoId = normalizeRepoId(input.repo);\n const exec = await getExecFile();\n const { metadata, entries } = await fetchRepoData(repoId, exec);\n\n const primaryLang = await resolveLanguage(repoId, entries, metadata, exec);\n const enhanced = { ...metadata, language: primaryLang };\n\n // Resolve null or NOASSERTION license when LICENSE file exists\n const hasLicenseFile = entries.includes('LICENSE') || entries.includes('LICENSE.md');\n const licenseUnresolved = enhanced.license === null || enhanced.license.spdx_id === 'NOASSERTION';\n if (licenseUnresolved && hasLicenseFile) {\n const resolved = await resolveLicense(repoId, exec);\n if (resolved !== null) enhanced.license = { spdx_id: resolved };\n }\n\n // Fetch workflow filenames for CI-level security detection (#1674)\n const workflowEntries = entries.includes('.github')\n ? await fetchWorkflowEntries(repoId, exec)\n : [];\n\n return analyzeRepo(enhanced, entries, workflowEntries);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
getAvailableClis,
|
|
24
24
|
isCliAvailable,
|
|
25
25
|
withTimeout
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-MV4R2ZIJ.js";
|
|
27
27
|
import {
|
|
28
28
|
SessionMemory
|
|
29
29
|
} from "./chunk-3VWMM6UF.js";
|
|
@@ -12993,7 +12993,7 @@ async function processVotesWithCascade(engineVotes, opts) {
|
|
|
12993
12993
|
var CONTRARIAN_ESCALATION_THRESHOLD = 0.8;
|
|
12994
12994
|
async function runContrarianCheck(proposal, log) {
|
|
12995
12995
|
try {
|
|
12996
|
-
const { executeExpert } = await import("./expert-bridge-
|
|
12996
|
+
const { executeExpert } = await import("./expert-bridge-NX2MGOBQ.js");
|
|
12997
12997
|
const prompt = [
|
|
12998
12998
|
"You are a contrarian analyst. Your job is to find reasons this proposal should be REJECTED.",
|
|
12999
12999
|
"Look for: YAGNI (not needed), MISALIGNED (wrong tech/architecture), SECURITY_RISK, SCOPE_CREEP.",
|
|
@@ -13415,4 +13415,4 @@ export {
|
|
|
13415
13415
|
CONSENSUS_VOTE_OUTPUT_SCHEMA,
|
|
13416
13416
|
registerConsensusVoteTool
|
|
13417
13417
|
};
|
|
13418
|
-
//# sourceMappingURL=chunk-
|
|
13418
|
+
//# sourceMappingURL=chunk-EEW7VFFF.js.map
|
|
@@ -38,7 +38,7 @@ function adaptCompositeRouter(compositeRouter) {
|
|
|
38
38
|
}
|
|
39
39
|
async function getRouter() {
|
|
40
40
|
if (cachedRouter !== null) return cachedRouter;
|
|
41
|
-
const { createAllAdapters } = await import("./factory-
|
|
41
|
+
const { createAllAdapters } = await import("./factory-JI6PSWGR.js");
|
|
42
42
|
const { createCompositeRouter } = await import("./composite-router-S6E26BCI.js");
|
|
43
43
|
const adapters = createAllAdapters();
|
|
44
44
|
if (adapters.size === 0) return null;
|
|
@@ -136,4 +136,4 @@ ${prompt}`;
|
|
|
136
136
|
export {
|
|
137
137
|
executeExpert
|
|
138
138
|
};
|
|
139
|
-
//# sourceMappingURL=chunk-
|
|
139
|
+
//# sourceMappingURL=chunk-FYAQBYHM.js.map
|
|
@@ -5,13 +5,13 @@ import {
|
|
|
5
5
|
resolveInsideRoot
|
|
6
6
|
} from "./chunk-NUBSJGQZ.js";
|
|
7
7
|
import {
|
|
8
|
-
createAllAdapters
|
|
9
|
-
|
|
8
|
+
createAllAdapters,
|
|
9
|
+
probeCli
|
|
10
|
+
} from "./chunk-MV4R2ZIJ.js";
|
|
10
11
|
import {
|
|
11
12
|
capitalize
|
|
12
13
|
} from "./chunk-633WH2ML.js";
|
|
13
14
|
import {
|
|
14
|
-
CLI_SUBPROCESS_TIMEOUTS,
|
|
15
15
|
CliNameSchema,
|
|
16
16
|
DEFAULT_CAPABILITIES,
|
|
17
17
|
DEFAULT_COMPOSITE_CONFIG,
|
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
} from "./chunk-GOT7OAL5.js";
|
|
41
41
|
|
|
42
42
|
// src/version.ts
|
|
43
|
-
var VERSION = true ? "2.77.
|
|
43
|
+
var VERSION = true ? "2.77.4" : "dev";
|
|
44
44
|
|
|
45
45
|
// src/config/schemas-core.ts
|
|
46
46
|
import { z } from "zod";
|
|
@@ -1297,18 +1297,18 @@ function getConfig(options) {
|
|
|
1297
1297
|
}
|
|
1298
1298
|
|
|
1299
1299
|
// src/cli/setup-data-dir.ts
|
|
1300
|
-
import { mkdirSync, existsSync as
|
|
1301
|
-
import { join as
|
|
1300
|
+
import { mkdirSync, existsSync as existsSync3 } from "fs";
|
|
1301
|
+
import { join as join3 } from "path";
|
|
1302
1302
|
|
|
1303
1303
|
// src/cli/doctor.ts
|
|
1304
1304
|
import {
|
|
1305
|
-
existsSync as
|
|
1306
|
-
readFileSync as
|
|
1305
|
+
existsSync as existsSync2,
|
|
1306
|
+
readFileSync as readFileSync2,
|
|
1307
1307
|
readdirSync,
|
|
1308
1308
|
accessSync,
|
|
1309
1309
|
constants as fsConstants
|
|
1310
1310
|
} from "fs";
|
|
1311
|
-
import { join as
|
|
1311
|
+
import { join as join2 } from "path";
|
|
1312
1312
|
|
|
1313
1313
|
// src/mcp/server.ts
|
|
1314
1314
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
@@ -1773,193 +1773,6 @@ function printDoctorResults(result) {
|
|
|
1773
1773
|
printDoctorSummary(result);
|
|
1774
1774
|
}
|
|
1775
1775
|
|
|
1776
|
-
// src/cli/cli-auth-probe.ts
|
|
1777
|
-
import { execFile } from "child_process";
|
|
1778
|
-
import { promisify } from "util";
|
|
1779
|
-
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
1780
|
-
import { homedir } from "os";
|
|
1781
|
-
import { join as join2 } from "path";
|
|
1782
|
-
var execFileAsync = promisify(execFile);
|
|
1783
|
-
var HOME = homedir();
|
|
1784
|
-
function claudeNeedsLogin(reason) {
|
|
1785
|
-
return {
|
|
1786
|
-
cli: "claude",
|
|
1787
|
-
state: "needs-login",
|
|
1788
|
-
reason,
|
|
1789
|
-
fixCommand: "claude /login",
|
|
1790
|
-
envFallback: "ANTHROPIC_API_KEY",
|
|
1791
|
-
fixUrl: "https://console.anthropic.com/account/keys"
|
|
1792
|
-
};
|
|
1793
|
-
}
|
|
1794
|
-
function probeClaude() {
|
|
1795
|
-
if (process.env["ANTHROPIC_API_KEY"] !== void 0 && process.env["ANTHROPIC_API_KEY"] !== "") {
|
|
1796
|
-
return { cli: "claude", state: "authenticated", via: "env-var" };
|
|
1797
|
-
}
|
|
1798
|
-
const credPath = join2(HOME, ".claude", ".credentials.json");
|
|
1799
|
-
if (!existsSync2(credPath)) {
|
|
1800
|
-
return claudeNeedsLogin(
|
|
1801
|
-
"No credentials at ~/.claude/.credentials.json and ANTHROPIC_API_KEY is not set"
|
|
1802
|
-
);
|
|
1803
|
-
}
|
|
1804
|
-
try {
|
|
1805
|
-
const parsed = JSON.parse(readFileSync2(credPath, "utf-8"));
|
|
1806
|
-
if (!isClaudeCredsShape(parsed)) {
|
|
1807
|
-
return claudeNeedsLogin(
|
|
1808
|
-
"Credentials file present but not in expected shape (missing claudeAiOauth.accessToken)"
|
|
1809
|
-
);
|
|
1810
|
-
}
|
|
1811
|
-
const expiresAt = parsed.claudeAiOauth.expiresAt;
|
|
1812
|
-
if (typeof expiresAt === "number" && expiresAt < Date.now()) {
|
|
1813
|
-
return claudeNeedsLogin(`OAuth token expired ${new Date(expiresAt).toISOString()}`);
|
|
1814
|
-
}
|
|
1815
|
-
return {
|
|
1816
|
-
cli: "claude",
|
|
1817
|
-
state: "authenticated",
|
|
1818
|
-
via: "cli-credentials",
|
|
1819
|
-
...typeof expiresAt === "number" ? { meta: { expiresAt } } : {}
|
|
1820
|
-
};
|
|
1821
|
-
} catch (e) {
|
|
1822
|
-
return {
|
|
1823
|
-
cli: "claude",
|
|
1824
|
-
state: "error",
|
|
1825
|
-
reason: `Failed to read claude credentials: ${e instanceof Error ? e.message : String(e)}`
|
|
1826
|
-
};
|
|
1827
|
-
}
|
|
1828
|
-
}
|
|
1829
|
-
function codexNeedsLogin(reason) {
|
|
1830
|
-
return {
|
|
1831
|
-
cli: "codex",
|
|
1832
|
-
state: "needs-login",
|
|
1833
|
-
reason,
|
|
1834
|
-
fixCommand: "codex login",
|
|
1835
|
-
envFallback: "OPENAI_API_KEY",
|
|
1836
|
-
fixUrl: "https://platform.openai.com/api-keys"
|
|
1837
|
-
};
|
|
1838
|
-
}
|
|
1839
|
-
function classifyCodexStdout(stdout) {
|
|
1840
|
-
if (/not logged/i.test(stdout) || /no.*token/i.test(stdout)) {
|
|
1841
|
-
return codexNeedsLogin(stdout.trim().split("\n")[0] ?? "Not logged in");
|
|
1842
|
-
}
|
|
1843
|
-
return { cli: "codex", state: "authenticated", via: "cli-credentials" };
|
|
1844
|
-
}
|
|
1845
|
-
async function probeCodex() {
|
|
1846
|
-
if (process.env["OPENAI_API_KEY"] !== void 0 && process.env["OPENAI_API_KEY"] !== "") {
|
|
1847
|
-
return { cli: "codex", state: "authenticated", via: "env-var" };
|
|
1848
|
-
}
|
|
1849
|
-
try {
|
|
1850
|
-
const { stdout } = await execFileAsync("codex", ["login", "status"], {
|
|
1851
|
-
timeout: CLI_SUBPROCESS_TIMEOUTS.spawnMs
|
|
1852
|
-
});
|
|
1853
|
-
return classifyCodexStdout(stdout);
|
|
1854
|
-
} catch (e) {
|
|
1855
|
-
const msg = e instanceof Error ? e.message : String(e);
|
|
1856
|
-
if (/ENOENT|not found/i.test(msg)) {
|
|
1857
|
-
return { cli: "codex", state: "not-installed", reason: "codex binary not on PATH" };
|
|
1858
|
-
}
|
|
1859
|
-
return codexNeedsLogin("Not logged in (codex login status returned non-zero)");
|
|
1860
|
-
}
|
|
1861
|
-
}
|
|
1862
|
-
function geminiNeedsLogin(reason) {
|
|
1863
|
-
return {
|
|
1864
|
-
cli: "gemini",
|
|
1865
|
-
state: "needs-login",
|
|
1866
|
-
reason,
|
|
1867
|
-
fixCommand: "gemini",
|
|
1868
|
-
envFallback: "GOOGLE_AI_API_KEY",
|
|
1869
|
-
fixUrl: "https://aistudio.google.com/apikey"
|
|
1870
|
-
};
|
|
1871
|
-
}
|
|
1872
|
-
function classifyGeminiCreds(parsed) {
|
|
1873
|
-
if (!isGeminiCredsShape(parsed)) {
|
|
1874
|
-
return geminiNeedsLogin("OAuth credentials file present but not in expected shape");
|
|
1875
|
-
}
|
|
1876
|
-
if (typeof parsed.expiry_date === "number" && parsed.expiry_date < Date.now()) {
|
|
1877
|
-
return geminiNeedsLogin(
|
|
1878
|
-
`OAuth access token expired ${new Date(parsed.expiry_date).toISOString()} (refresh may still work)`
|
|
1879
|
-
);
|
|
1880
|
-
}
|
|
1881
|
-
return {
|
|
1882
|
-
cli: "gemini",
|
|
1883
|
-
state: "authenticated",
|
|
1884
|
-
via: "cli-credentials",
|
|
1885
|
-
...typeof parsed.expiry_date === "number" ? { meta: { expiresAt: parsed.expiry_date } } : {}
|
|
1886
|
-
};
|
|
1887
|
-
}
|
|
1888
|
-
function probeGemini() {
|
|
1889
|
-
const env = process.env["GOOGLE_AI_API_KEY"] ?? process.env["GEMINI_API_KEY"];
|
|
1890
|
-
if (env !== void 0 && env !== "") {
|
|
1891
|
-
return { cli: "gemini", state: "authenticated", via: "env-var" };
|
|
1892
|
-
}
|
|
1893
|
-
const credPath = join2(HOME, ".gemini", "oauth_creds.json");
|
|
1894
|
-
if (!existsSync2(credPath)) {
|
|
1895
|
-
return geminiNeedsLogin(
|
|
1896
|
-
"No OAuth credentials at ~/.gemini/oauth_creds.json and GOOGLE_AI_API_KEY/GEMINI_API_KEY are not set"
|
|
1897
|
-
);
|
|
1898
|
-
}
|
|
1899
|
-
try {
|
|
1900
|
-
return classifyGeminiCreds(JSON.parse(readFileSync2(credPath, "utf-8")));
|
|
1901
|
-
} catch (e) {
|
|
1902
|
-
return {
|
|
1903
|
-
cli: "gemini",
|
|
1904
|
-
state: "error",
|
|
1905
|
-
reason: `Failed to read gemini credentials: ${e instanceof Error ? e.message : String(e)}`
|
|
1906
|
-
};
|
|
1907
|
-
}
|
|
1908
|
-
}
|
|
1909
|
-
async function probeOpencode() {
|
|
1910
|
-
try {
|
|
1911
|
-
const { stdout } = await execFileAsync("opencode", ["auth", "list"], {
|
|
1912
|
-
timeout: CLI_SUBPROCESS_TIMEOUTS.spawnMs
|
|
1913
|
-
});
|
|
1914
|
-
if (/0 credentials/i.test(stdout)) {
|
|
1915
|
-
return {
|
|
1916
|
-
cli: "opencode",
|
|
1917
|
-
state: "needs-login",
|
|
1918
|
-
reason: "No providers configured in opencode",
|
|
1919
|
-
fixCommand: "opencode auth login",
|
|
1920
|
-
fixUrl: "https://opencode.ai/docs/config"
|
|
1921
|
-
};
|
|
1922
|
-
}
|
|
1923
|
-
return { cli: "opencode", state: "authenticated", via: "cli-credentials" };
|
|
1924
|
-
} catch (e) {
|
|
1925
|
-
const msg = e instanceof Error ? e.message : String(e);
|
|
1926
|
-
if (/ENOENT|not found/i.test(msg)) {
|
|
1927
|
-
return { cli: "opencode", state: "not-installed", reason: "opencode binary not on PATH" };
|
|
1928
|
-
}
|
|
1929
|
-
return {
|
|
1930
|
-
cli: "opencode",
|
|
1931
|
-
state: "error",
|
|
1932
|
-
reason: msg.split("\n")[0] ?? "opencode auth list failed"
|
|
1933
|
-
};
|
|
1934
|
-
}
|
|
1935
|
-
}
|
|
1936
|
-
function isClaudeCredsShape(v) {
|
|
1937
|
-
if (typeof v !== "object" || v === null) return false;
|
|
1938
|
-
const oauth = v.claudeAiOauth;
|
|
1939
|
-
if (typeof oauth !== "object" || oauth === null) return false;
|
|
1940
|
-
return typeof oauth.accessToken === "string";
|
|
1941
|
-
}
|
|
1942
|
-
function isGeminiCredsShape(v) {
|
|
1943
|
-
if (typeof v !== "object" || v === null) return false;
|
|
1944
|
-
return typeof v.access_token === "string";
|
|
1945
|
-
}
|
|
1946
|
-
async function probeCli(cli) {
|
|
1947
|
-
switch (cli) {
|
|
1948
|
-
case "claude":
|
|
1949
|
-
return Promise.resolve(probeClaude());
|
|
1950
|
-
case "codex":
|
|
1951
|
-
return probeCodex();
|
|
1952
|
-
case "gemini":
|
|
1953
|
-
return Promise.resolve(probeGemini());
|
|
1954
|
-
case "opencode":
|
|
1955
|
-
return probeOpencode();
|
|
1956
|
-
}
|
|
1957
|
-
}
|
|
1958
|
-
async function probeAllClis() {
|
|
1959
|
-
const clis = ["claude", "gemini", "codex", "opencode"];
|
|
1960
|
-
return Promise.all(clis.map((c) => probeCli(c)));
|
|
1961
|
-
}
|
|
1962
|
-
|
|
1963
1776
|
// src/cli/doctor.ts
|
|
1964
1777
|
var REQUIRED_NODE_MAJOR2 = 22;
|
|
1965
1778
|
var API_KEY_VARS = ["ANTHROPIC_API_KEY", "OPENAI_API_KEY", "GOOGLE_AI_API_KEY"];
|
|
@@ -2088,7 +1901,7 @@ function checkApiKeys() {
|
|
|
2088
1901
|
}
|
|
2089
1902
|
function checkConfigFile() {
|
|
2090
1903
|
for (const configPath of CONFIG_FILE_PATHS) {
|
|
2091
|
-
if (
|
|
1904
|
+
if (existsSync2(configPath)) {
|
|
2092
1905
|
return { found: true, path: configPath };
|
|
2093
1906
|
}
|
|
2094
1907
|
}
|
|
@@ -2129,11 +1942,11 @@ function buildRegistryAdvisory(cliResults) {
|
|
|
2129
1942
|
function hasPriorUsage() {
|
|
2130
1943
|
try {
|
|
2131
1944
|
const root = getNexusDataDir();
|
|
2132
|
-
if (!
|
|
1945
|
+
if (!existsSync2(root)) return false;
|
|
2133
1946
|
for (const sub of ["audit", "learning", "sessions", "voting"]) {
|
|
2134
1947
|
const p = `${root}/${sub}`;
|
|
2135
1948
|
try {
|
|
2136
|
-
if (
|
|
1949
|
+
if (existsSync2(p) && readdirSync(p).length > 0) return true;
|
|
2137
1950
|
} catch {
|
|
2138
1951
|
}
|
|
2139
1952
|
}
|
|
@@ -2143,13 +1956,13 @@ function hasPriorUsage() {
|
|
|
2143
1956
|
}
|
|
2144
1957
|
}
|
|
2145
1958
|
function countJsonlLines(filePath) {
|
|
2146
|
-
if (!
|
|
2147
|
-
return
|
|
1959
|
+
if (!existsSync2(filePath)) return 0;
|
|
1960
|
+
return readFileSync2(filePath, "utf-8").split("\n").filter((l) => l.trim().length > 0).length;
|
|
2148
1961
|
}
|
|
2149
1962
|
function readRulesMetadata(filePath) {
|
|
2150
|
-
if (!
|
|
1963
|
+
if (!existsSync2(filePath)) return { count: 0, savedAt: null };
|
|
2151
1964
|
try {
|
|
2152
|
-
const raw = JSON.parse(
|
|
1965
|
+
const raw = JSON.parse(readFileSync2(filePath, "utf-8"));
|
|
2153
1966
|
const rules = raw["rules"];
|
|
2154
1967
|
const saved = raw["savedAt"];
|
|
2155
1968
|
return {
|
|
@@ -2161,7 +1974,7 @@ function readRulesMetadata(filePath) {
|
|
|
2161
1974
|
}
|
|
2162
1975
|
}
|
|
2163
1976
|
function checkDirAccess(dir) {
|
|
2164
|
-
const exists =
|
|
1977
|
+
const exists = existsSync2(dir);
|
|
2165
1978
|
if (!exists) return { exists: false, writable: false };
|
|
2166
1979
|
try {
|
|
2167
1980
|
accessSync(dir, fsConstants.W_OK);
|
|
@@ -2221,10 +2034,10 @@ async function checkSqlite() {
|
|
|
2221
2034
|
}
|
|
2222
2035
|
function checkDataDirectory() {
|
|
2223
2036
|
const rootPath = getNexusDataDir();
|
|
2224
|
-
const rootExists =
|
|
2037
|
+
const rootExists = existsSync2(rootPath);
|
|
2225
2038
|
const subdirectories = DATA_SUBDIRECTORIES.map((name) => {
|
|
2226
|
-
const fullPath =
|
|
2227
|
-
const exists =
|
|
2039
|
+
const fullPath = join2(rootPath, name);
|
|
2040
|
+
const exists = existsSync2(fullPath);
|
|
2228
2041
|
return { name, path: fullPath, exists, writable: exists && isWritable(fullPath) };
|
|
2229
2042
|
});
|
|
2230
2043
|
return { rootExists, rootPath, subdirectories };
|
|
@@ -2308,7 +2121,7 @@ async function runDoctorFix(result) {
|
|
|
2308
2121
|
writeLine2("\u2500".repeat(40));
|
|
2309
2122
|
let fixCount = 0;
|
|
2310
2123
|
if (!result.dataDirectory.rootExists || result.dataDirectory.subdirectories.some((d) => !d.exists || !d.writable)) {
|
|
2311
|
-
const { runSetup } = await import("./setup-command-
|
|
2124
|
+
const { runSetup } = await import("./setup-command-DB3DOE6K.js");
|
|
2312
2125
|
const setupResult = runSetup({
|
|
2313
2126
|
skipMcp: true,
|
|
2314
2127
|
skipRules: true,
|
|
@@ -2355,7 +2168,7 @@ function initDataDirectories(dryRun = false) {
|
|
|
2355
2168
|
ensureDir(NEXUS_DATA_DIR, dryRun, created, alreadyExisted);
|
|
2356
2169
|
for (const subdir of DATA_SUBDIRECTORIES) {
|
|
2357
2170
|
const mode = RESTRICTED_DIRS.has(subdir) ? 448 : void 0;
|
|
2358
|
-
ensureDir(
|
|
2171
|
+
ensureDir(join3(NEXUS_DATA_DIR, subdir), dryRun, created, alreadyExisted, mode);
|
|
2359
2172
|
}
|
|
2360
2173
|
return { success: true, rootPath: NEXUS_DATA_DIR, created, alreadyExisted, error: null };
|
|
2361
2174
|
} catch (error) {
|
|
@@ -2364,7 +2177,7 @@ function initDataDirectories(dryRun = false) {
|
|
|
2364
2177
|
}
|
|
2365
2178
|
}
|
|
2366
2179
|
function ensureDir(dirPath, dryRun, created, alreadyExisted, mode) {
|
|
2367
|
-
if (
|
|
2180
|
+
if (existsSync3(dirPath)) {
|
|
2368
2181
|
alreadyExisted.push(dirPath);
|
|
2369
2182
|
return;
|
|
2370
2183
|
}
|
|
@@ -2406,7 +2219,6 @@ export {
|
|
|
2406
2219
|
filterAvailableModels,
|
|
2407
2220
|
DEFAULT_TASK_TTL_MS,
|
|
2408
2221
|
clampTaskTtl,
|
|
2409
|
-
probeAllClis,
|
|
2410
2222
|
DATA_SUBDIRECTORIES,
|
|
2411
2223
|
checkApiKeys,
|
|
2412
2224
|
checkSqlite,
|
|
@@ -2419,4 +2231,4 @@ export {
|
|
|
2419
2231
|
startStdioServer,
|
|
2420
2232
|
closeServer
|
|
2421
2233
|
};
|
|
2422
|
-
//# sourceMappingURL=chunk-
|
|
2234
|
+
//# sourceMappingURL=chunk-LIY6WZNR.js.map
|