@cdxgen/cdxgen 13.5.0 → 13.7.0
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/README.md +17 -10
- package/bin/audit.js +7 -4
- package/bin/cdxgen.js +260 -37
- package/bin/convert.js +146 -22
- package/bin/evinse.js +28 -3
- package/bin/repl.js +47 -3
- package/bin/sign.js +211 -34
- package/bin/tracebom.js +18 -6
- package/bin/validate.js +24 -3
- package/bin/verify.js +113 -5
- package/data/behavior-taxonomy.schema.json +1491 -0
- package/data/cyclonedx-2.0-bundled.schema.json +18606 -5528
- package/data/cyclonedx-2.0-cryptography-defs.schema.json +857 -0
- package/data/license-aliases.json +24 -2
- package/data/pqc-migration.json +239 -0
- package/data/remediations.json +176 -0
- package/data/rules/ai-bom.yaml +1 -1
- package/data/rules/brotli-decoder.yaml +107 -0
- package/data/rules/cbom-security.yaml +4 -3
- package/data/rules/package-integrity.yaml +28 -0
- package/data/rules/vscode-extensions.yaml +75 -0
- package/data/spdx-license-list.json +121 -7
- package/data/spdx-licenses.json +69 -0
- package/data/spdx.schema.json +845 -2
- package/lib/audit/index.js +25 -3
- package/lib/cli/bomAssembly.js +172 -4
- package/lib/cli/cliOptions.js +121 -17
- package/lib/cli/index.js +720 -902
- package/lib/cli/jsBom.js +156 -64
- package/lib/cli/jvmBom.js +602 -86
- package/lib/cli/managedBom.js +161 -19
- package/lib/cli/nativeBom.js +52 -5
- package/lib/core/boundedFile.js +344 -0
- package/lib/core/brotliProbe.js +182 -0
- package/lib/core/env.js +34 -0
- package/lib/core/fs.js +138 -3
- package/lib/core/globPatterns.js +218 -0
- package/lib/core/httpClient.js +98 -1
- package/lib/core/lockPaths.js +38 -0
- package/lib/core/paths.js +24 -1
- package/lib/core/processTree.js +100 -8
- package/lib/core/projectConfig.js +332 -25
- package/lib/core/toolRegistry.js +184 -0
- package/lib/ecosystems/cppEvidence.js +263 -106
- package/lib/ecosystems/cppIncludeResolver.js +16 -5
- package/lib/ecosystems/denoutils.js +2 -2
- package/lib/ecosystems/ecosystems.js +25 -10
- package/lib/ecosystems/gemHostProbe.js +301 -0
- package/lib/ecosystems/golem.js +3 -8
- package/lib/ecosystems/gradleutils.js +1909 -229
- package/lib/ecosystems/jsEvidence.js +90 -38
- package/lib/ecosystems/kosi.js +3 -5
- package/lib/ecosystems/npmVersionResolution.js +376 -0
- package/lib/ecosystems/parsers-bazel.js +107 -6
- package/lib/ecosystems/parsers-js.js +505 -22
- package/lib/ecosystems/parsers-misc.js +209 -20
- package/lib/ecosystems/parsers-python.js +178 -30
- package/lib/ecosystems/parsers-rust.js +117 -15
- package/lib/ecosystems/pythonutils.js +128 -2
- package/lib/ecosystems/remote/huggingface.js +22 -0
- package/lib/ecosystems/rubyutils.js +538 -31
- package/lib/ecosystems/rusi.js +2 -4
- package/lib/ecosystems/scalacliutils.js +2 -0
- package/lib/ecosystems/scalasem.js +798 -152
- package/lib/ecosystems/vendoredCode.js +237 -3
- package/lib/ecosystems/venvProbe.js +360 -0
- package/lib/evinser/evinser.js +536 -71
- package/lib/evinser/scalasem.js +5 -1
- package/lib/helpers/agenticToolutils.js +525 -94
- package/lib/helpers/bomSigner.js +43 -9
- package/lib/helpers/jssSigner.js +1276 -0
- package/lib/helpers/vsixutils.js +1574 -315
- package/lib/inventory/agentBlueprint.js +193 -0
- package/lib/inventory/agentToolNames.js +145 -0
- package/lib/inventory/aiCollector.js +153 -7
- package/lib/inventory/aiInventory.js +44 -8
- package/lib/inventory/aiProviders.js +324 -0
- package/lib/inventory/atomUtils.js +77 -0
- package/lib/inventory/bomUtils.js +8 -1
- package/lib/inventory/brotliDecoder.js +142 -0
- package/lib/inventory/buildToolRateLimit.js +1 -1
- package/lib/inventory/cbomutils.js +56 -7
- package/lib/inventory/ciParsers/githubActionsLock.js +821 -0
- package/lib/inventory/citations.js +31 -2
- package/lib/inventory/communityAiConfigParser.js +978 -80
- package/lib/inventory/cyclonedx20.js +152 -0
- package/lib/inventory/cyclonedx20Common.js +286 -0
- package/lib/inventory/cyclonedx20Derived.js +159 -0
- package/lib/inventory/cyclonedx20Parties.js +552 -0
- package/lib/inventory/cyclonedx20Read.js +768 -0
- package/lib/inventory/cyclonedx20ReadCommon.js +374 -0
- package/lib/inventory/cyclonedx20ReadComponents.js +692 -0
- package/lib/inventory/cyclonedx20ReadContext.js +380 -0
- package/lib/inventory/cyclonedx20ReadEvidence.js +466 -0
- package/lib/inventory/cyclonedx20ReadSections.js +599 -0
- package/lib/inventory/cyclonedx20Render.js +766 -0
- package/lib/inventory/cyclonedx20RenderComponents.js +716 -0
- package/lib/inventory/cyclonedx20RenderDefinitions.js +405 -0
- package/lib/inventory/cyclonedx20RenderEvidence.js +726 -0
- package/lib/inventory/cyclonedx20RenderHardware.js +203 -0
- package/lib/inventory/cyclonedx20RenderPatents.js +174 -0
- package/lib/inventory/cyclonedx20RenderRefIds.js +314 -0
- package/lib/inventory/cyclonedx20RenderSections.js +499 -0
- package/lib/inventory/cyclonedx20Tables.js +594 -0
- package/lib/inventory/deps.js +141 -13
- package/lib/inventory/dosai.js +375 -6
- package/lib/inventory/dosaiParsers.js +3 -6
- package/lib/inventory/dotnetRuntime.js +367 -0
- package/lib/inventory/ecosystemFormulationParsers.js +979 -0
- package/lib/inventory/envcontext.js +436 -48
- package/lib/inventory/evidenceUtils.js +13 -1
- package/lib/inventory/fetchBatch.js +1 -1
- package/lib/inventory/formulationParsers.js +124 -14
- package/lib/inventory/gtfobins.js +13 -0
- package/lib/inventory/hbom.js +45 -6
- package/lib/inventory/hbomLoader.js +166 -0
- package/lib/inventory/hostRuntimeProbe.js +686 -0
- package/lib/inventory/jvmLocalRepos.js +9 -2
- package/lib/inventory/jvmToolEnv.js +29 -0
- package/lib/inventory/licenseEnhancer.js +12 -0
- package/lib/inventory/mavenCentralMirror.js +534 -0
- package/lib/inventory/mcpConfigParser.js +5 -0
- package/lib/inventory/nodeBuildInfo.js +218 -0
- package/lib/inventory/nodeHostProbe.js +202 -0
- package/lib/inventory/occurrenceKey.js +90 -0
- package/lib/inventory/osPackageResolver.js +182 -0
- package/lib/inventory/phpBuildInfo.js +10 -59
- package/lib/inventory/phpHostProbe.js +32 -488
- package/lib/inventory/pqcMigration.js +426 -0
- package/lib/inventory/rubyBuildInfo.js +972 -0
- package/lib/inventory/rubyHostProbe.js +218 -0
- package/lib/inventory/rustFormulationParser.js +21 -10
- package/lib/inventory/scalaCoords.js +4 -3
- package/lib/inventory/scalaDedupe.js +440 -0
- package/lib/inventory/source.js +114 -8
- package/lib/managers/binary.js +337 -3
- package/lib/managers/docker.js +79 -0
- package/lib/parsers/huggingfaceManifest.js +9 -1
- package/lib/parsers/huggingfaceUtils.js +18 -0
- package/lib/parsers/kiroPermissions.js +166 -0
- package/lib/parsers/largeJson.js +28 -11
- package/lib/parsers/vscodeExtensionId.js +183 -0
- package/lib/server/server.js +48 -35
- package/lib/stages/postgen/postgen.js +41 -1
- package/lib/stages/postgen/ruleEngine.js +13 -5
- package/lib/stages/postgen/specVersionCompat.js +76 -0
- package/lib/stages/pregen/envAudit.js +1 -0
- package/lib/stages/pregen/pregen.js +114 -57
- package/lib/validator/bomValidator.js +14 -2
- package/lib/validator/complianceEngine.js +30 -3
- package/lib/validator/complianceRules.js +1416 -4
- package/lib/validator/generated/validate-1.6.mjs +1 -1
- package/lib/validator/generated/validate-1.7.mjs +1 -1
- package/lib/validator/generated/validate-2.0.mjs +57554 -13851
- package/lib/validator/index.js +49 -8
- package/lib/validator/reporters/json.js +6 -0
- package/package.json +11 -10
- package/types/bin/repl.d.ts.map +1 -1
- package/types/lib/audit/index.d.ts +6 -2
- package/types/lib/audit/index.d.ts.map +1 -1
- package/types/lib/cli/bomAssembly.d.ts +29 -1
- package/types/lib/cli/bomAssembly.d.ts.map +1 -1
- package/types/lib/cli/cliOptions.d.ts +6 -0
- package/types/lib/cli/cliOptions.d.ts.map +1 -1
- package/types/lib/cli/index.d.ts.map +1 -1
- package/types/lib/cli/jsBom.d.ts +3 -18
- package/types/lib/cli/jsBom.d.ts.map +1 -1
- package/types/lib/cli/jvmBom.d.ts +15 -0
- package/types/lib/cli/jvmBom.d.ts.map +1 -1
- package/types/lib/cli/managedBom.d.ts.map +1 -1
- package/types/lib/cli/nativeBom.d.ts.map +1 -1
- package/types/lib/core/boundedFile.d.ts +100 -0
- package/types/lib/core/boundedFile.d.ts.map +1 -0
- package/types/lib/core/brotliProbe.d.ts +37 -0
- package/types/lib/core/brotliProbe.d.ts.map +1 -0
- package/types/lib/core/env.d.ts +14 -0
- package/types/lib/core/env.d.ts.map +1 -1
- package/types/lib/core/fs.d.ts +4 -0
- package/types/lib/core/fs.d.ts.map +1 -1
- package/types/lib/core/globPatterns.d.ts +70 -0
- package/types/lib/core/globPatterns.d.ts.map +1 -0
- package/types/lib/core/httpClient.d.ts +24 -0
- package/types/lib/core/httpClient.d.ts.map +1 -1
- package/types/lib/core/lockPaths.d.ts +19 -0
- package/types/lib/core/lockPaths.d.ts.map +1 -0
- package/types/lib/core/paths.d.ts +9 -0
- package/types/lib/core/paths.d.ts.map +1 -1
- package/types/lib/core/processTree.d.ts +17 -4
- package/types/lib/core/processTree.d.ts.map +1 -1
- package/types/lib/core/projectConfig.d.ts +47 -8
- package/types/lib/core/projectConfig.d.ts.map +1 -1
- package/types/lib/core/toolRegistry.d.ts +36 -0
- package/types/lib/core/toolRegistry.d.ts.map +1 -0
- package/types/lib/ecosystems/cppEvidence.d.ts +40 -13
- package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -1
- package/types/lib/ecosystems/cppIncludeResolver.d.ts +2 -1
- package/types/lib/ecosystems/cppIncludeResolver.d.ts.map +1 -1
- package/types/lib/ecosystems/ecosystems.d.ts.map +1 -1
- package/types/lib/ecosystems/gemHostProbe.d.ts +28 -0
- package/types/lib/ecosystems/gemHostProbe.d.ts.map +1 -0
- package/types/lib/ecosystems/golem.d.ts.map +1 -1
- package/types/lib/ecosystems/gradleutils.d.ts +294 -20
- package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
- package/types/lib/ecosystems/jsEvidence.d.ts +14 -1
- package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -1
- package/types/lib/ecosystems/kosi.d.ts.map +1 -1
- package/types/lib/ecosystems/npmVersionResolution.d.ts +119 -0
- package/types/lib/ecosystems/npmVersionResolution.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-bazel.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-js.d.ts +17 -20
- package/types/lib/ecosystems/parsers-js.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-misc.d.ts +19 -0
- package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-python.d.ts +10 -0
- package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-rust.d.ts.map +1 -1
- package/types/lib/ecosystems/pythonutils.d.ts +19 -1
- package/types/lib/ecosystems/pythonutils.d.ts.map +1 -1
- package/types/lib/ecosystems/remote/huggingface.d.ts.map +1 -1
- package/types/lib/ecosystems/rubyutils.d.ts +144 -12
- package/types/lib/ecosystems/rubyutils.d.ts.map +1 -1
- package/types/lib/ecosystems/rusi.d.ts.map +1 -1
- package/types/lib/ecosystems/scalacliutils.d.ts.map +1 -1
- package/types/lib/ecosystems/scalasem.d.ts +58 -16
- package/types/lib/ecosystems/scalasem.d.ts.map +1 -1
- package/types/lib/ecosystems/vendoredCode.d.ts +26 -0
- package/types/lib/ecosystems/vendoredCode.d.ts.map +1 -1
- package/types/lib/ecosystems/venvProbe.d.ts +40 -0
- package/types/lib/ecosystems/venvProbe.d.ts.map +1 -0
- package/types/lib/evinser/evinser.d.ts +120 -13
- package/types/lib/evinser/evinser.d.ts.map +1 -1
- package/types/lib/evinser/scalasem.d.ts.map +1 -1
- package/types/lib/helpers/agenticToolutils.d.ts +53 -19
- package/types/lib/helpers/agenticToolutils.d.ts.map +1 -1
- package/types/lib/helpers/bomSigner.d.ts +20 -3
- package/types/lib/helpers/bomSigner.d.ts.map +1 -1
- package/types/lib/helpers/jssSigner.d.ts +288 -0
- package/types/lib/helpers/jssSigner.d.ts.map +1 -0
- package/types/lib/helpers/vsixutils.d.ts +303 -19
- package/types/lib/helpers/vsixutils.d.ts.map +1 -1
- package/types/lib/inventory/agentBlueprint.d.ts +70 -0
- package/types/lib/inventory/agentBlueprint.d.ts.map +1 -0
- package/types/lib/inventory/agentToolNames.d.ts +51 -0
- package/types/lib/inventory/agentToolNames.d.ts.map +1 -0
- package/types/lib/inventory/aiCollector.d.ts.map +1 -1
- package/types/lib/inventory/aiInventory.d.ts.map +1 -1
- package/types/lib/inventory/aiProviders.d.ts +85 -0
- package/types/lib/inventory/aiProviders.d.ts.map +1 -0
- package/types/lib/inventory/atomUtils.d.ts +19 -0
- package/types/lib/inventory/atomUtils.d.ts.map +1 -1
- package/types/lib/inventory/bomUtils.d.ts.map +1 -1
- package/types/lib/inventory/brotliDecoder.d.ts +58 -0
- package/types/lib/inventory/brotliDecoder.d.ts.map +1 -0
- package/types/lib/inventory/cbomutils.d.ts +17 -0
- package/types/lib/inventory/cbomutils.d.ts.map +1 -1
- package/types/lib/inventory/ciParsers/githubActionsLock.d.ts +101 -0
- package/types/lib/inventory/ciParsers/githubActionsLock.d.ts.map +1 -0
- package/types/lib/inventory/citations.d.ts +5 -0
- package/types/lib/inventory/citations.d.ts.map +1 -1
- package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -1
- package/types/lib/inventory/cyclonedx20.d.ts +99 -0
- package/types/lib/inventory/cyclonedx20.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Common.d.ts +102 -0
- package/types/lib/inventory/cyclonedx20Common.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Derived.d.ts +74 -0
- package/types/lib/inventory/cyclonedx20Derived.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Parties.d.ts +91 -0
- package/types/lib/inventory/cyclonedx20Parties.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Read.d.ts +51 -0
- package/types/lib/inventory/cyclonedx20Read.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadCommon.d.ts +69 -0
- package/types/lib/inventory/cyclonedx20ReadCommon.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadComponents.d.ts +77 -0
- package/types/lib/inventory/cyclonedx20ReadComponents.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadContext.d.ts +118 -0
- package/types/lib/inventory/cyclonedx20ReadContext.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadEvidence.d.ts +40 -0
- package/types/lib/inventory/cyclonedx20ReadEvidence.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadSections.d.ts +45 -0
- package/types/lib/inventory/cyclonedx20ReadSections.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Render.d.ts +53 -0
- package/types/lib/inventory/cyclonedx20Render.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderComponents.d.ts +73 -0
- package/types/lib/inventory/cyclonedx20RenderComponents.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderDefinitions.d.ts +29 -0
- package/types/lib/inventory/cyclonedx20RenderDefinitions.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderEvidence.d.ts +110 -0
- package/types/lib/inventory/cyclonedx20RenderEvidence.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderHardware.d.ts +42 -0
- package/types/lib/inventory/cyclonedx20RenderHardware.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderPatents.d.ts +26 -0
- package/types/lib/inventory/cyclonedx20RenderPatents.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderRefIds.d.ts +55 -0
- package/types/lib/inventory/cyclonedx20RenderRefIds.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderSections.d.ts +45 -0
- package/types/lib/inventory/cyclonedx20RenderSections.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Tables.d.ts +134 -0
- package/types/lib/inventory/cyclonedx20Tables.d.ts.map +1 -0
- package/types/lib/inventory/deps.d.ts +35 -2
- package/types/lib/inventory/deps.d.ts.map +1 -1
- package/types/lib/inventory/dosai.d.ts +36 -1
- package/types/lib/inventory/dosai.d.ts.map +1 -1
- package/types/lib/inventory/dosaiParsers.d.ts.map +1 -1
- package/types/lib/inventory/dotnetRuntime.d.ts +91 -0
- package/types/lib/inventory/dotnetRuntime.d.ts.map +1 -0
- package/types/lib/inventory/ecosystemFormulationParsers.d.ts +73 -0
- package/types/lib/inventory/ecosystemFormulationParsers.d.ts.map +1 -0
- package/types/lib/inventory/envcontext.d.ts +74 -12
- package/types/lib/inventory/envcontext.d.ts.map +1 -1
- package/types/lib/inventory/evidenceUtils.d.ts.map +1 -1
- package/types/lib/inventory/formulationParsers.d.ts.map +1 -1
- package/types/lib/inventory/gtfobins.d.ts.map +1 -1
- package/types/lib/inventory/hbom.d.ts +11 -0
- package/types/lib/inventory/hbom.d.ts.map +1 -1
- package/types/lib/inventory/hbomLoader.d.ts +54 -0
- package/types/lib/inventory/hbomLoader.d.ts.map +1 -1
- package/types/lib/inventory/hostRuntimeProbe.d.ts +44 -0
- package/types/lib/inventory/hostRuntimeProbe.d.ts.map +1 -0
- package/types/lib/inventory/jvmLocalRepos.d.ts +5 -1
- package/types/lib/inventory/jvmLocalRepos.d.ts.map +1 -1
- package/types/lib/inventory/jvmToolEnv.d.ts +12 -0
- package/types/lib/inventory/jvmToolEnv.d.ts.map +1 -1
- package/types/lib/inventory/licenseEnhancer.d.ts.map +1 -1
- package/types/lib/inventory/mavenCentralMirror.d.ts +170 -0
- package/types/lib/inventory/mavenCentralMirror.d.ts.map +1 -0
- package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -1
- package/types/lib/inventory/nodeBuildInfo.d.ts +95 -0
- package/types/lib/inventory/nodeBuildInfo.d.ts.map +1 -0
- package/types/lib/inventory/nodeHostProbe.d.ts +15 -0
- package/types/lib/inventory/nodeHostProbe.d.ts.map +1 -0
- package/types/lib/inventory/occurrenceKey.d.ts +52 -0
- package/types/lib/inventory/occurrenceKey.d.ts.map +1 -0
- package/types/lib/inventory/osPackageResolver.d.ts +38 -0
- package/types/lib/inventory/osPackageResolver.d.ts.map +1 -1
- package/types/lib/inventory/phpBuildInfo.d.ts.map +1 -1
- package/types/lib/inventory/phpHostProbe.d.ts.map +1 -1
- package/types/lib/inventory/pqcMigration.d.ts +84 -0
- package/types/lib/inventory/pqcMigration.d.ts.map +1 -0
- package/types/lib/inventory/rubyBuildInfo.d.ts +271 -0
- package/types/lib/inventory/rubyBuildInfo.d.ts.map +1 -0
- package/types/lib/inventory/rubyHostProbe.d.ts +47 -0
- package/types/lib/inventory/rubyHostProbe.d.ts.map +1 -0
- package/types/lib/inventory/rustFormulationParser.d.ts +7 -2
- package/types/lib/inventory/rustFormulationParser.d.ts.map +1 -1
- package/types/lib/inventory/scalaCoords.d.ts.map +1 -1
- package/types/lib/inventory/scalaDedupe.d.ts +43 -0
- package/types/lib/inventory/scalaDedupe.d.ts.map +1 -0
- package/types/lib/inventory/source.d.ts +25 -0
- package/types/lib/inventory/source.d.ts.map +1 -1
- package/types/lib/managers/binary.d.ts.map +1 -1
- package/types/lib/managers/docker.d.ts +12 -0
- package/types/lib/managers/docker.d.ts.map +1 -1
- package/types/lib/parsers/huggingfaceManifest.d.ts +10 -1
- package/types/lib/parsers/huggingfaceManifest.d.ts.map +1 -1
- package/types/lib/parsers/huggingfaceUtils.d.ts +12 -0
- package/types/lib/parsers/huggingfaceUtils.d.ts.map +1 -1
- package/types/lib/parsers/kiroPermissions.d.ts +62 -0
- package/types/lib/parsers/kiroPermissions.d.ts.map +1 -0
- package/types/lib/parsers/largeJson.d.ts +4 -3
- package/types/lib/parsers/largeJson.d.ts.map +1 -1
- package/types/lib/parsers/vscodeExtensionId.d.ts +48 -0
- package/types/lib/parsers/vscodeExtensionId.d.ts.map +1 -0
- package/types/lib/server/server.d.ts.map +1 -1
- package/types/lib/stages/postgen/postgen.d.ts +7 -0
- package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
- package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -1
- package/types/lib/stages/postgen/specVersionCompat.d.ts +25 -0
- package/types/lib/stages/postgen/specVersionCompat.d.ts.map +1 -1
- package/types/lib/stages/pregen/envAudit.d.ts.map +1 -1
- package/types/lib/stages/pregen/pregen.d.ts +12 -8
- package/types/lib/stages/pregen/pregen.d.ts.map +1 -1
- package/types/lib/validator/bomValidator.d.ts +5 -1
- package/types/lib/validator/bomValidator.d.ts.map +1 -1
- package/types/lib/validator/complianceEngine.d.ts +4 -4
- package/types/lib/validator/complianceEngine.d.ts.map +1 -1
- package/types/lib/validator/complianceRules.d.ts +14 -2
- package/types/lib/validator/complianceRules.d.ts.map +1 -1
- package/types/lib/validator/index.d.ts +10 -0
- package/types/lib/validator/index.d.ts.map +1 -1
- package/types/lib/validator/reporters/json.d.ts.map +1 -1
|
@@ -1,14 +1,22 @@
|
|
|
1
|
-
import { readdirSync,
|
|
1
|
+
import { readdirSync, realpathSync } from "node:fs";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
|
-
import { join } from "node:path";
|
|
3
|
+
import { basename, dirname, isAbsolute, join } from "node:path";
|
|
4
4
|
|
|
5
5
|
import { build } from "@cdxgen/cdx-purl";
|
|
6
6
|
import { parse as loadYaml } from "yaml";
|
|
7
7
|
|
|
8
8
|
import { DEBUG_MODE, readEnvironmentVariable } from "../core/activity.js";
|
|
9
|
+
import { readUserFileText } from "../core/boundedFile.js";
|
|
9
10
|
import { safeExistsSync } from "../core/fs.js";
|
|
10
|
-
import { isMac, isWin } from "../core/paths.js";
|
|
11
|
+
import { isMac, isWin, redactHomePath } from "../core/paths.js";
|
|
11
12
|
import { parseToml } from "../core/toml.js";
|
|
13
|
+
import {
|
|
14
|
+
kiroPermissionSummaryEntries,
|
|
15
|
+
summarizeKiroPermissions,
|
|
16
|
+
} from "../parsers/kiroPermissions.js";
|
|
17
|
+
import { findIdeProductInfo, IDE_PRODUCTS } from "./vsixutils.js";
|
|
18
|
+
|
|
19
|
+
export { redactHomePath };
|
|
12
20
|
|
|
13
21
|
/**
|
|
14
22
|
* The purl type used for installed agentic CLI tools. These tools ship as
|
|
@@ -45,29 +53,6 @@ function buildGenericPurl(name, version) {
|
|
|
45
53
|
}
|
|
46
54
|
}
|
|
47
55
|
|
|
48
|
-
/**
|
|
49
|
-
* Rewrite an absolute path under the user's home directory to a `~`-relative
|
|
50
|
-
* form so the emitted BOM does not carry the local username.
|
|
51
|
-
*
|
|
52
|
-
* @param {string} filePath Absolute path
|
|
53
|
-
* @returns {string} Home-relative path when applicable, else the input
|
|
54
|
-
*/
|
|
55
|
-
export function redactHomePath(filePath) {
|
|
56
|
-
const home = homedir();
|
|
57
|
-
const value = String(filePath || "");
|
|
58
|
-
if (!home || !value.startsWith(home)) {
|
|
59
|
-
return value;
|
|
60
|
-
}
|
|
61
|
-
// Require a path boundary so a sibling home such as /Users/alice-backup is
|
|
62
|
-
// not rewritten as if it sat under /Users/alice.
|
|
63
|
-
const remainder = value.slice(home.length);
|
|
64
|
-
if (remainder && !/^[/\\]/u.test(remainder)) {
|
|
65
|
-
return value;
|
|
66
|
-
}
|
|
67
|
-
const rest = remainder.replace(/^[/\\]/u, "");
|
|
68
|
-
return rest ? `~/${rest.replaceAll("\\", "/")}` : "~";
|
|
69
|
-
}
|
|
70
|
-
|
|
71
56
|
// Directory or file names inside a tool home that must never be read for their
|
|
72
57
|
// values. They hold credentials, transcripts, or telemetry. The scanner may
|
|
73
58
|
// count entries under some of these, but it does not open their contents.
|
|
@@ -95,23 +80,40 @@ const SENSITIVE_ENTRY_NAMES = new Set([
|
|
|
95
80
|
* extension locations). Only the current platform's directories plus
|
|
96
81
|
* always-present dot-directories are included.
|
|
97
82
|
*
|
|
98
|
-
*
|
|
83
|
+
* An entry may also name `mcpConfigs`, the files and keys where the tool
|
|
84
|
+
* lists its MCP servers, and `ide`, the IDE_PRODUCTS id of the editor the tool
|
|
85
|
+
* ships in, whose installed version and extensions folder it then reports.
|
|
86
|
+
*
|
|
87
|
+
* @param {string} [home] Home directory to resolve the folders against
|
|
88
|
+
* @returns {Array<{tool: string, name: string, dirs: string[], supportDirs?: string[], mcpConfigs?: Array<{file: string, key: string}>, ide?: string}>}
|
|
99
89
|
* One entry per known agentic CLI tool.
|
|
100
90
|
*/
|
|
101
|
-
export function getAgenticToolDirs() {
|
|
102
|
-
|
|
91
|
+
export function getAgenticToolDirs(home = homedir()) {
|
|
92
|
+
// These variables describe the current user, so another home, such as a
|
|
93
|
+
// fixture or another user's home, uses the defaults.
|
|
94
|
+
const ownHome = home === homedir();
|
|
103
95
|
const appData =
|
|
104
|
-
readEnvironmentVariable("APPDATA") ||
|
|
96
|
+
(ownHome && readEnvironmentVariable("APPDATA")) ||
|
|
97
|
+
join(home, "AppData", "Roaming");
|
|
105
98
|
const xdgConfigHome =
|
|
106
|
-
readEnvironmentVariable("XDG_CONFIG_HOME") ||
|
|
99
|
+
(ownHome && readEnvironmentVariable("XDG_CONFIG_HOME")) ||
|
|
100
|
+
join(home, ".config");
|
|
107
101
|
const xdgDataHome =
|
|
108
|
-
readEnvironmentVariable("XDG_DATA_HOME") ||
|
|
102
|
+
(ownHome && readEnvironmentVariable("XDG_DATA_HOME")) ||
|
|
103
|
+
join(home, ".local", "share");
|
|
109
104
|
|
|
110
105
|
return [
|
|
111
106
|
{
|
|
112
107
|
tool: "kiro-cli",
|
|
113
108
|
name: "Kiro CLI",
|
|
114
|
-
|
|
109
|
+
// The Kiro editor also creates ~/.kiro, so the CLI is recognised by the
|
|
110
|
+
// files only the CLI writes there.
|
|
111
|
+
dirs: [
|
|
112
|
+
join(home, ".kiro", "settings", "cli.json"),
|
|
113
|
+
join(home, ".kiro", "sessions", "cli"),
|
|
114
|
+
],
|
|
115
|
+
homeDir: join(home, ".kiro"),
|
|
116
|
+
mcpConfigs: [{ file: join("settings", "mcp.json"), key: "mcpServers" }],
|
|
115
117
|
supportDirs: isWin
|
|
116
118
|
? [join(appData, "kiro-cli")]
|
|
117
119
|
: isMac
|
|
@@ -136,6 +138,8 @@ export function getAgenticToolDirs() {
|
|
|
136
138
|
tool: "claude-code",
|
|
137
139
|
name: "Claude Code",
|
|
138
140
|
dirs: [join(home, ".claude")],
|
|
141
|
+
// User-scope MCP servers live in ~/.claude.json, beside the folder.
|
|
142
|
+
mcpConfigs: [{ file: join(home, ".claude.json"), key: "mcpServers" }],
|
|
139
143
|
},
|
|
140
144
|
{
|
|
141
145
|
tool: "codex",
|
|
@@ -161,11 +165,111 @@ export function getAgenticToolDirs() {
|
|
|
161
165
|
tool: "cursor",
|
|
162
166
|
name: "Cursor",
|
|
163
167
|
dirs: [join(home, ".cursor")],
|
|
168
|
+
mcpConfigs: [{ file: "mcp.json", key: "mcpServers" }],
|
|
169
|
+
ide: "cursor",
|
|
164
170
|
},
|
|
165
171
|
{
|
|
166
172
|
tool: "windsurf",
|
|
167
173
|
name: "Windsurf",
|
|
168
174
|
dirs: [join(home, ".codeium", "windsurf")],
|
|
175
|
+
mcpConfigs: [{ file: "mcp_config.json", key: "mcpServers" }],
|
|
176
|
+
ide: "windsurf",
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
tool: "devin-desktop",
|
|
180
|
+
name: "Devin Desktop",
|
|
181
|
+
dirs: [join(home, ".devin")],
|
|
182
|
+
mcpConfigs: [
|
|
183
|
+
{
|
|
184
|
+
file: join(xdgConfigHome, "devin", "config.json"),
|
|
185
|
+
key: "mcpServers",
|
|
186
|
+
},
|
|
187
|
+
],
|
|
188
|
+
ide: "devin-desktop",
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
tool: "kiro",
|
|
192
|
+
name: "Kiro",
|
|
193
|
+
// Kiro and Kiro CLI share ~/.kiro; the IDE is told apart by its
|
|
194
|
+
// extensions folder.
|
|
195
|
+
dirs: [join(home, ".kiro", "extensions")],
|
|
196
|
+
homeDir: join(home, ".kiro"),
|
|
197
|
+
mcpConfigs: [{ file: join("settings", "mcp.json"), key: "mcpServers" }],
|
|
198
|
+
ide: "kiro",
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
tool: "trae",
|
|
202
|
+
name: "Trae",
|
|
203
|
+
dirs: [join(home, ".trae")],
|
|
204
|
+
ide: "trae",
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
tool: "antigravity",
|
|
208
|
+
name: "Antigravity",
|
|
209
|
+
dirs: [join(home, ".antigravity")],
|
|
210
|
+
ide: "antigravity",
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
tool: "antigravity-ide",
|
|
214
|
+
name: "Antigravity IDE",
|
|
215
|
+
dirs: [join(home, ".antigravity-ide")],
|
|
216
|
+
ide: "antigravity-ide",
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
tool: "qoder",
|
|
220
|
+
name: "Qoder",
|
|
221
|
+
dirs: [join(home, ".qoder")],
|
|
222
|
+
ide: "qoder",
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
tool: "void",
|
|
226
|
+
name: "Void",
|
|
227
|
+
dirs: [join(home, ".void-editor")],
|
|
228
|
+
ide: "void",
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
tool: "qwen-code",
|
|
232
|
+
name: "Qwen Code",
|
|
233
|
+
dirs: [join(home, ".qwen")],
|
|
234
|
+
mcpConfigs: [{ file: "settings.json", key: "mcpServers" }],
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
tool: "factory-droid",
|
|
238
|
+
name: "Factory Droid",
|
|
239
|
+
dirs: [join(home, ".factory")],
|
|
240
|
+
mcpConfigs: [{ file: "mcp.json", key: "mcpServers" }],
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
tool: "auggie",
|
|
244
|
+
name: "Augment Auggie CLI",
|
|
245
|
+
dirs: [join(home, ".augment")],
|
|
246
|
+
mcpConfigs: [{ file: "settings.json", key: "mcpServers" }],
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
tool: "continue",
|
|
250
|
+
name: "Continue",
|
|
251
|
+
dirs: [join(home, ".continue")],
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
tool: "cline-cli",
|
|
255
|
+
name: "Cline CLI",
|
|
256
|
+
dirs: [join(home, ".cline")],
|
|
257
|
+
mcpConfigs: [
|
|
258
|
+
{
|
|
259
|
+
file: join("data", "settings", "cline_mcp_settings.json"),
|
|
260
|
+
key: "mcpServers",
|
|
261
|
+
},
|
|
262
|
+
],
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
tool: "claude-desktop",
|
|
266
|
+
name: "Claude Desktop",
|
|
267
|
+
dirs: isWin
|
|
268
|
+
? [join(appData, "Claude")]
|
|
269
|
+
: isMac
|
|
270
|
+
? [join(home, "Library", "Application Support", "Claude")]
|
|
271
|
+
: [join(xdgConfigHome, "Claude")],
|
|
272
|
+
mcpConfigs: [{ file: "claude_desktop_config.json", key: "mcpServers" }],
|
|
169
273
|
},
|
|
170
274
|
{
|
|
171
275
|
tool: "goose",
|
|
@@ -184,11 +288,16 @@ export function getAgenticToolDirs() {
|
|
|
184
288
|
join(home, ".config", "amp"),
|
|
185
289
|
...(isWin ? [join(appData, "amp")] : []),
|
|
186
290
|
],
|
|
291
|
+
mcpConfigs: [
|
|
292
|
+
{ file: "settings.json", key: "amp.mcpServers" },
|
|
293
|
+
{ file: "settings.jsonc", key: "amp.mcpServers" },
|
|
294
|
+
],
|
|
187
295
|
},
|
|
188
296
|
{
|
|
189
297
|
tool: "copilot-cli",
|
|
190
298
|
name: "GitHub Copilot CLI",
|
|
191
299
|
dirs: [join(home, ".copilot-cli"), join(home, ".copilot")],
|
|
300
|
+
mcpConfigs: [{ file: "mcp-config.json", key: "mcpServers" }],
|
|
192
301
|
},
|
|
193
302
|
{
|
|
194
303
|
tool: "crush",
|
|
@@ -206,27 +315,74 @@ export function getAgenticToolDirs() {
|
|
|
206
315
|
* Discover which agentic CLI tools are installed for the current user by
|
|
207
316
|
* checking their known home directories.
|
|
208
317
|
*
|
|
209
|
-
* @
|
|
318
|
+
* @param {string} [home] Home directory to resolve the folders against
|
|
319
|
+
* @returns {Array<{tool: string, name: string, dir: string, supportDir?: string, mcpConfigs?: Object[], ide?: string}>}
|
|
210
320
|
* One entry per discovered tool, using the first existing directory.
|
|
211
321
|
*/
|
|
212
|
-
export function discoverAgenticTools() {
|
|
322
|
+
export function discoverAgenticTools(home = homedir()) {
|
|
213
323
|
const found = [];
|
|
214
|
-
for (const entry of getAgenticToolDirs()) {
|
|
215
|
-
const
|
|
216
|
-
if (!
|
|
324
|
+
for (const entry of getAgenticToolDirs(home)) {
|
|
325
|
+
const marker = entry.dirs.find((candidate) => safeExistsSync(candidate));
|
|
326
|
+
if (!marker) {
|
|
217
327
|
continue;
|
|
218
328
|
}
|
|
219
329
|
const supportDir = (entry.supportDirs || []).find((candidate) =>
|
|
220
330
|
safeExistsSync(candidate),
|
|
221
331
|
);
|
|
222
|
-
found.push({
|
|
332
|
+
found.push({
|
|
333
|
+
tool: entry.tool,
|
|
334
|
+
name: entry.name,
|
|
335
|
+
dir: entry.homeDir || marker,
|
|
336
|
+
supportDir,
|
|
337
|
+
mcpConfigs: entry.mcpConfigs,
|
|
338
|
+
ide: entry.ide,
|
|
339
|
+
});
|
|
223
340
|
}
|
|
224
341
|
return found;
|
|
225
342
|
}
|
|
226
343
|
|
|
344
|
+
// Largest tool configuration file read. ~/.claude.json keeps per-project state
|
|
345
|
+
// and grows with use, so the cap is generous; it only has to stop a FIFO, a
|
|
346
|
+
// device or a runaway file from stalling the scan or exhausting memory.
|
|
347
|
+
const MAX_CONFIG_FILE_BYTES = 64 * 1024 * 1024;
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Read a tool configuration file only when it is a regular file of bounded
|
|
351
|
+
* size. A FIFO or a device reads as undefined, and so does a symlink when the
|
|
352
|
+
* scan runs as root.
|
|
353
|
+
*
|
|
354
|
+
* @param {string} filePath Absolute path
|
|
355
|
+
* @returns {string|undefined} File text, or undefined
|
|
356
|
+
*/
|
|
357
|
+
function readConfigText(filePath) {
|
|
358
|
+
return readUserFileText(filePath, MAX_CONFIG_FILE_BYTES);
|
|
359
|
+
}
|
|
360
|
+
|
|
227
361
|
function parseJsonFile(filePath) {
|
|
228
362
|
try {
|
|
229
|
-
return parseJsonLikeText(
|
|
363
|
+
return parseJsonLikeText(readConfigText(filePath));
|
|
364
|
+
} catch {
|
|
365
|
+
return undefined;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Read a small YAML settings file, such as a Kiro permissions document,
|
|
371
|
+
* through the bounded user-file reader. A file that exists but holds no
|
|
372
|
+
* document, such as an empty or comment-only permissions file, reads as an
|
|
373
|
+
* empty object so its presence still counts.
|
|
374
|
+
*
|
|
375
|
+
* @param {string} filePath Absolute file path
|
|
376
|
+
* @returns {Object|undefined} Parsed document, or undefined when the file is
|
|
377
|
+
* missing, unreadable, or malformed
|
|
378
|
+
*/
|
|
379
|
+
function parseYamlFile(filePath) {
|
|
380
|
+
try {
|
|
381
|
+
const raw = readConfigText(filePath);
|
|
382
|
+
if (typeof raw !== "string") {
|
|
383
|
+
return undefined;
|
|
384
|
+
}
|
|
385
|
+
return loadYaml(raw) || {};
|
|
230
386
|
} catch {
|
|
231
387
|
return undefined;
|
|
232
388
|
}
|
|
@@ -335,7 +491,52 @@ function countDirEntries(dirPath, filterFn) {
|
|
|
335
491
|
* @param {string} [supportDir] Optional platform support directory
|
|
336
492
|
* @returns {string|undefined} Version string when found
|
|
337
493
|
*/
|
|
494
|
+
/**
|
|
495
|
+
* Read a semver-like version from the start of a release folder name such as
|
|
496
|
+
* `2.1.278` or `0.137.0-aarch64-apple-darwin`.
|
|
497
|
+
*
|
|
498
|
+
* @param {string} name Folder name
|
|
499
|
+
* @returns {string|undefined} The version, or undefined
|
|
500
|
+
*/
|
|
501
|
+
function versionFromReleaseName(name) {
|
|
502
|
+
const match = /^v?(\d+\.\d+\.\d+)/u.exec(`${name || ""}`);
|
|
503
|
+
return match ? match[1] : undefined;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Follow a launcher symlink that points into a per-version folder, as the
|
|
508
|
+
* native Claude Code and Codex installers do, and read the version from the
|
|
509
|
+
* folder name.
|
|
510
|
+
*
|
|
511
|
+
* @param {string} linkPath Launcher or `current` symlink
|
|
512
|
+
* @returns {string|undefined} The version, or undefined
|
|
513
|
+
*/
|
|
514
|
+
function versionFromReleaseLink(linkPath) {
|
|
515
|
+
try {
|
|
516
|
+
return versionFromReleaseName(basename(realpathSync(linkPath)));
|
|
517
|
+
} catch {
|
|
518
|
+
return undefined;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
338
522
|
function readToolVersion(tool, dir, supportDir) {
|
|
523
|
+
if (tool === "claude-code") {
|
|
524
|
+
const home = dirname(dir);
|
|
525
|
+
const version =
|
|
526
|
+
versionFromReleaseLink(join(home, ".local", "bin", "claude")) ||
|
|
527
|
+
versionFromReleaseLink(join(home, ".claude", "local", "claude"));
|
|
528
|
+
if (version) {
|
|
529
|
+
return version;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
if (tool === "codex") {
|
|
533
|
+
const version = versionFromReleaseLink(
|
|
534
|
+
join(dir, "packages", "standalone", "current"),
|
|
535
|
+
);
|
|
536
|
+
if (version) {
|
|
537
|
+
return version;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
339
540
|
const candidates = [];
|
|
340
541
|
if (tool === "opencode") {
|
|
341
542
|
// ~/.opencode/package.json pins the installed opencode plugin runtime,
|
|
@@ -370,7 +571,7 @@ function readToolVersion(tool, dir, supportDir) {
|
|
|
370
571
|
}
|
|
371
572
|
} else {
|
|
372
573
|
try {
|
|
373
|
-
const raw =
|
|
574
|
+
const raw = (readConfigText(candidate) || "").trim();
|
|
374
575
|
if (/^v?\d+\.\d+/.test(raw)) {
|
|
375
576
|
return raw.replace(/^v/, "");
|
|
376
577
|
}
|
|
@@ -382,6 +583,58 @@ function readToolVersion(tool, dir, supportDir) {
|
|
|
382
583
|
return undefined;
|
|
383
584
|
}
|
|
384
585
|
|
|
586
|
+
/**
|
|
587
|
+
* Collect the workspace-scope permission counts under
|
|
588
|
+
* `~/.kiro/workspace-roots/<hash>/permissions.yaml`. Only counts and booleans
|
|
589
|
+
* are returned; the hash-named directories, the file paths, and the rule
|
|
590
|
+
* match patterns stay out of the result.
|
|
591
|
+
*
|
|
592
|
+
* @param {string} dir Kiro home directory
|
|
593
|
+
* @returns {{workspacePermissionFileCount?: number, trustedWorkspaceCount?: number, workspaceWithAllowRuleCount?: number}}
|
|
594
|
+
* Aggregate workspace posture counts
|
|
595
|
+
*/
|
|
596
|
+
function countKiroWorkspacePermissions(dir) {
|
|
597
|
+
const rootsDir = join(dir, "workspace-roots");
|
|
598
|
+
if (!safeExistsSync(rootsDir)) {
|
|
599
|
+
return {};
|
|
600
|
+
}
|
|
601
|
+
let entries = [];
|
|
602
|
+
try {
|
|
603
|
+
entries = readdirSync(rootsDir, { withFileTypes: true });
|
|
604
|
+
} catch {
|
|
605
|
+
return {};
|
|
606
|
+
}
|
|
607
|
+
let fileCount = 0;
|
|
608
|
+
let trustedCount = 0;
|
|
609
|
+
let withAllowRuleCount = 0;
|
|
610
|
+
for (const entry of entries) {
|
|
611
|
+
if (!entry.isDirectory()) {
|
|
612
|
+
continue;
|
|
613
|
+
}
|
|
614
|
+
const permissionsPath = join(rootsDir, entry.name, "permissions.yaml");
|
|
615
|
+
const doc = parseYamlFile(permissionsPath);
|
|
616
|
+
if (doc === undefined) {
|
|
617
|
+
continue;
|
|
618
|
+
}
|
|
619
|
+
fileCount += 1;
|
|
620
|
+
const summary = summarizeKiroPermissions(doc);
|
|
621
|
+
if (summary.workspaceTrusted === true) {
|
|
622
|
+
trustedCount += 1;
|
|
623
|
+
}
|
|
624
|
+
if (summary.allowRuleCount > 0) {
|
|
625
|
+
withAllowRuleCount += 1;
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
if (!fileCount) {
|
|
629
|
+
return {};
|
|
630
|
+
}
|
|
631
|
+
return {
|
|
632
|
+
trustedWorkspaceCount: trustedCount,
|
|
633
|
+
workspacePermissionFileCount: fileCount,
|
|
634
|
+
workspaceWithAllowRuleCount: withAllowRuleCount,
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
|
|
385
638
|
function countKiroSignals(dir, supportDir) {
|
|
386
639
|
const signals = {};
|
|
387
640
|
const agentsDir = join(dir, "agents");
|
|
@@ -404,6 +657,17 @@ function countKiroSignals(dir, supportDir) {
|
|
|
404
657
|
if (settings && typeof settings["chat.defaultAgent"] === "string") {
|
|
405
658
|
signals.defaultAgent = settings["chat.defaultAgent"];
|
|
406
659
|
}
|
|
660
|
+
// The V3 user-scope permission posture from ~/.kiro/settings/permissions.yaml.
|
|
661
|
+
const userPermissions = parseYamlFile(
|
|
662
|
+
join(dir, "settings", "permissions.yaml"),
|
|
663
|
+
);
|
|
664
|
+
if (userPermissions !== undefined) {
|
|
665
|
+
Object.assign(
|
|
666
|
+
signals,
|
|
667
|
+
kiroPermissionSummaryEntries(summarizeKiroPermissions(userPermissions)),
|
|
668
|
+
);
|
|
669
|
+
}
|
|
670
|
+
Object.assign(signals, countKiroWorkspacePermissions(dir));
|
|
407
671
|
return signals;
|
|
408
672
|
}
|
|
409
673
|
|
|
@@ -476,7 +740,7 @@ function countCodexSignals(dir) {
|
|
|
476
740
|
return signals;
|
|
477
741
|
}
|
|
478
742
|
try {
|
|
479
|
-
const config = parseToml(
|
|
743
|
+
const config = parseToml(readConfigText(configPath) || "");
|
|
480
744
|
if (config?.mcp_servers && typeof config.mcp_servers === "object") {
|
|
481
745
|
signals.mcpServerCount = Object.keys(config.mcp_servers).length;
|
|
482
746
|
}
|
|
@@ -488,24 +752,35 @@ function countCodexSignals(dir) {
|
|
|
488
752
|
|
|
489
753
|
function countCursorSignals(dir) {
|
|
490
754
|
const signals = {};
|
|
491
|
-
const mcpConfig = parseJsonFile(join(dir, "mcp.json"));
|
|
492
|
-
if (mcpConfig?.mcpServers && typeof mcpConfig.mcpServers === "object") {
|
|
493
|
-
signals.mcpServerCount = Object.keys(mcpConfig.mcpServers).length;
|
|
494
|
-
}
|
|
495
755
|
const agentsDir = join(dir, "agents");
|
|
496
756
|
if (safeExistsSync(agentsDir)) {
|
|
497
757
|
signals.agentCount = countDirEntries(agentsDir, (name) =>
|
|
498
758
|
name.endsWith(".md"),
|
|
499
759
|
);
|
|
500
760
|
}
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
761
|
+
const rulesDir = join(dir, "rules");
|
|
762
|
+
if (safeExistsSync(rulesDir)) {
|
|
763
|
+
signals.ruleCount = countDirEntries(rulesDir, (name) =>
|
|
764
|
+
/\.(md|mdc)$/u.test(name),
|
|
765
|
+
);
|
|
766
|
+
}
|
|
767
|
+
for (const [skillsDir, key] of [
|
|
768
|
+
[join(dir, "skills"), "skillCount"],
|
|
769
|
+
[join(dir, "skills-cursor"), "bundledSkillCount"],
|
|
770
|
+
]) {
|
|
771
|
+
if (safeExistsSync(skillsDir)) {
|
|
772
|
+
signals[key] = countDirEntries(skillsDir);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
// The Cursor CLI keeps its tool permissions in cli-config.json. Only the
|
|
776
|
+
// number of rules is recorded, not the commands or paths they name.
|
|
777
|
+
const cliConfig = parseJsonFile(join(dir, "cli-config.json"));
|
|
778
|
+
const permissions = cliConfig?.permissions;
|
|
779
|
+
if (Array.isArray(permissions?.allow)) {
|
|
780
|
+
signals.cliAllowRuleCount = permissions.allow.length;
|
|
781
|
+
}
|
|
782
|
+
if (Array.isArray(permissions?.deny)) {
|
|
783
|
+
signals.cliDenyRuleCount = permissions.deny.length;
|
|
509
784
|
}
|
|
510
785
|
return signals;
|
|
511
786
|
}
|
|
@@ -514,7 +789,7 @@ function countGooseSignals(dir) {
|
|
|
514
789
|
const signals = {};
|
|
515
790
|
// Goose keeps its resolved extension set in config.yaml.
|
|
516
791
|
try {
|
|
517
|
-
const config = loadYaml(
|
|
792
|
+
const config = loadYaml(readConfigText(join(dir, "config.yaml")) || "");
|
|
518
793
|
if (Array.isArray(config?.extensions)) {
|
|
519
794
|
signals.extensionCount = config.extensions.length;
|
|
520
795
|
}
|
|
@@ -546,6 +821,81 @@ function countGeminiSignals(dir) {
|
|
|
546
821
|
return signals;
|
|
547
822
|
}
|
|
548
823
|
|
|
824
|
+
function countClaudeDesktopSignals(dir) {
|
|
825
|
+
const signals = {};
|
|
826
|
+
// Desktop extensions (.mcpb/.dxt) each bundle an MCP server.
|
|
827
|
+
const extensionsDir = join(dir, "Claude Extensions");
|
|
828
|
+
if (safeExistsSync(extensionsDir)) {
|
|
829
|
+
signals.extensionCount = countDirEntries(extensionsDir);
|
|
830
|
+
}
|
|
831
|
+
return signals;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
/**
|
|
835
|
+
* Count the MCP servers a tool lists across its configuration files. A server
|
|
836
|
+
* named in two files is counted once.
|
|
837
|
+
*
|
|
838
|
+
* @param {string} dir Tool home directory, which relative files resolve against
|
|
839
|
+
* @param {Array<{file: string, key: string}>} [mcpConfigs] Files and the key
|
|
840
|
+
* holding the server map. A key is looked up as written first, so a dotted
|
|
841
|
+
* key such as `amp.mcpServers` matches a literal property.
|
|
842
|
+
* @returns {number|undefined} Number of servers, or undefined when no file
|
|
843
|
+
* defines any
|
|
844
|
+
*/
|
|
845
|
+
export function countConfiguredMcpServers(dir, mcpConfigs) {
|
|
846
|
+
const names = new Set();
|
|
847
|
+
let sawConfig = false;
|
|
848
|
+
for (const { file, key } of mcpConfigs || []) {
|
|
849
|
+
const config = parseJsonFile(isAbsolute(file) ? file : join(dir, file));
|
|
850
|
+
if (!config || typeof config !== "object") {
|
|
851
|
+
continue;
|
|
852
|
+
}
|
|
853
|
+
let servers = config[key];
|
|
854
|
+
if (servers === undefined && key.includes(".")) {
|
|
855
|
+
servers = key.split(".").reduce((value, part) => value?.[part], config);
|
|
856
|
+
}
|
|
857
|
+
if (servers && typeof servers === "object" && !Array.isArray(servers)) {
|
|
858
|
+
sawConfig = true;
|
|
859
|
+
for (const name of Object.keys(servers)) {
|
|
860
|
+
names.add(name);
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
return sawConfig ? names.size : undefined;
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
/**
|
|
868
|
+
* Describe the editor an agentic tool ships in: its installed version and
|
|
869
|
+
* how many extensions are in its extensions folder.
|
|
870
|
+
*
|
|
871
|
+
* @param {string} ideId Entry id from IDE_PRODUCTS
|
|
872
|
+
* @param {string} home Home directory
|
|
873
|
+
* @returns {{version?: string, installDir?: string, extensionCount?: number}}
|
|
874
|
+
* What could be read
|
|
875
|
+
*/
|
|
876
|
+
function describeAgenticIde(ideId, home) {
|
|
877
|
+
const product = IDE_PRODUCTS.find((p) => p.id === ideId);
|
|
878
|
+
if (!product) {
|
|
879
|
+
return {};
|
|
880
|
+
}
|
|
881
|
+
const info = findIdeProductInfo({ id: ideId, kind: "desktop" }, home);
|
|
882
|
+
const result = {};
|
|
883
|
+
if (info?.version) {
|
|
884
|
+
result.version = info.version;
|
|
885
|
+
}
|
|
886
|
+
if (info?.appDir) {
|
|
887
|
+
result.installDir = info.appDir;
|
|
888
|
+
}
|
|
889
|
+
const extensionsDir = join(home, product.dataFolderName, "extensions");
|
|
890
|
+
if (safeExistsSync(extensionsDir)) {
|
|
891
|
+
result.extensionCount = countDirEntries(
|
|
892
|
+
extensionsDir,
|
|
893
|
+
(name) => !name.startsWith(".") && name !== "extensions.json",
|
|
894
|
+
);
|
|
895
|
+
}
|
|
896
|
+
return result;
|
|
897
|
+
}
|
|
898
|
+
|
|
549
899
|
/**
|
|
550
900
|
* Compute safe, redacted signal counts for a discovered tool. Only structural
|
|
551
901
|
* counts and small enumerated values are returned; no credential, transcript,
|
|
@@ -554,9 +904,34 @@ function countGeminiSignals(dir) {
|
|
|
554
904
|
* @param {string} tool Tool key
|
|
555
905
|
* @param {string} dir Discovered tool home directory
|
|
556
906
|
* @param {string} [supportDir] Optional platform support directory
|
|
907
|
+
* @param {Array<{file: string, key: string}>} [mcpConfigs] Files that list
|
|
908
|
+
* the tool's MCP servers, used when the tool has no reader of its own
|
|
909
|
+
* @param {string} [home] Home directory the tool was found in
|
|
557
910
|
* @returns {Object} Map of signal name to count/boolean/small-string value
|
|
558
911
|
*/
|
|
559
|
-
export function collectToolSignals(
|
|
912
|
+
export function collectToolSignals(
|
|
913
|
+
tool,
|
|
914
|
+
dir,
|
|
915
|
+
supportDir,
|
|
916
|
+
mcpConfigs,
|
|
917
|
+
home = homedir(),
|
|
918
|
+
) {
|
|
919
|
+
const signals = toolSpecificSignals(tool, dir, supportDir);
|
|
920
|
+
if (signals.mcpServerCount === undefined) {
|
|
921
|
+
const mcpServerCount = countConfiguredMcpServers(
|
|
922
|
+
dir,
|
|
923
|
+
mcpConfigs ||
|
|
924
|
+
getAgenticToolDirs(home).find((entry) => entry.tool === tool)
|
|
925
|
+
?.mcpConfigs || [{ file: ".mcp.json", key: "mcpServers" }],
|
|
926
|
+
);
|
|
927
|
+
if (mcpServerCount !== undefined) {
|
|
928
|
+
signals.mcpServerCount = mcpServerCount;
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
return signals;
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
function toolSpecificSignals(tool, dir, supportDir) {
|
|
560
935
|
switch (tool) {
|
|
561
936
|
case "kiro-cli":
|
|
562
937
|
return countKiroSignals(dir, supportDir);
|
|
@@ -572,48 +947,60 @@ export function collectToolSignals(tool, dir, supportDir) {
|
|
|
572
947
|
return countGeminiSignals(dir);
|
|
573
948
|
case "cursor":
|
|
574
949
|
return countCursorSignals(dir);
|
|
575
|
-
case "
|
|
576
|
-
return
|
|
950
|
+
case "claude-desktop":
|
|
951
|
+
return countClaudeDesktopSignals(dir);
|
|
577
952
|
case "goose":
|
|
578
953
|
return countGooseSignals(dir);
|
|
579
954
|
case "crush":
|
|
580
955
|
return countCrushSignals(dir);
|
|
581
|
-
default:
|
|
582
|
-
|
|
583
|
-
const signals = {};
|
|
584
|
-
const mcpConfig = parseJsonFile(join(dir, ".mcp.json"));
|
|
585
|
-
if (mcpConfig?.mcpServers) {
|
|
586
|
-
signals.mcpServerCount = Object.keys(mcpConfig.mcpServers).length;
|
|
587
|
-
}
|
|
588
|
-
return signals;
|
|
589
|
-
}
|
|
956
|
+
default:
|
|
957
|
+
return {};
|
|
590
958
|
}
|
|
591
959
|
}
|
|
592
960
|
|
|
593
961
|
/**
|
|
594
962
|
* Build a CycloneDX application component for one discovered agentic tool.
|
|
595
963
|
*
|
|
596
|
-
* @param {{tool: string, name: string, dir: string, supportDir?: string}} entry
|
|
964
|
+
* @param {{tool: string, name: string, dir: string, supportDir?: string, mcpConfigs?: Object[], ide?: string}} entry
|
|
597
965
|
* Discovered tool entry
|
|
966
|
+
* @param {string} [home] Home directory, used to find the tool's editor
|
|
598
967
|
* @returns {Object} CycloneDX component
|
|
599
968
|
*/
|
|
600
|
-
export function componentForAgenticTool(entry) {
|
|
601
|
-
const { tool, name, dir, supportDir } = entry;
|
|
602
|
-
const
|
|
969
|
+
export function componentForAgenticTool(entry, home = homedir()) {
|
|
970
|
+
const { tool, name, dir, supportDir, mcpConfigs, ide } = entry;
|
|
971
|
+
const ideInfo = ide ? describeAgenticIde(ide, home) : {};
|
|
972
|
+
const version = readToolVersion(tool, dir, supportDir) || ideInfo.version;
|
|
603
973
|
const purl = buildGenericPurl(tool, version);
|
|
604
974
|
const properties = [
|
|
605
|
-
{ name: "internal:SrcFile", value: redactHomePath(dir) },
|
|
975
|
+
{ name: "internal:SrcFile", value: redactHomePath(dir, home) },
|
|
606
976
|
{ name: "cdx:agentic:tool", value: tool },
|
|
607
|
-
{ name: "cdx:agentic:home", value: redactHomePath(dir) },
|
|
977
|
+
{ name: "cdx:agentic:home", value: redactHomePath(dir, home) },
|
|
608
978
|
{ name: "cdx:agentic:inventorySource", value: "host-scan" },
|
|
609
979
|
];
|
|
610
980
|
if (supportDir) {
|
|
611
981
|
properties.push({
|
|
612
982
|
name: "cdx:agentic:supportDir",
|
|
613
|
-
value: redactHomePath(supportDir),
|
|
983
|
+
value: redactHomePath(supportDir, home),
|
|
984
|
+
});
|
|
985
|
+
}
|
|
986
|
+
// ~/.cursor or ~/.codeium/windsurf can exist with only a CLI or a plugin
|
|
987
|
+
// installed, so the editor is named only when it was found.
|
|
988
|
+
const ideFound =
|
|
989
|
+
Boolean(ide) &&
|
|
990
|
+
(ideInfo.installDir !== undefined || ideInfo.extensionCount !== undefined);
|
|
991
|
+
if (ideFound) {
|
|
992
|
+
properties.push({ name: "cdx:agentic:ide", value: ide });
|
|
993
|
+
}
|
|
994
|
+
if (ideInfo.installDir) {
|
|
995
|
+
properties.push({
|
|
996
|
+
name: "cdx:agentic:ideInstallDir",
|
|
997
|
+
value: redactHomePath(ideInfo.installDir, home),
|
|
614
998
|
});
|
|
615
999
|
}
|
|
616
|
-
const signals = collectToolSignals(tool, dir, supportDir);
|
|
1000
|
+
const signals = collectToolSignals(tool, dir, supportDir, mcpConfigs, home);
|
|
1001
|
+
if (ideInfo.extensionCount !== undefined) {
|
|
1002
|
+
signals.extensionCount = ideInfo.extensionCount;
|
|
1003
|
+
}
|
|
617
1004
|
for (const [key, value] of Object.entries(signals)) {
|
|
618
1005
|
if (value === undefined || value === null || value === "") {
|
|
619
1006
|
continue;
|
|
@@ -639,7 +1026,12 @@ export function componentForAgenticTool(entry) {
|
|
|
639
1026
|
if (purl) {
|
|
640
1027
|
component.purl = purl;
|
|
641
1028
|
}
|
|
642
|
-
component.description =
|
|
1029
|
+
component.description = ideFound
|
|
1030
|
+
? `${name} AI editor discovered on the host`
|
|
1031
|
+
: `${name} agentic CLI tool discovered on the host`;
|
|
1032
|
+
if (ideFound) {
|
|
1033
|
+
component.tags.push("ai-ide");
|
|
1034
|
+
}
|
|
643
1035
|
return component;
|
|
644
1036
|
}
|
|
645
1037
|
|
|
@@ -652,13 +1044,17 @@ function childBomRef(parentRef, kind, id) {
|
|
|
652
1044
|
* Parse Kiro agent definitions (`~/.kiro/agents/*.json`) into components.
|
|
653
1045
|
*
|
|
654
1046
|
* Each agent contributes its name, model, and redacted counts of MCP servers,
|
|
655
|
-
* tools, and allowed tools
|
|
1047
|
+
* tools, and allowed tools, plus the permission posture of its V3
|
|
1048
|
+
* `permissions` object and the integer `kiroUpgrade` revision. Prompts,
|
|
1049
|
+
* resource values, match patterns, and the upgrade fingerprint or source are
|
|
1050
|
+
* never copied.
|
|
656
1051
|
*
|
|
657
1052
|
* @param {string} dir Kiro home directory
|
|
658
1053
|
* @param {string} parentRef Parent tool bom-ref
|
|
1054
|
+
* @param {string} [home] Home directory the tool was found in, for redaction
|
|
659
1055
|
* @returns {Object[]} Child components
|
|
660
1056
|
*/
|
|
661
|
-
function parseKiroAgents(dir, parentRef) {
|
|
1057
|
+
function parseKiroAgents(dir, parentRef, home = homedir()) {
|
|
662
1058
|
const agentsDir = join(dir, "agents");
|
|
663
1059
|
if (!safeExistsSync(agentsDir)) {
|
|
664
1060
|
return [];
|
|
@@ -681,7 +1077,7 @@ function parseKiroAgents(dir, parentRef) {
|
|
|
681
1077
|
const properties = [
|
|
682
1078
|
{
|
|
683
1079
|
name: "internal:SrcFile",
|
|
684
|
-
value: redactHomePath(join(agentsDir, file)),
|
|
1080
|
+
value: redactHomePath(join(agentsDir, file), home),
|
|
685
1081
|
},
|
|
686
1082
|
{ name: "cdx:agentic:tool", value: "kiro-cli" },
|
|
687
1083
|
{ name: "cdx:agentic:kind", value: "agent-definition" },
|
|
@@ -707,6 +1103,24 @@ function parseKiroAgents(dir, parentRef) {
|
|
|
707
1103
|
value: String(agent.allowedTools.length),
|
|
708
1104
|
});
|
|
709
1105
|
}
|
|
1106
|
+
if (agent.permissions && typeof agent.permissions === "object") {
|
|
1107
|
+
for (const [suffix, value] of Object.entries(
|
|
1108
|
+
kiroPermissionSummaryEntries(
|
|
1109
|
+
summarizeKiroPermissions(agent.permissions),
|
|
1110
|
+
),
|
|
1111
|
+
)) {
|
|
1112
|
+
properties.push({
|
|
1113
|
+
name: `cdx:agentic:${suffix}`,
|
|
1114
|
+
value: String(value),
|
|
1115
|
+
});
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
if (Number.isInteger(agent.kiroUpgrade?.revision)) {
|
|
1119
|
+
properties.push({
|
|
1120
|
+
name: "cdx:agentic:upgradeRevision",
|
|
1121
|
+
value: String(agent.kiroUpgrade.revision),
|
|
1122
|
+
});
|
|
1123
|
+
}
|
|
710
1124
|
components.push({
|
|
711
1125
|
"bom-ref": childBomRef(parentRef, "agent", agent.name),
|
|
712
1126
|
type: "application",
|
|
@@ -725,9 +1139,10 @@ function parseKiroAgents(dir, parentRef) {
|
|
|
725
1139
|
*
|
|
726
1140
|
* @param {string} dir zcode home directory
|
|
727
1141
|
* @param {string} parentRef Parent tool bom-ref
|
|
1142
|
+
* @param {string} [home] Home directory the tool was found in, for redaction
|
|
728
1143
|
* @returns {Object[]} Child components
|
|
729
1144
|
*/
|
|
730
|
-
function parseZcodePlugins(dir, parentRef) {
|
|
1145
|
+
function parseZcodePlugins(dir, parentRef, home = homedir()) {
|
|
731
1146
|
const cacheDir = join(dir, "cli", "plugins", "cache");
|
|
732
1147
|
if (!safeExistsSync(cacheDir)) {
|
|
733
1148
|
return [];
|
|
@@ -763,7 +1178,7 @@ function parseZcodePlugins(dir, parentRef) {
|
|
|
763
1178
|
typeof plugin.version === "string" ? plugin.version : undefined,
|
|
764
1179
|
);
|
|
765
1180
|
const properties = [
|
|
766
|
-
{ name: "internal:SrcFile", value: redactHomePath(full) },
|
|
1181
|
+
{ name: "internal:SrcFile", value: redactHomePath(full, home) },
|
|
767
1182
|
{ name: "cdx:agentic:tool", value: "zcode" },
|
|
768
1183
|
{ name: "cdx:agentic:kind", value: "plugin" },
|
|
769
1184
|
];
|
|
@@ -813,6 +1228,7 @@ function parseZcodePlugins(dir, parentRef) {
|
|
|
813
1228
|
*
|
|
814
1229
|
* @param {string} dir opencode home directory
|
|
815
1230
|
* @param {string} parentRef Parent tool bom-ref
|
|
1231
|
+
* @param {string} [home] Home directory the tool was found in, for redaction
|
|
816
1232
|
* @returns {Object[]} Child components
|
|
817
1233
|
*/
|
|
818
1234
|
/**
|
|
@@ -823,9 +1239,10 @@ function parseZcodePlugins(dir, parentRef) {
|
|
|
823
1239
|
*
|
|
824
1240
|
* @param {string} dir opencode home directory
|
|
825
1241
|
* @param {string} parentRef Parent tool bom-ref
|
|
1242
|
+
* @param {string} [home] Home directory the tool was found in, for redaction
|
|
826
1243
|
* @returns {Object[]} Child provider services
|
|
827
1244
|
*/
|
|
828
|
-
function parseOpencodeProviders(dir, parentRef) {
|
|
1245
|
+
function parseOpencodeProviders(dir, parentRef, home = homedir()) {
|
|
829
1246
|
const jsonPath = join(dir, "opencode.json");
|
|
830
1247
|
const jsoncPath = join(dir, "opencode.jsonc");
|
|
831
1248
|
const usedPath = safeExistsSync(jsonPath) ? jsonPath : jsoncPath;
|
|
@@ -840,7 +1257,7 @@ function parseOpencodeProviders(dir, parentRef) {
|
|
|
840
1257
|
group: providerName,
|
|
841
1258
|
name: providerName,
|
|
842
1259
|
properties: [
|
|
843
|
-
{ name: "internal:SrcFile", value: redactHomePath(usedPath) },
|
|
1260
|
+
{ name: "internal:SrcFile", value: redactHomePath(usedPath, home) },
|
|
844
1261
|
{ name: "cdx:agentic:tool", value: "opencode" },
|
|
845
1262
|
{ name: "cdx:agentic:kind", value: "provider" },
|
|
846
1263
|
{ name: "cdx:ai:kind", value: "inference-service" },
|
|
@@ -857,18 +1274,25 @@ function parseOpencodeProviders(dir, parentRef) {
|
|
|
857
1274
|
* @param {string} tool Tool key
|
|
858
1275
|
* @param {string} dir Tool home directory
|
|
859
1276
|
* @param {string} parentRef Parent tool bom-ref
|
|
1277
|
+
* @param {string} [home] Home directory the tool was found in, for redaction
|
|
860
1278
|
* @returns {{components: Object[], services: Object[]}} Child inventory
|
|
861
1279
|
*/
|
|
862
|
-
function collectToolChildren(tool, dir, parentRef) {
|
|
1280
|
+
function collectToolChildren(tool, dir, parentRef, home = homedir()) {
|
|
863
1281
|
switch (tool) {
|
|
864
1282
|
case "kiro-cli":
|
|
865
|
-
return {
|
|
1283
|
+
return {
|
|
1284
|
+
components: parseKiroAgents(dir, parentRef, home),
|
|
1285
|
+
services: [],
|
|
1286
|
+
};
|
|
866
1287
|
case "zcode":
|
|
867
|
-
return {
|
|
1288
|
+
return {
|
|
1289
|
+
components: parseZcodePlugins(dir, parentRef, home),
|
|
1290
|
+
services: [],
|
|
1291
|
+
};
|
|
868
1292
|
case "opencode":
|
|
869
1293
|
return {
|
|
870
1294
|
components: [],
|
|
871
|
-
services: parseOpencodeProviders(dir, parentRef),
|
|
1295
|
+
services: parseOpencodeProviders(dir, parentRef, home),
|
|
872
1296
|
};
|
|
873
1297
|
default:
|
|
874
1298
|
return { components: [], services: [] };
|
|
@@ -882,22 +1306,29 @@ function collectToolChildren(tool, dir, parentRef) {
|
|
|
882
1306
|
*
|
|
883
1307
|
* This host scan is unconditional: it does not consult scan filters such as
|
|
884
1308
|
* `--exclude` or profile/technique options, because it inventories fixed tool
|
|
885
|
-
* home directories rather than a project tree.
|
|
886
|
-
* accepted for signature parity and is intentionally not used to alter results.
|
|
1309
|
+
* home directories rather than a project tree.
|
|
887
1310
|
*
|
|
888
|
-
* @param {Object} [options={}] Collection options
|
|
1311
|
+
* @param {Object} [options={}] Collection options
|
|
1312
|
+
* @param {string} [options.home] Home directory to scan, defaulting to the
|
|
1313
|
+
* current user's
|
|
889
1314
|
* @returns {{components: Object[], services: Object[], dependencies: Object[]}} Discovered inventory
|
|
890
1315
|
*/
|
|
891
|
-
export function collectAgenticTools(
|
|
1316
|
+
export function collectAgenticTools(options = {}) {
|
|
892
1317
|
const components = [];
|
|
893
1318
|
const services = [];
|
|
894
1319
|
const dependencies = [];
|
|
895
|
-
|
|
1320
|
+
const home = options.home || homedir();
|
|
1321
|
+
for (const entry of discoverAgenticTools(home)) {
|
|
896
1322
|
try {
|
|
897
|
-
const toolComponent = componentForAgenticTool(entry);
|
|
1323
|
+
const toolComponent = componentForAgenticTool(entry, home);
|
|
898
1324
|
components.push(toolComponent);
|
|
899
1325
|
const parentRef = toolComponent["bom-ref"];
|
|
900
|
-
const children = collectToolChildren(
|
|
1326
|
+
const children = collectToolChildren(
|
|
1327
|
+
entry.tool,
|
|
1328
|
+
entry.dir,
|
|
1329
|
+
parentRef,
|
|
1330
|
+
home,
|
|
1331
|
+
);
|
|
901
1332
|
const childRefs = [];
|
|
902
1333
|
if (children.components.length) {
|
|
903
1334
|
components.push(...children.components);
|