bi-superpowers 1.0.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/.claude-plugin/marketplace.json +31 -0
- package/.claude-plugin/plugin.json +34 -0
- package/.claude-plugin/skill-manifest.json +79 -0
- package/.mcp.json +13 -0
- package/.plugin/plugin.json +14 -0
- package/LICENSE +21 -0
- package/README.md +849 -0
- package/bin/build-plugin.js +97 -0
- package/bin/cli.js +891 -0
- package/bin/commands/autoupdate.js +128 -0
- package/bin/commands/build-desktop.js +368 -0
- package/bin/commands/create-from-template.js +165 -0
- package/bin/commands/diff.js +435 -0
- package/bin/commands/install.js +542 -0
- package/bin/commands/lint.js +441 -0
- package/bin/commands/mcp-setup.js +255 -0
- package/bin/commands/session-update.js +204 -0
- package/bin/commands/smoke-test.js +20 -0
- package/bin/commands/uninstall.js +611 -0
- package/bin/commands/update-check.js +427 -0
- package/bin/commands/validate-cases.js +264 -0
- package/bin/commands/validate-projects.js +426 -0
- package/bin/commands/watch.js +251 -0
- package/bin/lib/agents.js +62 -0
- package/bin/lib/base-template-smoke.js +299 -0
- package/bin/lib/claude-hooks.js +160 -0
- package/bin/lib/generators/claude-plugin.js +529 -0
- package/bin/lib/generators/index.js +116 -0
- package/bin/lib/generators/shared.js +257 -0
- package/bin/lib/mcp-config.js +835 -0
- package/bin/lib/microsoft-mcp.js +206 -0
- package/bin/lib/powerbi-mcp-session.js +140 -0
- package/bin/lib/skills.js +164 -0
- package/bin/lib/template-scaffold.js +366 -0
- package/bin/mcp/powerbi-modeling-launcher.js +42 -0
- package/bin/postinstall.js +50 -0
- package/bin/utils/mcp-detect.js +346 -0
- package/bin/utils/tui.js +314 -0
- package/commands/bi-connect.md +520 -0
- package/commands/bi-dax.md +464 -0
- package/commands/bi-kickoff.md +550 -0
- package/commands/bi-modeling.md +485 -0
- package/commands/bi-performance.md +521 -0
- package/commands/bi-powerquery.md +229 -0
- package/commands/bi-refactor.md +249 -0
- package/commands/bi-scorecard.md +268 -0
- package/commands/bi-start.md +272 -0
- package/config.example.json +23 -0
- package/config.json +23 -0
- package/desktop-extension/manifest.json +30 -0
- package/desktop-extension/package.json +10 -0
- package/desktop-extension/server.js +137 -0
- package/package.json +94 -0
- package/skills/bi-connect/SKILL.md +522 -0
- package/skills/bi-connect/scripts/update-check.js +427 -0
- package/skills/bi-dax/SKILL.md +466 -0
- package/skills/bi-dax/scripts/update-check.js +427 -0
- package/skills/bi-kickoff/SKILL.md +552 -0
- package/skills/bi-kickoff/references/flow.html +78 -0
- package/skills/bi-kickoff/references/flow.md +62 -0
- package/skills/bi-kickoff/scripts/update-check.js +427 -0
- package/skills/bi-modeling/SKILL.md +487 -0
- package/skills/bi-modeling/scripts/update-check.js +427 -0
- package/skills/bi-performance/SKILL.md +523 -0
- package/skills/bi-performance/scripts/install-tabular-editor.ps1 +159 -0
- package/skills/bi-performance/scripts/run-bpa.ps1 +265 -0
- package/skills/bi-performance/scripts/update-check.js +427 -0
- package/skills/bi-powerquery/SKILL.md +231 -0
- package/skills/bi-powerquery/references/base-template-data-contract.md +323 -0
- package/skills/bi-powerquery/references/power-query-standards.md +74 -0
- package/skills/bi-powerquery/scripts/new-powerquery-staging.ps1 +371 -0
- package/skills/bi-powerquery/scripts/test-powerquery-contract.ps1 +225 -0
- package/skills/bi-powerquery/scripts/update-check.js +427 -0
- package/skills/bi-refactor/SKILL.md +251 -0
- package/skills/bi-refactor/references/flow.md +27 -0
- package/skills/bi-refactor/scripts/update-check.js +427 -0
- package/skills/bi-scorecard/SKILL.md +270 -0
- package/skills/bi-scorecard/examples/base-template-scorecard-overlay.json +82 -0
- package/skills/bi-scorecard/scripts/new-scorecard-blueprint-from-base-template.ps1 +124 -0
- package/skills/bi-scorecard/scripts/powerbi-goal-status-rules-api.ps1 +39 -0
- package/skills/bi-scorecard/scripts/powerbi-goal-values-api.ps1 +48 -0
- package/skills/bi-scorecard/scripts/powerbi-goals-api.ps1 +68 -0
- package/skills/bi-scorecard/scripts/powerbi-rest-common.ps1 +197 -0
- package/skills/bi-scorecard/scripts/powerbi-scorecards-api.ps1 +53 -0
- package/skills/bi-scorecard/scripts/update-check.js +427 -0
- package/skills/bi-start/SKILL.md +274 -0
- package/skills/bi-start/scripts/update-check.js +427 -0
- package/src/content/base.md +197 -0
- package/src/content/mcp-requirements.json +57 -0
- package/src/content/routing.md +201 -0
- package/src/content/skills/bi-connect.md +493 -0
- package/src/content/skills/bi-dax.md +437 -0
- package/src/content/skills/bi-kickoff/SKILL.md +523 -0
- package/src/content/skills/bi-kickoff/references/flow.html +78 -0
- package/src/content/skills/bi-kickoff/references/flow.md +62 -0
- package/src/content/skills/bi-modeling.md +458 -0
- package/src/content/skills/bi-performance/SKILL.md +494 -0
- package/src/content/skills/bi-performance/scripts/install-tabular-editor.ps1 +159 -0
- package/src/content/skills/bi-performance/scripts/run-bpa.ps1 +265 -0
- package/src/content/skills/bi-powerquery/SKILL.md +202 -0
- package/src/content/skills/bi-powerquery/references/base-template-data-contract.md +323 -0
- package/src/content/skills/bi-powerquery/references/power-query-standards.md +74 -0
- package/src/content/skills/bi-powerquery/scripts/new-powerquery-staging.ps1 +371 -0
- package/src/content/skills/bi-powerquery/scripts/test-powerquery-contract.ps1 +225 -0
- package/src/content/skills/bi-refactor/SKILL.md +222 -0
- package/src/content/skills/bi-refactor/references/flow.md +27 -0
- package/src/content/skills/bi-scorecard/SKILL.md +241 -0
- package/src/content/skills/bi-scorecard/examples/base-template-scorecard-blueprint.expected.json +105 -0
- package/src/content/skills/bi-scorecard/examples/base-template-scorecard-overlay.json +82 -0
- package/src/content/skills/bi-scorecard/scripts/new-scorecard-blueprint-from-base-template.ps1 +124 -0
- package/src/content/skills/bi-scorecard/scripts/powerbi-goal-status-rules-api.ps1 +39 -0
- package/src/content/skills/bi-scorecard/scripts/powerbi-goal-values-api.ps1 +48 -0
- package/src/content/skills/bi-scorecard/scripts/powerbi-goals-api.ps1 +68 -0
- package/src/content/skills/bi-scorecard/scripts/powerbi-rest-common.ps1 +197 -0
- package/src/content/skills/bi-scorecard/scripts/powerbi-scorecards-api.ps1 +53 -0
- package/src/content/skills/bi-start.md +266 -0
- package/templates/base-template/AGENTS.md +33 -0
- package/templates/base-template/base-template.Report/.platform +11 -0
- package/templates/base-template/base-template.Report/StaticResources/RegisteredResources/BISuperpowers.json +3888 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BaseThemes/CY18SU07.json +177 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BaseThemes/Fluent2-CY26SU03.json +4104 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/AccessibleCityPark.json +26 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/AccessibleDefault.json +26 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/AccessibleNeutral.json +26 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/AccessibleOrchid.json +26 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/AccessibleTidal.json +26 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Bloom.json +139 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/CityPark.json +40 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Classroom.json +40 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/ColorblindSafe.json +48 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/CopilotDefault.json +1861 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Divergent.json +127 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Electric.json +48 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Frontier.json +136 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/HighContrast.json +40 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Highrise.json +41 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Innovate.json +227 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/NewExecutive.json +41 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Solar.json +33 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Storm.json +25 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Sunset.json +48 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Temperature.json +33 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Tidal.json +100 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Twilight.json +40 -0
- package/templates/base-template/base-template.Report/definition/bookmarks/1d40d43c7ade66e8603c.bookmark.json +2297 -0
- package/templates/base-template/base-template.Report/definition/bookmarks/af068ff51c0ca3089ea7.bookmark.json +2300 -0
- package/templates/base-template/base-template.Report/definition/bookmarks/bookmarks.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/page.json +130 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/0352fd80d074693a65db/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/0352fd80d074693a65db/visual.json +669 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/1c5a14bf493697344b68/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/1c5a14bf493697344b68/visual.json +723 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/3486cf7624c5b109b4e5/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/3486cf7624c5b109b4e5/visual.json +333 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/4d8b989008edc0db28d1/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/4d8b989008edc0db28d1/visual.json +109 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/55e10ac7d76a1954f94f/mobile.json +31 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/55e10ac7d76a1954f94f/visual.json +378 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/57f52ecf4490f70e4da1/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/57f52ecf4490f70e4da1/visual.json +175 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/5f4d76bbc870118e9840/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/5f4d76bbc870118e9840/visual.json +468 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/73629e1abebb7a444b59/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/73629e1abebb7a444b59/visual.json +359 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/749cb1388c7e0a88161c/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/749cb1388c7e0a88161c/visual.json +690 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/90677f13cea5d1275990/visual.json +17 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/92cf92e3da10493adb78/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/92cf92e3da10493adb78/visual.json +468 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/9fe17b1971f68443fc15/mobile.json +10 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/9fe17b1971f68443fc15/visual.json +328 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/a30bd0950630ed94e8a3/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/a30bd0950630ed94e8a3/visual.json +578 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/a56e91d9400a835e4814/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/a56e91d9400a835e4814/visual.json +432 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/aded24cd205c0b528642/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/aded24cd205c0b528642/visual.json +801 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/af34b26f14a8a724c9a9/mobile.json +37 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/af34b26f14a8a724c9a9/visual.json +1318 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/b529688fe5a226643322/visual.json +209 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/c4c6f332d05e72e2eb06/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/c4c6f332d05e72e2eb06/visual.json +174 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/fa81f184e2cb0e8b087c/mobile.json +29 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/fa81f184e2cb0e8b087c/visual.json +241 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/page.json +130 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/07e9c4302e29029c5462/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/07e9c4302e29029c5462/visual.json +690 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/109ceede4bc015b0c006/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/109ceede4bc015b0c006/visual.json +468 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/118257e006d472277e10/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/118257e006d472277e10/visual.json +359 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/2caf02e0137c4a1280cc/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/2caf02e0137c4a1280cc/visual.json +669 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/311e76fe3c9edad68204/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/311e76fe3c9edad68204/visual.json +109 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/31c21f8cbeb3b208940a/visual.json +209 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/3ab72c25062437149b03/visual.json +17 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/5959867442abcb0ce2b3/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/5959867442abcb0ce2b3/visual.json +788 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/5b96e0f88d192b044a13/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/5b96e0f88d192b044a13/visual.json +592 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/64e749a63d0786000e22/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/64e749a63d0786000e22/visual.json +468 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/7ae1ca604edac6586ad0/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/7ae1ca604edac6586ad0/visual.json +1310 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/840300733885141a6603/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/840300733885141a6603/visual.json +175 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/a38448cdb203279273d2/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/a38448cdb203279273d2/visual.json +516 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/d1e86f213a3841d12e20/visual.json +328 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/d4a484c1bcc8ee3075e2/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/d4a484c1bcc8ee3075e2/visual.json +432 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/d87cb5cf06acca19bbb5/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/d87cb5cf06acca19bbb5/visual.json +241 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/e243da2677209ed69408/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/e243da2677209ed69408/visual.json +174 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/f3aaf24f5b22b67573b0/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/f3aaf24f5b22b67573b0/visual.json +333 -0
- package/templates/base-template/base-template.Report/definition/pages/pages.json +8 -0
- package/templates/base-template/base-template.Report/definition/report.json +89 -0
- package/templates/base-template/base-template.Report/definition/version.json +4 -0
- package/templates/base-template/base-template.Report/definition.pbir +9 -0
- package/templates/base-template/base-template.SemanticModel/.platform +11 -0
- package/templates/base-template/base-template.SemanticModel/definition/cultures/es-AR.tmdl +11185 -0
- package/templates/base-template/base-template.SemanticModel/definition/database.tmdl +3 -0
- package/templates/base-template/base-template.SemanticModel/definition/expressions.tmdl +234 -0
- package/templates/base-template/base-template.SemanticModel/definition/functions.tmdl +637 -0
- package/templates/base-template/base-template.SemanticModel/definition/model.tmdl +82 -0
- package/templates/base-template/base-template.SemanticModel/definition/relationships.tmdl +271 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Calendario.tmdl +200 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Campa/303/261as.tmdl +75 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Canales.tmdl +84 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Clientes.tmdl +143 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Devoluciones.tmdl +95 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Ejecuci/303/263n proyectos.tmdl" +130 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Entregas.tmdl +122 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Equipos m/303/251tricas.tmdl" +40 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Equipos.tmdl +73 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Horas.tmdl +122 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Interacciones clientes.tmdl +146 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Leads.tmdl +119 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Monedas.tmdl +44 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Movimientos financieros.tmdl +145 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/M/303/251tricas.tmdl +1294 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/N/303/263mina.tmdl +110 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Oportunidades.tmdl +135 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Presupuesto.tmdl +125 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Productos.tmdl +98 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Proyectos.tmdl +77 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Servicios.tmdl +75 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Tareas proyecto.tmdl +102 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Tipo de cambio.tmdl +67 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Ventas.tmdl +180 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux An/303/241lisis dimensiones.tmdl" +38 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Comparaciones.tmdl +227 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Compatibilidad m/303/251trica-dimensi/303/263n.tmdl" +68 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Modelo configuraci/303/263n.tmdl" +44 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Modo fechas.tmdl +36 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux M/303/251trica-Equipo.tmdl" +102 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Overrides m/303/251trica-dimensi/303/263n.tmdl" +54 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Per/303/255odos.tmdl" +182 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Rango fechas modo.tmdl +36 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Rango fechas.tmdl +27 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Vista de calendario.tmdl +30 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_GC C/303/241lculo.tmdl" +70 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_GC Eje X.tmdl +63 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_GC M/303/251trica.tmdl" +374 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_GC Tipo c/303/241lculo.tmdl" +223 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_PC Dimensi/303/263n.tmdl" +98 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_PC Eje X.tmdl +68 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables//303/223rdenes servicio.tmdl" +151 -0
- package/templates/base-template/base-template.SemanticModel/definition.pbism +5 -0
- package/templates/base-template/base-template.SemanticModel/diagramLayout.json +568 -0
- package/templates/base-template/base-template.pbip +14 -0
- package/templates/base-template/template.manifest.json +41 -0
- package/theme/BISuperpowers.json +3888 -0
|
@@ -0,0 +1,542 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install Command — Multi-agent skill + MCP installer
|
|
3
|
+
* =====================================================
|
|
4
|
+
*
|
|
5
|
+
* Installs the bi-superpowers skills and Microsoft MCP servers into
|
|
6
|
+
* every supported AI coding agent:
|
|
7
|
+
* - Claude Code
|
|
8
|
+
* - GitHub Copilot
|
|
9
|
+
* - Codex (OpenAI)
|
|
10
|
+
* - Gemini CLI
|
|
11
|
+
* - Kilo Code
|
|
12
|
+
*
|
|
13
|
+
* Everything is installed at the user level (~/) so it applies across
|
|
14
|
+
* all projects without polluting any specific repo. Skills land in
|
|
15
|
+
* ~/.agents/skills/ (universal path) and each agent's own skill dir is
|
|
16
|
+
* symlinked to that universal copy when possible. Copy fallback mirrors
|
|
17
|
+
* managed skill directories on every run. MCPs are written to each agent's
|
|
18
|
+
* expected config file in the format that agent requires (JSON for
|
|
19
|
+
* most, TOML for Codex) — see `lib/mcp-config.js` for details.
|
|
20
|
+
*
|
|
21
|
+
* Fully open source (MIT). CLI copy, comments, and JSDoc stay in English
|
|
22
|
+
* so contributors from any language can work on the source.
|
|
23
|
+
*
|
|
24
|
+
* Usage:
|
|
25
|
+
* npx bi-superpowers install
|
|
26
|
+
* super install
|
|
27
|
+
* super install --agent claude-code --agent codex
|
|
28
|
+
* super install --all --yes
|
|
29
|
+
*
|
|
30
|
+
* @module commands/install
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
const fs = require('fs');
|
|
34
|
+
const path = require('path');
|
|
35
|
+
const os = require('os');
|
|
36
|
+
const readline = require('readline');
|
|
37
|
+
const { AGENTS, UNIVERSAL_DIR } = require('../lib/agents');
|
|
38
|
+
const { writeMcpConfigForAgent } = require('../lib/mcp-config');
|
|
39
|
+
const { getSkillPurpose } = require('../lib/generators/shared');
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Detect which agents are installed by checking their config directories.
|
|
43
|
+
* Used in the interactive installer to pre-select the detected agents.
|
|
44
|
+
* @param {string} baseDir - Base directory to scan (typically the user's home)
|
|
45
|
+
* @returns {string[]} IDs of detected agents
|
|
46
|
+
*/
|
|
47
|
+
function detectAgents(baseDir) {
|
|
48
|
+
const detected = [];
|
|
49
|
+
for (const [id, agent] of Object.entries(AGENTS)) {
|
|
50
|
+
const agentRoot = path.dirname(agent.dir);
|
|
51
|
+
const checkPaths =
|
|
52
|
+
id === 'kilo'
|
|
53
|
+
? [path.join(baseDir, agentRoot), path.join(baseDir, '.config', 'kilo')]
|
|
54
|
+
: [path.join(baseDir, agentRoot)];
|
|
55
|
+
|
|
56
|
+
if (checkPaths.some((checkPath) => fs.existsSync(checkPath))) {
|
|
57
|
+
detected.push(id);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return detected;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Create a readline interface for interactive prompts.
|
|
65
|
+
*/
|
|
66
|
+
function createReadline() {
|
|
67
|
+
return readline.createInterface({
|
|
68
|
+
input: process.stdin,
|
|
69
|
+
output: process.stdout,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Promise-wrapped readline question.
|
|
75
|
+
*/
|
|
76
|
+
function prompt(rl, question) {
|
|
77
|
+
return new Promise((resolve) => {
|
|
78
|
+
rl.question(question, (answer) => resolve(answer.trim()));
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Render a numbered multi-select list and wait for the user's choice.
|
|
84
|
+
* @param {readline.Interface} rl
|
|
85
|
+
* @param {Array<{id: string, name: string}>} items
|
|
86
|
+
* @param {string[]} preselected - IDs that should default to selected
|
|
87
|
+
* @returns {Promise<string[]>} Selected IDs
|
|
88
|
+
*/
|
|
89
|
+
async function selectMultiple(rl, items, preselected = []) {
|
|
90
|
+
items.forEach((item, i) => {
|
|
91
|
+
const marker = preselected.includes(item.id) ? '●' : '○';
|
|
92
|
+
console.log(` ${i + 1}) ${marker} ${item.name}`);
|
|
93
|
+
});
|
|
94
|
+
console.log();
|
|
95
|
+
console.log(' Enter numbers separated by commas (for example: 1,2,3)');
|
|
96
|
+
console.log(' Press Enter for detected agents, or "a" for all agents');
|
|
97
|
+
|
|
98
|
+
const answer = await prompt(rl, '\n > ');
|
|
99
|
+
|
|
100
|
+
if (answer.toLowerCase() === 'a') {
|
|
101
|
+
return items.map((item) => item.id);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (answer === '') {
|
|
105
|
+
return preselected.length > 0 ? preselected : items.map((item) => item.id);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const indices = answer
|
|
109
|
+
.split(',')
|
|
110
|
+
.map((s) => parseInt(s.trim(), 10) - 1)
|
|
111
|
+
.filter((i) => i >= 0 && i < items.length);
|
|
112
|
+
|
|
113
|
+
return indices.map((i) => items[i].id);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Recursively copy a skill directory (SKILL.md + references/ + scripts/).
|
|
118
|
+
* Filesystem errors propagate to the caller for centralized handling.
|
|
119
|
+
* @param {string} srcDir - Source skill directory
|
|
120
|
+
* @param {string} destDir - Destination directory
|
|
121
|
+
*/
|
|
122
|
+
function copySkillDir(srcDir, destDir) {
|
|
123
|
+
const resolvedSrc = path.resolve(srcDir);
|
|
124
|
+
const resolvedDest = path.resolve(destDir);
|
|
125
|
+
const destRoot = path.parse(resolvedDest).root;
|
|
126
|
+
|
|
127
|
+
if (
|
|
128
|
+
resolvedSrc === resolvedDest ||
|
|
129
|
+
resolvedSrc.startsWith(`${resolvedDest}${path.sep}`) ||
|
|
130
|
+
resolvedDest === destRoot
|
|
131
|
+
) {
|
|
132
|
+
throw new Error(`Refusing to mirror skill directory into unsafe target: ${destDir}`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Skill directories are package-managed. Remove the old managed copy first
|
|
136
|
+
// so upgrades cannot leave deleted scripts or references behind.
|
|
137
|
+
const existingDest = fs.lstatSync(destDir, { throwIfNoEntry: false });
|
|
138
|
+
if (existingDest) {
|
|
139
|
+
if (existingDest.isSymbolicLink()) {
|
|
140
|
+
fs.unlinkSync(destDir);
|
|
141
|
+
} else {
|
|
142
|
+
fs.rmSync(destDir, { recursive: true, force: true });
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
147
|
+
|
|
148
|
+
const entries = fs.readdirSync(srcDir, { withFileTypes: true });
|
|
149
|
+
for (const entry of entries) {
|
|
150
|
+
const srcPath = path.join(srcDir, entry.name);
|
|
151
|
+
const destPath = path.join(destDir, entry.name);
|
|
152
|
+
|
|
153
|
+
if (entry.isDirectory()) {
|
|
154
|
+
copySkillDir(srcPath, destPath);
|
|
155
|
+
} else {
|
|
156
|
+
fs.copyFileSync(srcPath, destPath);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Format a filesystem error with a user-friendly hint based on the code.
|
|
163
|
+
* Keeps the underlying error message so debugging is still possible.
|
|
164
|
+
*/
|
|
165
|
+
function formatFsError(err, context) {
|
|
166
|
+
const codeHints = {
|
|
167
|
+
EACCES: 'Permission denied. Check the directory permissions.',
|
|
168
|
+
EPERM: 'Operation not permitted. On Windows, try running as Administrator.',
|
|
169
|
+
ENOSPC: 'No disk space left.',
|
|
170
|
+
ENOENT: 'File or directory does not exist.',
|
|
171
|
+
EROFS: 'Read-only filesystem.',
|
|
172
|
+
};
|
|
173
|
+
const hint = codeHints[err.code] || '';
|
|
174
|
+
return `${context}: ${err.message}${hint ? `\n ${hint}` : ''}`;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Parse CLI arguments into an options object.
|
|
179
|
+
* Validates that each --agent / -a flag is followed by a real value
|
|
180
|
+
* so we don't silently accept dangling flags.
|
|
181
|
+
*/
|
|
182
|
+
function parseArgs(args) {
|
|
183
|
+
const opts = {
|
|
184
|
+
isYes: args.includes('--yes') || args.includes('-y'),
|
|
185
|
+
isAll: args.includes('--all'),
|
|
186
|
+
autoUpdate: args.includes('--auto-update'),
|
|
187
|
+
agentFlags: [],
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
for (let i = 0; i < args.length; i++) {
|
|
191
|
+
if (args[i] === '--agent' || args[i] === '-a') {
|
|
192
|
+
const next = args[i + 1];
|
|
193
|
+
if (next === undefined || next.startsWith('-')) {
|
|
194
|
+
// Missing value — warn and skip this flag instead of crashing.
|
|
195
|
+
console.warn(
|
|
196
|
+
`⚠ Flag ${args[i]} is missing a value. Usage: ${args[i]} <agent-id>. Ignoring.`
|
|
197
|
+
);
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
opts.agentFlags.push(next);
|
|
201
|
+
i++;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return opts;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Resolve which agents to install based on flags or interactive prompt.
|
|
210
|
+
* @returns {Promise<string[]>} IDs of the selected agents
|
|
211
|
+
*/
|
|
212
|
+
async function resolveSelectedAgents(opts, baseDir, chalk) {
|
|
213
|
+
if (opts.isAll) {
|
|
214
|
+
return Object.keys(AGENTS);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (opts.agentFlags.length > 0) {
|
|
218
|
+
const known = opts.agentFlags.filter((a) => AGENTS[a]);
|
|
219
|
+
const unknown = opts.agentFlags.filter((a) => !AGENTS[a]);
|
|
220
|
+
if (unknown.length > 0) {
|
|
221
|
+
console.log(chalk.yellow(` Unknown agents: ${unknown.join(', ')}`));
|
|
222
|
+
console.log(chalk.gray(` Available agents: ${Object.keys(AGENTS).join(', ')}\n`));
|
|
223
|
+
}
|
|
224
|
+
return known;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (opts.isYes) {
|
|
228
|
+
return Object.keys(AGENTS);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Interactive mode — detect installed agents and prompt the user.
|
|
232
|
+
const detected = detectAgents(baseDir);
|
|
233
|
+
console.log(chalk.cyan(' Select the agents where you want to install:\n'));
|
|
234
|
+
|
|
235
|
+
const items = Object.entries(AGENTS).map(([id, agent]) => ({
|
|
236
|
+
id,
|
|
237
|
+
name: detected.includes(id) ? `${agent.name} ${chalk.green('(detected)')}` : agent.name,
|
|
238
|
+
}));
|
|
239
|
+
|
|
240
|
+
const rl = createReadline();
|
|
241
|
+
try {
|
|
242
|
+
return await selectMultiple(rl, items, detected);
|
|
243
|
+
} finally {
|
|
244
|
+
rl.close();
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Copy skills into the universal path first, then either symlink or copy
|
|
250
|
+
* each selected agent's skill directory to point at the universal copy.
|
|
251
|
+
* @returns {{agentResults: Array, copyFallbacks: number}}
|
|
252
|
+
*/
|
|
253
|
+
function performInstall(skillsSourceDir, skillDirs, selectedAgents, baseDir) {
|
|
254
|
+
// Always install to the universal path first. This is the source of
|
|
255
|
+
// truth that all other agent dirs symlink to.
|
|
256
|
+
const universalTarget = path.join(baseDir, UNIVERSAL_DIR);
|
|
257
|
+
for (const skill of skillDirs) {
|
|
258
|
+
const src = path.join(skillsSourceDir, skill);
|
|
259
|
+
const dest = path.join(universalTarget, skill);
|
|
260
|
+
copySkillDir(src, dest);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const agentResults = [];
|
|
264
|
+
let copyFallbacks = 0;
|
|
265
|
+
|
|
266
|
+
for (const agentId of selectedAgents) {
|
|
267
|
+
const agent = AGENTS[agentId];
|
|
268
|
+
if (agent.dir === UNIVERSAL_DIR) continue; // Already handled above.
|
|
269
|
+
|
|
270
|
+
const agentTarget = path.join(baseDir, agent.dir);
|
|
271
|
+
|
|
272
|
+
// If a real directory already exists (not a symlink), copy into it
|
|
273
|
+
// directly so we don't destroy user data.
|
|
274
|
+
if (fs.existsSync(agentTarget) && !fs.lstatSync(agentTarget).isSymbolicLink()) {
|
|
275
|
+
for (const skill of skillDirs) {
|
|
276
|
+
copySkillDir(path.join(skillsSourceDir, skill), path.join(agentTarget, skill));
|
|
277
|
+
}
|
|
278
|
+
agentResults.push({ agent: agent.name, method: 'copied', dir: agent.dir });
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const parentDir = path.dirname(agentTarget);
|
|
283
|
+
if (!fs.existsSync(parentDir)) {
|
|
284
|
+
fs.mkdirSync(parentDir, { recursive: true });
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// Remove any pre-existing symlink so we can recreate it cleanly.
|
|
288
|
+
if (fs.existsSync(agentTarget) || fs.lstatSync(agentTarget, { throwIfNoEntry: false })) {
|
|
289
|
+
try {
|
|
290
|
+
fs.unlinkSync(agentTarget);
|
|
291
|
+
} catch (_) {
|
|
292
|
+
/* target didn't exist after all — that's fine */
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
try {
|
|
297
|
+
// Relative symlink from the agent's dir to the universal dir.
|
|
298
|
+
const relPath = path.relative(parentDir, universalTarget);
|
|
299
|
+
fs.symlinkSync(relPath, agentTarget);
|
|
300
|
+
agentResults.push({ agent: agent.name, method: 'symlinked', dir: agent.dir });
|
|
301
|
+
} catch (symlinkErr) {
|
|
302
|
+
// Windows without admin can't create symlinks. Fall back to copy
|
|
303
|
+
// and remember so we can warn the user at the end.
|
|
304
|
+
copyFallbacks++;
|
|
305
|
+
if (!fs.existsSync(agentTarget)) {
|
|
306
|
+
fs.mkdirSync(agentTarget, { recursive: true });
|
|
307
|
+
}
|
|
308
|
+
for (const skill of skillDirs) {
|
|
309
|
+
copySkillDir(path.join(skillsSourceDir, skill), path.join(agentTarget, skill));
|
|
310
|
+
}
|
|
311
|
+
agentResults.push({
|
|
312
|
+
agent: agent.name,
|
|
313
|
+
method: 'copied',
|
|
314
|
+
dir: agent.dir,
|
|
315
|
+
fallbackReason: symlinkErr.code || symlinkErr.message,
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
return { agentResults, copyFallbacks };
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Configure the 2 MCP servers (powerbi-modeling + microsoft-learn)
|
|
325
|
+
* for each selected agent by writing the config file in the path and
|
|
326
|
+
* format that agent expects.
|
|
327
|
+
*
|
|
328
|
+
* Per-agent errors don't abort the whole flow: they're collected in the
|
|
329
|
+
* results array so the caller can display them and decide on the exit
|
|
330
|
+
* code.
|
|
331
|
+
*
|
|
332
|
+
* @param {string[]} selectedAgents - Agent IDs to configure
|
|
333
|
+
* @param {string} packageDir - Absolute path to the installed package
|
|
334
|
+
* @param {string} baseDir - User's home directory (for display)
|
|
335
|
+
* @param {Object} chalk - chalk instance for colored output
|
|
336
|
+
* @returns {Array<{agent: string, success: boolean, configPath?: string, error?: string}>}
|
|
337
|
+
*/
|
|
338
|
+
function configureMcpsForAgents(selectedAgents, packageDir, baseDir, chalk) {
|
|
339
|
+
console.log(chalk.cyan('\n Configuring MCP servers (Power BI Modeling + Microsoft Learn)...\n'));
|
|
340
|
+
|
|
341
|
+
const results = [];
|
|
342
|
+
for (const agentId of selectedAgents) {
|
|
343
|
+
const agent = AGENTS[agentId];
|
|
344
|
+
try {
|
|
345
|
+
const configPath = writeMcpConfigForAgent(agentId, packageDir);
|
|
346
|
+
if (configPath) {
|
|
347
|
+
const relPath = configPath.replace(baseDir, '~');
|
|
348
|
+
console.log(chalk.green(` ✓ ${relPath} — ${agent.name}`));
|
|
349
|
+
results.push({ agent: agent.name, configPath, success: true });
|
|
350
|
+
}
|
|
351
|
+
} catch (err) {
|
|
352
|
+
console.log(chalk.red(` ✗ ${agent.name}: ${err.message}`));
|
|
353
|
+
results.push({ agent: agent.name, success: false, error: err.message });
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
return results;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Main handler for the `super install` command.
|
|
361
|
+
* @param {string[]} args - CLI arguments
|
|
362
|
+
* @param {Object} config - Command config from the CLI (packageDir, version)
|
|
363
|
+
*/
|
|
364
|
+
async function installCommand(args, config) {
|
|
365
|
+
const chalk = require('chalk');
|
|
366
|
+
const boxen = require('boxen');
|
|
367
|
+
|
|
368
|
+
const opts = parseArgs(args);
|
|
369
|
+
|
|
370
|
+
// Always install at the user level (home directory) — skills and MCPs
|
|
371
|
+
// apply across all projects without polluting any specific repo.
|
|
372
|
+
const baseDir = os.homedir();
|
|
373
|
+
|
|
374
|
+
// Locate the skills inside the installed package.
|
|
375
|
+
const packageDir = config.packageDir || path.dirname(path.dirname(__dirname));
|
|
376
|
+
const skillsSourceDir = path.join(packageDir, 'skills');
|
|
377
|
+
|
|
378
|
+
if (!fs.existsSync(skillsSourceDir)) {
|
|
379
|
+
console.error(
|
|
380
|
+
chalk.red(
|
|
381
|
+
'Skills directory not found. Reinstall the package with: npm install -g bi-superpowers'
|
|
382
|
+
)
|
|
383
|
+
);
|
|
384
|
+
process.exit(1);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// Read the available skill directories from the package.
|
|
388
|
+
let skillDirs;
|
|
389
|
+
try {
|
|
390
|
+
skillDirs = fs
|
|
391
|
+
.readdirSync(skillsSourceDir, { withFileTypes: true })
|
|
392
|
+
.filter(
|
|
393
|
+
(d) => d.isDirectory() && fs.existsSync(path.join(skillsSourceDir, d.name, 'SKILL.md'))
|
|
394
|
+
)
|
|
395
|
+
.map((d) => d.name);
|
|
396
|
+
} catch (err) {
|
|
397
|
+
console.error(chalk.red(formatFsError(err, 'Could not read skills')));
|
|
398
|
+
process.exit(1);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// Header box shown at the top of every install run.
|
|
402
|
+
console.log(
|
|
403
|
+
boxen(
|
|
404
|
+
chalk.bold.cyan('BI Agent Superpowers') +
|
|
405
|
+
chalk.gray(` v${config.version}`) +
|
|
406
|
+
'\n' +
|
|
407
|
+
chalk.gray('Multi-agent installer'),
|
|
408
|
+
{
|
|
409
|
+
padding: 1,
|
|
410
|
+
borderStyle: 'round',
|
|
411
|
+
borderColor: 'cyan',
|
|
412
|
+
}
|
|
413
|
+
)
|
|
414
|
+
);
|
|
415
|
+
|
|
416
|
+
console.log(chalk.gray(` Install path: ~/${UNIVERSAL_DIR}/`));
|
|
417
|
+
console.log(chalk.gray(` Skills available: ${skillDirs.length}\n`));
|
|
418
|
+
|
|
419
|
+
// Resolve which agents to configure.
|
|
420
|
+
const selectedAgents = await resolveSelectedAgents(opts, baseDir, chalk);
|
|
421
|
+
|
|
422
|
+
if (selectedAgents.length === 0) {
|
|
423
|
+
console.log(chalk.yellow('\n No agent selected. Nothing to install.'));
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
console.log(
|
|
428
|
+
chalk.cyan(`\n Installing ${skillDirs.length} skills for ${selectedAgents.length} agents...\n`)
|
|
429
|
+
);
|
|
430
|
+
|
|
431
|
+
// Phase 1: copy skills and create symlinks per agent.
|
|
432
|
+
let agentResults;
|
|
433
|
+
let copyFallbacks;
|
|
434
|
+
try {
|
|
435
|
+
const result = performInstall(skillsSourceDir, skillDirs, selectedAgents, baseDir);
|
|
436
|
+
agentResults = result.agentResults;
|
|
437
|
+
copyFallbacks = result.copyFallbacks;
|
|
438
|
+
} catch (err) {
|
|
439
|
+
console.error(chalk.red(formatFsError(err, 'Skill installation failed')));
|
|
440
|
+
process.exit(1);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// Report on the universal skills path.
|
|
444
|
+
const universalAgents = selectedAgents
|
|
445
|
+
.filter((id) => AGENTS[id] && AGENTS[id].dir === UNIVERSAL_DIR)
|
|
446
|
+
.map((id) => AGENTS[id].name);
|
|
447
|
+
const universalSuffix = universalAgents.length > 0 ? ` — ${universalAgents.join(', ')}` : '';
|
|
448
|
+
console.log(chalk.green(` ✓ ${UNIVERSAL_DIR}/ (${skillDirs.length} skills)${universalSuffix}`));
|
|
449
|
+
|
|
450
|
+
// Report per agent.
|
|
451
|
+
for (const result of agentResults) {
|
|
452
|
+
const icon = result.method === 'symlinked' ? '→' : '✓';
|
|
453
|
+
console.log(chalk.green(` ${icon} ${result.dir}/ (${result.method}) — ${result.agent}`));
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Warn if any agent fell back from symlink to copy.
|
|
457
|
+
if (copyFallbacks > 0) {
|
|
458
|
+
console.log(
|
|
459
|
+
chalk.yellow(
|
|
460
|
+
`\n ⚠ ${copyFallbacks} agent(s) used copy fallback instead of symlink ` +
|
|
461
|
+
'(probably Windows without admin permissions).\n' +
|
|
462
|
+
" Re-run 'super install' after each upgrade; copied installs are mirrored and stale runtimes are removed."
|
|
463
|
+
)
|
|
464
|
+
);
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// Phase 2: write the 2 MCP configs per agent.
|
|
468
|
+
const mcpResults = configureMcpsForAgents(selectedAgents, packageDir, baseDir, chalk);
|
|
469
|
+
|
|
470
|
+
// Build the final summary box.
|
|
471
|
+
const totalAgents = agentResults.length + (universalAgents.length > 0 ? 1 : 0);
|
|
472
|
+
const mcpSuccess = mcpResults.filter((r) => r.success).length;
|
|
473
|
+
const mcpFailures = mcpResults.filter((r) => !r.success);
|
|
474
|
+
const hasFailures = mcpFailures.length > 0;
|
|
475
|
+
|
|
476
|
+
const successMsg = `Installed ${skillDirs.length} skills + 2 MCPs for ${totalAgents} agents`;
|
|
477
|
+
const failureMsg = `Installed ${skillDirs.length} skills. MCPs: ${mcpSuccess}/${mcpResults.length} agents ok, ${mcpFailures.length} failed.`;
|
|
478
|
+
const headerLine = hasFailures ? chalk.yellow.bold(failureMsg) : chalk.green.bold(successMsg);
|
|
479
|
+
|
|
480
|
+
const failureDetail = hasFailures
|
|
481
|
+
? '\n' +
|
|
482
|
+
chalk.red('Agents with MCP errors:') +
|
|
483
|
+
'\n' +
|
|
484
|
+
mcpFailures.map((r) => chalk.red(` ✗ ${r.agent}: ${r.error}`)).join('\n') +
|
|
485
|
+
'\n'
|
|
486
|
+
: '';
|
|
487
|
+
|
|
488
|
+
const skillSummary = skillDirs
|
|
489
|
+
.map((skillName) => ` /${skillName.padEnd(15)} — ${getSkillPurpose(skillName)}`)
|
|
490
|
+
.join('\n');
|
|
491
|
+
|
|
492
|
+
console.log(
|
|
493
|
+
boxen(
|
|
494
|
+
headerLine +
|
|
495
|
+
failureDetail +
|
|
496
|
+
'\n\n' +
|
|
497
|
+
chalk.gray(`MCPs configured in ${mcpSuccess}/${mcpResults.length} agents.`) +
|
|
498
|
+
'\n' +
|
|
499
|
+
chalk.gray('Restart your AI agent so it loads the new MCP configuration.') +
|
|
500
|
+
'\n\n' +
|
|
501
|
+
chalk.gray(`Skills available (${skillDirs.length}):`) +
|
|
502
|
+
'\n' +
|
|
503
|
+
chalk.gray(skillSummary),
|
|
504
|
+
{
|
|
505
|
+
padding: 1,
|
|
506
|
+
margin: { top: 1 },
|
|
507
|
+
borderStyle: 'round',
|
|
508
|
+
borderColor: hasFailures ? 'yellow' : 'green',
|
|
509
|
+
}
|
|
510
|
+
)
|
|
511
|
+
);
|
|
512
|
+
|
|
513
|
+
// Opt-in: register the Claude Code SessionStart auto-update hook.
|
|
514
|
+
if (opts.autoUpdate) {
|
|
515
|
+
try {
|
|
516
|
+
const { enableAutoupdate } = require('./autoupdate');
|
|
517
|
+
enableAutoupdate(packageDir);
|
|
518
|
+
console.log(
|
|
519
|
+
chalk.green('\n ✓ Auto-update enabled (Claude Code SessionStart hook).') +
|
|
520
|
+
chalk.gray('\n New Claude Code sessions self-update via npm (throttled, background).')
|
|
521
|
+
);
|
|
522
|
+
} catch (err) {
|
|
523
|
+
console.log(chalk.yellow(`\n ⚠ Could not enable auto-update: ${err.message}`));
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
if (hasFailures) {
|
|
528
|
+
// Non-zero exit so CI/scripts know something went wrong. Exit code 2
|
|
529
|
+
// distinguishes partial failure (skills ok, some MCPs failed) from
|
|
530
|
+
// total failure (exit code 1).
|
|
531
|
+
process.exitCode = 2;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// Internal exports for testing.
|
|
536
|
+
module.exports = installCommand;
|
|
537
|
+
module.exports.parseArgs = parseArgs;
|
|
538
|
+
module.exports.detectAgents = detectAgents;
|
|
539
|
+
module.exports.copySkillDir = copySkillDir;
|
|
540
|
+
module.exports.formatFsError = formatFsError;
|
|
541
|
+
module.exports.AGENTS = AGENTS;
|
|
542
|
+
module.exports.UNIVERSAL_DIR = UNIVERSAL_DIR;
|