bps-kit 1.0.1 → 1.0.2
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/package.json +1 -1
- package/templates/.agents/agents/backend-specialist.md +263 -0
- package/templates/.agents/agents/code-archaeologist.md +106 -0
- package/templates/.agents/agents/database-architect.md +226 -0
- package/templates/.agents/agents/debugger.md +225 -0
- package/templates/.agents/agents/devops-engineer.md +242 -0
- package/templates/.agents/agents/documentation-writer.md +104 -0
- package/templates/.agents/agents/explorer-agent.md +73 -0
- package/templates/.agents/agents/frontend-specialist.md +593 -0
- package/templates/.agents/agents/game-developer.md +162 -0
- package/templates/.agents/agents/mobile-developer.md +377 -0
- package/templates/.agents/agents/orchestrator.md +416 -0
- package/templates/.agents/agents/penetration-tester.md +188 -0
- package/templates/.agents/agents/performance-optimizer.md +187 -0
- package/templates/.agents/agents/product-manager.md +112 -0
- package/templates/.agents/agents/product-owner.md +95 -0
- package/templates/.agents/agents/project-planner.md +406 -0
- package/templates/.agents/agents/qa-automation-engineer.md +103 -0
- package/templates/.agents/agents/security-auditor.md +170 -0
- package/templates/.agents/agents/seo-specialist.md +111 -0
- package/templates/.agents/agents/test-engineer.md +158 -0
- package/templates/.agents/rules/GEMINI.md +219 -0
- package/templates/.agents/scripts/auto_preview.py +148 -0
- package/templates/.agents/scripts/checklist.py +217 -0
- package/templates/.agents/scripts/session_manager.py +120 -0
- package/templates/.agents/scripts/verify_all.py +327 -0
- package/templates/.agents/workflows/brainstorm.md +113 -0
- package/templates/.agents/workflows/create.md +59 -0
- package/templates/.agents/workflows/debug.md +103 -0
- package/templates/.agents/workflows/deploy.md +176 -0
- package/templates/.agents/workflows/enhance.md +63 -0
- package/templates/.agents/workflows/orchestrate.md +237 -0
- package/templates/.agents/workflows/plan.md +89 -0
- package/templates/.agents/workflows/preview.md +81 -0
- package/templates/.agents/workflows/setup-brain.md +39 -0
- package/templates/.agents/workflows/status.md +86 -0
- package/templates/.agents/workflows/test.md +144 -0
- package/templates/.agents/workflows/ui-ux-pro-max.md +296 -0
- package/templates/skills_normal/api-patterns/scripts/api_validator.py +211 -0
- package/templates/skills_normal/database-design/scripts/schema_validator.py +172 -0
- package/templates/skills_normal/frontend-design/scripts/accessibility_checker.py +183 -0
- package/templates/skills_normal/frontend-design/scripts/ux_audit.py +722 -0
- package/templates/skills_normal/git-pushing/scripts/smart_commit.sh +19 -0
- package/templates/skills_normal/lint-and-validate/scripts/lint_runner.py +184 -0
- package/templates/skills_normal/lint-and-validate/scripts/type_coverage.py +173 -0
- package/templates/skills_normal/performance-profiling/scripts/lighthouse_audit.py +76 -0
- package/templates/skills_normal/senior-fullstack/scripts/code_quality_analyzer.py +114 -0
- package/templates/skills_normal/senior-fullstack/scripts/fullstack_scaffolder.py +114 -0
- package/templates/skills_normal/senior-fullstack/scripts/project_scaffolder.py +114 -0
- package/templates/skills_normal/seo-fundamentals/scripts/seo_checker.py +219 -0
- package/templates/skills_normal/testing-patterns/scripts/test_runner.py +219 -0
- package/templates/skills_normal/vulnerability-scanner/scripts/security_scan.py +458 -0
- package/templates/vault/007/scripts/config.py +472 -0
- package/templates/vault/007/scripts/full_audit.py +1306 -0
- package/templates/vault/007/scripts/quick_scan.py +481 -0
- package/templates/vault/007/scripts/requirements.txt +26 -0
- package/templates/vault/007/scripts/scanners/__init__.py +0 -0
- package/templates/vault/007/scripts/scanners/dependency_scanner.py +1305 -0
- package/templates/vault/007/scripts/scanners/injection_scanner.py +1104 -0
- package/templates/vault/007/scripts/scanners/secrets_scanner.py +1008 -0
- package/templates/vault/007/scripts/score_calculator.py +693 -0
- package/templates/vault/agent-orchestrator/scripts/match_skills.py +329 -0
- package/templates/vault/agent-orchestrator/scripts/orchestrate.py +304 -0
- package/templates/vault/agent-orchestrator/scripts/requirements.txt +1 -0
- package/templates/vault/agent-orchestrator/scripts/scan_registry.py +508 -0
- package/templates/vault/ai-studio-image/scripts/config.py +613 -0
- package/templates/vault/ai-studio-image/scripts/generate.py +630 -0
- package/templates/vault/ai-studio-image/scripts/prompt_engine.py +424 -0
- package/templates/vault/ai-studio-image/scripts/requirements.txt +4 -0
- package/templates/vault/ai-studio-image/scripts/templates.py +349 -0
- package/templates/vault/android_ui_verification/scripts/verify_ui.sh +32 -0
- package/templates/vault/apify-audience-analysis/reference/scripts/run_actor.js +363 -0
- package/templates/vault/apify-brand-reputation-monitoring/reference/scripts/run_actor.js +363 -0
- package/templates/vault/apify-competitor-intelligence/reference/scripts/run_actor.js +363 -0
- package/templates/vault/apify-content-analytics/reference/scripts/run_actor.js +363 -0
- package/templates/vault/apify-ecommerce/reference/scripts/package.json +3 -0
- package/templates/vault/apify-ecommerce/reference/scripts/run_actor.js +369 -0
- package/templates/vault/apify-influencer-discovery/reference/scripts/run_actor.js +363 -0
- package/templates/vault/apify-lead-generation/reference/scripts/run_actor.js +363 -0
- package/templates/vault/apify-market-research/reference/scripts/run_actor.js +363 -0
- package/templates/vault/apify-trend-analysis/reference/scripts/run_actor.js +363 -0
- package/templates/vault/apify-ultimate-scraper/reference/scripts/run_actor.js +363 -0
- package/templates/vault/audio-transcriber/scripts/install-requirements.sh +190 -0
- package/templates/vault/audio-transcriber/scripts/transcribe.py +486 -0
- package/templates/vault/claude-monitor/scripts/api_bench.py +240 -0
- package/templates/vault/claude-monitor/scripts/config.py +69 -0
- package/templates/vault/claude-monitor/scripts/health_check.py +362 -0
- package/templates/vault/claude-monitor/scripts/monitor.py +296 -0
- package/templates/vault/content-creator/scripts/brand_voice_analyzer.py +185 -0
- package/templates/vault/content-creator/scripts/seo_optimizer.py +419 -0
- package/templates/vault/context-agent/scripts/active_context.py +227 -0
- package/templates/vault/context-agent/scripts/compressor.py +149 -0
- package/templates/vault/context-agent/scripts/config.py +69 -0
- package/templates/vault/context-agent/scripts/context_loader.py +155 -0
- package/templates/vault/context-agent/scripts/context_manager.py +302 -0
- package/templates/vault/context-agent/scripts/models.py +103 -0
- package/templates/vault/context-agent/scripts/project_registry.py +132 -0
- package/templates/vault/context-agent/scripts/requirements.txt +6 -0
- package/templates/vault/context-agent/scripts/search.py +115 -0
- package/templates/vault/context-agent/scripts/session_parser.py +206 -0
- package/templates/vault/context-agent/scripts/session_summary.py +319 -0
- package/templates/vault/context-guardian/scripts/context_snapshot.py +229 -0
- package/templates/vault/docx/ooxml/scripts/pack.py +159 -0
- package/templates/vault/docx/ooxml/scripts/unpack.py +29 -0
- package/templates/vault/docx/ooxml/scripts/validate.py +69 -0
- package/templates/vault/docx/ooxml/scripts/validation/__init__.py +15 -0
- package/templates/vault/docx/ooxml/scripts/validation/base.py +951 -0
- package/templates/vault/docx/ooxml/scripts/validation/docx.py +274 -0
- package/templates/vault/docx/ooxml/scripts/validation/pptx.py +315 -0
- package/templates/vault/docx/ooxml/scripts/validation/redlining.py +279 -0
- package/templates/vault/docx/scripts/__init__.py +1 -0
- package/templates/vault/docx/scripts/document.py +1276 -0
- package/templates/vault/docx/scripts/templates/comments.xml +3 -0
- package/templates/vault/docx/scripts/templates/commentsExtended.xml +3 -0
- package/templates/vault/docx/scripts/templates/commentsExtensible.xml +3 -0
- package/templates/vault/docx/scripts/templates/commentsIds.xml +3 -0
- package/templates/vault/docx/scripts/templates/people.xml +3 -0
- package/templates/vault/docx/scripts/utilities.py +374 -0
- package/templates/vault/docx-official/ooxml/scripts/pack.py +159 -0
- package/templates/vault/docx-official/ooxml/scripts/unpack.py +29 -0
- package/templates/vault/docx-official/ooxml/scripts/validate.py +69 -0
- package/templates/vault/docx-official/ooxml/scripts/validation/__init__.py +15 -0
- package/templates/vault/docx-official/ooxml/scripts/validation/base.py +951 -0
- package/templates/vault/docx-official/ooxml/scripts/validation/docx.py +274 -0
- package/templates/vault/docx-official/ooxml/scripts/validation/pptx.py +315 -0
- package/templates/vault/docx-official/ooxml/scripts/validation/redlining.py +279 -0
- package/templates/vault/docx-official/scripts/__init__.py +1 -0
- package/templates/vault/docx-official/scripts/document.py +1276 -0
- package/templates/vault/docx-official/scripts/templates/comments.xml +3 -0
- package/templates/vault/docx-official/scripts/templates/commentsExtended.xml +3 -0
- package/templates/vault/docx-official/scripts/templates/commentsExtensible.xml +3 -0
- package/templates/vault/docx-official/scripts/templates/commentsIds.xml +3 -0
- package/templates/vault/docx-official/scripts/templates/people.xml +3 -0
- package/templates/vault/docx-official/scripts/utilities.py +374 -0
- package/templates/vault/geo-fundamentals/scripts/geo_checker.py +289 -0
- package/templates/vault/helm-chart-scaffolding/scripts/validate-chart.sh +244 -0
- package/templates/vault/i18n-localization/scripts/i18n_checker.py +241 -0
- package/templates/vault/instagram/scripts/account_setup.py +233 -0
- package/templates/vault/instagram/scripts/analyze.py +221 -0
- package/templates/vault/instagram/scripts/api_client.py +444 -0
- package/templates/vault/instagram/scripts/auth.py +411 -0
- package/templates/vault/instagram/scripts/comments.py +160 -0
- package/templates/vault/instagram/scripts/config.py +111 -0
- package/templates/vault/instagram/scripts/db.py +467 -0
- package/templates/vault/instagram/scripts/export.py +138 -0
- package/templates/vault/instagram/scripts/governance.py +233 -0
- package/templates/vault/instagram/scripts/hashtags.py +114 -0
- package/templates/vault/instagram/scripts/insights.py +170 -0
- package/templates/vault/instagram/scripts/media.py +65 -0
- package/templates/vault/instagram/scripts/messages.py +103 -0
- package/templates/vault/instagram/scripts/profile.py +58 -0
- package/templates/vault/instagram/scripts/publish.py +449 -0
- package/templates/vault/instagram/scripts/requirements.txt +5 -0
- package/templates/vault/instagram/scripts/run_all.py +189 -0
- package/templates/vault/instagram/scripts/schedule.py +189 -0
- package/templates/vault/instagram/scripts/serve_api.py +234 -0
- package/templates/vault/instagram/scripts/templates.py +155 -0
- package/templates/vault/junta-leiloeiros/scripts/db.py +216 -0
- package/templates/vault/junta-leiloeiros/scripts/export.py +137 -0
- package/templates/vault/junta-leiloeiros/scripts/requirements.txt +15 -0
- package/templates/vault/junta-leiloeiros/scripts/run_all.py +190 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/__init__.py +4 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/base_scraper.py +209 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/generic_scraper.py +110 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucap.py +110 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/juceac.py +72 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/juceal.py +72 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/juceb.py +68 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucec.py +63 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucema.py +211 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucemg.py +218 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucep.py +70 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucepa.py +74 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucepar.py +80 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucepe.py +78 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucepi.py +69 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucer.py +256 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucerja.py +170 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucern.py +71 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucesc.py +89 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucesp.py +233 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucetins.py +134 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucis_df.py +63 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/jucisrs.py +299 -0
- package/templates/vault/junta-leiloeiros/scripts/scraper/states.py +99 -0
- package/templates/vault/junta-leiloeiros/scripts/serve_api.py +164 -0
- package/templates/vault/junta-leiloeiros/scripts/web_scraper_fallback.py +233 -0
- package/templates/vault/last30days/scripts/last30days.py +521 -0
- package/templates/vault/last30days/scripts/lib/__init__.py +1 -0
- package/templates/vault/last30days/scripts/lib/cache.py +152 -0
- package/templates/vault/last30days/scripts/lib/dates.py +124 -0
- package/templates/vault/last30days/scripts/lib/dedupe.py +120 -0
- package/templates/vault/last30days/scripts/lib/env.py +149 -0
- package/templates/vault/last30days/scripts/lib/http.py +152 -0
- package/templates/vault/last30days/scripts/lib/models.py +175 -0
- package/templates/vault/last30days/scripts/lib/normalize.py +160 -0
- package/templates/vault/last30days/scripts/lib/openai_reddit.py +230 -0
- package/templates/vault/last30days/scripts/lib/reddit_enrich.py +232 -0
- package/templates/vault/last30days/scripts/lib/render.py +383 -0
- package/templates/vault/last30days/scripts/lib/schema.py +336 -0
- package/templates/vault/last30days/scripts/lib/score.py +311 -0
- package/templates/vault/last30days/scripts/lib/ui.py +324 -0
- package/templates/vault/last30days/scripts/lib/websearch.py +401 -0
- package/templates/vault/last30days/scripts/lib/xai_x.py +217 -0
- package/templates/vault/leiloeiro-avaliacao/scripts/governance.py +106 -0
- package/templates/vault/leiloeiro-avaliacao/scripts/requirements.txt +1 -0
- package/templates/vault/leiloeiro-edital/scripts/governance.py +106 -0
- package/templates/vault/leiloeiro-edital/scripts/requirements.txt +1 -0
- package/templates/vault/leiloeiro-ia/scripts/governance.py +106 -0
- package/templates/vault/leiloeiro-ia/scripts/requirements.txt +1 -0
- package/templates/vault/leiloeiro-juridico/scripts/governance.py +106 -0
- package/templates/vault/leiloeiro-juridico/scripts/requirements.txt +1 -0
- package/templates/vault/leiloeiro-mercado/scripts/governance.py +106 -0
- package/templates/vault/leiloeiro-mercado/scripts/requirements.txt +1 -0
- package/templates/vault/leiloeiro-risco/scripts/governance.py +106 -0
- package/templates/vault/leiloeiro-risco/scripts/requirements.txt +1 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/database.ts +24 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/db.ts +35 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/index.ts +2 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/migrations.ts +31 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/schema.sql +8 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/index.ts +44 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/routes/todos.ts +155 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/types/index.ts +35 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/App.css +384 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/App.tsx +81 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/api/todos.ts +57 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/ConfirmDialog.tsx +26 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/EmptyState.tsx +8 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/TodoForm.tsx +43 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/TodoItem.tsx +36 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/TodoList.tsx +27 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/hooks/useTodos.ts +81 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/index.css +48 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/main.tsx +10 -0
- package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/vite-env.d.ts +1 -0
- package/templates/vault/loki-mode/scripts/export-to-vibe-kanban.sh +178 -0
- package/templates/vault/loki-mode/scripts/loki-wrapper.sh +281 -0
- package/templates/vault/loki-mode/scripts/take-screenshots.js +55 -0
- package/templates/vault/matematico-tao/scripts/complexity_analyzer.py +544 -0
- package/templates/vault/matematico-tao/scripts/dependency_graph.py +538 -0
- package/templates/vault/mcp-builder/scripts/connections.py +151 -0
- package/templates/vault/mcp-builder/scripts/evaluation.py +373 -0
- package/templates/vault/mcp-builder/scripts/example_evaluation.xml +22 -0
- package/templates/vault/mcp-builder/scripts/requirements.txt +2 -0
- package/templates/vault/mobile-design/scripts/mobile_audit.py +670 -0
- package/templates/vault/notebooklm/scripts/__init__.py +81 -0
- package/templates/vault/notebooklm/scripts/ask_question.py +256 -0
- package/templates/vault/notebooklm/scripts/auth_manager.py +358 -0
- package/templates/vault/notebooklm/scripts/browser_session.py +255 -0
- package/templates/vault/notebooklm/scripts/browser_utils.py +107 -0
- package/templates/vault/notebooklm/scripts/cleanup_manager.py +302 -0
- package/templates/vault/notebooklm/scripts/config.py +44 -0
- package/templates/vault/notebooklm/scripts/notebook_manager.py +410 -0
- package/templates/vault/notebooklm/scripts/run.py +102 -0
- package/templates/vault/notebooklm/scripts/setup_environment.py +204 -0
- package/templates/vault/pdf/scripts/check_bounding_boxes.py +70 -0
- package/templates/vault/pdf/scripts/check_bounding_boxes_test.py +226 -0
- package/templates/vault/pdf/scripts/check_fillable_fields.py +12 -0
- package/templates/vault/pdf/scripts/convert_pdf_to_images.py +35 -0
- package/templates/vault/pdf/scripts/create_validation_image.py +41 -0
- package/templates/vault/pdf/scripts/extract_form_field_info.py +152 -0
- package/templates/vault/pdf/scripts/fill_fillable_fields.py +114 -0
- package/templates/vault/pdf/scripts/fill_pdf_form_with_annotations.py +108 -0
- package/templates/vault/pdf-official/scripts/check_bounding_boxes.py +70 -0
- package/templates/vault/pdf-official/scripts/check_bounding_boxes_test.py +226 -0
- package/templates/vault/pdf-official/scripts/check_fillable_fields.py +12 -0
- package/templates/vault/pdf-official/scripts/convert_pdf_to_images.py +35 -0
- package/templates/vault/pdf-official/scripts/create_validation_image.py +41 -0
- package/templates/vault/pdf-official/scripts/extract_form_field_info.py +152 -0
- package/templates/vault/pdf-official/scripts/fill_fillable_fields.py +114 -0
- package/templates/vault/pdf-official/scripts/fill_pdf_form_with_annotations.py +108 -0
- package/templates/vault/planning-with-files/scripts/check-complete.sh +44 -0
- package/templates/vault/planning-with-files/scripts/init-session.sh +120 -0
- package/templates/vault/pptx/ooxml/scripts/pack.py +159 -0
- package/templates/vault/pptx/ooxml/scripts/unpack.py +29 -0
- package/templates/vault/pptx/ooxml/scripts/validate.py +69 -0
- package/templates/vault/pptx/ooxml/scripts/validation/__init__.py +15 -0
- package/templates/vault/pptx/ooxml/scripts/validation/base.py +951 -0
- package/templates/vault/pptx/ooxml/scripts/validation/docx.py +274 -0
- package/templates/vault/pptx/ooxml/scripts/validation/pptx.py +315 -0
- package/templates/vault/pptx/ooxml/scripts/validation/redlining.py +279 -0
- package/templates/vault/pptx/scripts/html2pptx.js +979 -0
- package/templates/vault/pptx/scripts/inventory.py +1020 -0
- package/templates/vault/pptx/scripts/rearrange.py +231 -0
- package/templates/vault/pptx/scripts/replace.py +385 -0
- package/templates/vault/pptx/scripts/thumbnail.py +450 -0
- package/templates/vault/pptx-official/ooxml/scripts/pack.py +159 -0
- package/templates/vault/pptx-official/ooxml/scripts/unpack.py +29 -0
- package/templates/vault/pptx-official/ooxml/scripts/validate.py +69 -0
- package/templates/vault/pptx-official/ooxml/scripts/validation/__init__.py +15 -0
- package/templates/vault/pptx-official/ooxml/scripts/validation/base.py +951 -0
- package/templates/vault/pptx-official/ooxml/scripts/validation/docx.py +274 -0
- package/templates/vault/pptx-official/ooxml/scripts/validation/pptx.py +315 -0
- package/templates/vault/pptx-official/ooxml/scripts/validation/redlining.py +279 -0
- package/templates/vault/pptx-official/scripts/html2pptx.js +979 -0
- package/templates/vault/pptx-official/scripts/inventory.py +1020 -0
- package/templates/vault/pptx-official/scripts/rearrange.py +231 -0
- package/templates/vault/pptx-official/scripts/replace.py +385 -0
- package/templates/vault/pptx-official/scripts/thumbnail.py +450 -0
- package/templates/vault/product-manager-toolkit/scripts/customer_interview_analyzer.py +441 -0
- package/templates/vault/product-manager-toolkit/scripts/rice_prioritizer.py +296 -0
- package/templates/vault/prompt-engineering-patterns/scripts/optimize-prompt.py +279 -0
- package/templates/vault/scripts/.skill_cache.json +7538 -0
- package/templates/vault/scripts/skill_search.py +228 -0
- package/templates/vault/senior-architect/scripts/architecture_diagram_generator.py +114 -0
- package/templates/vault/senior-architect/scripts/dependency_analyzer.py +114 -0
- package/templates/vault/senior-architect/scripts/project_architect.py +114 -0
- package/templates/vault/shopify-development/scripts/requirements.txt +19 -0
- package/templates/vault/shopify-development/scripts/shopify_graphql.py +428 -0
- package/templates/vault/shopify-development/scripts/shopify_init.py +441 -0
- package/templates/vault/shopify-development/scripts/tests/test_shopify_init.py +379 -0
- package/templates/vault/skill-creator/scripts/init_skill.py +303 -0
- package/templates/vault/skill-creator/scripts/package_skill.py +110 -0
- package/templates/vault/skill-creator/scripts/quick_validate.py +95 -0
- package/templates/vault/skill-installer/scripts/detect_skills.py +318 -0
- package/templates/vault/skill-installer/scripts/install_skill.py +1708 -0
- package/templates/vault/skill-installer/scripts/package_skill.py +417 -0
- package/templates/vault/skill-installer/scripts/requirements.txt +1 -0
- package/templates/vault/skill-installer/scripts/validate_skill.py +430 -0
- package/templates/vault/skill-sentinel/scripts/analyzers/__init__.py +13 -0
- package/templates/vault/skill-sentinel/scripts/analyzers/code_quality.py +247 -0
- package/templates/vault/skill-sentinel/scripts/analyzers/cross_skill.py +134 -0
- package/templates/vault/skill-sentinel/scripts/analyzers/dependencies.py +121 -0
- package/templates/vault/skill-sentinel/scripts/analyzers/documentation.py +189 -0
- package/templates/vault/skill-sentinel/scripts/analyzers/governance_audit.py +153 -0
- package/templates/vault/skill-sentinel/scripts/analyzers/performance.py +164 -0
- package/templates/vault/skill-sentinel/scripts/analyzers/security.py +189 -0
- package/templates/vault/skill-sentinel/scripts/config.py +158 -0
- package/templates/vault/skill-sentinel/scripts/cost_optimizer.py +146 -0
- package/templates/vault/skill-sentinel/scripts/db.py +354 -0
- package/templates/vault/skill-sentinel/scripts/governance.py +58 -0
- package/templates/vault/skill-sentinel/scripts/recommender.py +228 -0
- package/templates/vault/skill-sentinel/scripts/report_generator.py +224 -0
- package/templates/vault/skill-sentinel/scripts/requirements.txt +1 -0
- package/templates/vault/skill-sentinel/scripts/run_audit.py +290 -0
- package/templates/vault/skill-sentinel/scripts/scanner.py +271 -0
- package/templates/vault/stability-ai/scripts/config.py +266 -0
- package/templates/vault/stability-ai/scripts/generate.py +687 -0
- package/templates/vault/stability-ai/scripts/requirements.txt +4 -0
- package/templates/vault/stability-ai/scripts/styles.py +174 -0
- package/templates/vault/telegram/assets/boilerplate/nodejs/src/bot-client.ts +86 -0
- package/templates/vault/telegram/assets/boilerplate/nodejs/src/handlers.ts +79 -0
- package/templates/vault/telegram/assets/boilerplate/nodejs/src/index.ts +32 -0
- package/templates/vault/telegram/scripts/send_message.py +143 -0
- package/templates/vault/telegram/scripts/setup_project.py +103 -0
- package/templates/vault/telegram/scripts/test_bot.py +144 -0
- package/templates/vault/typescript-expert/scripts/ts_diagnostic.py +203 -0
- package/templates/vault/ui-ux-pro-max/scripts/__pycache__/core.cpython-314.pyc +0 -0
- package/templates/vault/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-314.pyc +0 -0
- package/templates/vault/ui-ux-pro-max/scripts/core.py +257 -0
- package/templates/vault/ui-ux-pro-max/scripts/design_system.py +487 -0
- package/templates/vault/ui-ux-pro-max/scripts/search.py +76 -0
- package/templates/vault/videodb/scripts/ws_listener.py +204 -0
- package/templates/vault/web-artifacts-builder/scripts/bundle-artifact.sh +54 -0
- package/templates/vault/web-artifacts-builder/scripts/init-artifact.sh +322 -0
- package/templates/vault/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
- package/templates/vault/webapp-testing/scripts/with_server.py +106 -0
- package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/index.ts +125 -0
- package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/template-manager.ts +67 -0
- package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/types.ts +216 -0
- package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/webhook-handler.ts +173 -0
- package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/whatsapp-client.ts +193 -0
- package/templates/vault/whatsapp-cloud-api/scripts/send_test_message.py +137 -0
- package/templates/vault/whatsapp-cloud-api/scripts/setup_project.py +118 -0
- package/templates/vault/whatsapp-cloud-api/scripts/validate_config.py +190 -0
- package/templates/vault/youtube-summarizer/scripts/extract-transcript.py +65 -0
- package/templates/vault/youtube-summarizer/scripts/install-dependencies.sh +28 -0
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Skill Matching Algorithm for Agent Orchestrator.
|
|
4
|
+
|
|
5
|
+
Scores and ranks skills against a user query to determine
|
|
6
|
+
which agents are relevant for the current request.
|
|
7
|
+
|
|
8
|
+
Scoring:
|
|
9
|
+
- Skill name appears in query: +15
|
|
10
|
+
- Exact trigger keyword match: +10 per keyword
|
|
11
|
+
- Capability category match: +5 per category
|
|
12
|
+
- Description word overlap: +1 per word
|
|
13
|
+
- Project assignment boost: +20 if skill is assigned to active project
|
|
14
|
+
|
|
15
|
+
Usage:
|
|
16
|
+
python match_skills.py "raspar dados de um site"
|
|
17
|
+
python match_skills.py "coletar precos e enviar por whatsapp"
|
|
18
|
+
python match_skills.py --project myproject "query here"
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
import json
|
|
22
|
+
import sys
|
|
23
|
+
import os
|
|
24
|
+
import re
|
|
25
|
+
import subprocess
|
|
26
|
+
from pathlib import Path
|
|
27
|
+
|
|
28
|
+
# ── Configuration ──────────────────────────────────────────────────────────
|
|
29
|
+
|
|
30
|
+
# Resolve paths relative to this script's location
|
|
31
|
+
_SCRIPT_DIR = Path(__file__).resolve().parent
|
|
32
|
+
ORCHESTRATOR_DIR = _SCRIPT_DIR.parent
|
|
33
|
+
SKILLS_ROOT = ORCHESTRATOR_DIR.parent
|
|
34
|
+
DATA_DIR = ORCHESTRATOR_DIR / "data"
|
|
35
|
+
REGISTRY_PATH = DATA_DIR / "registry.json"
|
|
36
|
+
PROJECTS_PATH = DATA_DIR / "projects.json"
|
|
37
|
+
SCAN_SCRIPT = _SCRIPT_DIR / "scan_registry.py"
|
|
38
|
+
|
|
39
|
+
# Capability keywords for query -> category matching (PT + EN)
|
|
40
|
+
CAPABILITY_KEYWORDS = {
|
|
41
|
+
"data-extraction": [
|
|
42
|
+
"scrape", "extract", "crawl", "parse", "harvest", "collect", "data",
|
|
43
|
+
"raspar", "extrair", "coletar", "dados", "tabela", "table", "csv",
|
|
44
|
+
"web data", "pull info", "get data",
|
|
45
|
+
],
|
|
46
|
+
"messaging": [
|
|
47
|
+
"whatsapp", "message", "send", "chat", "notify", "notification", "sms",
|
|
48
|
+
"mensagem", "enviar", "notificar", "notificacao", "atendimento",
|
|
49
|
+
"comunicar", "avisar",
|
|
50
|
+
],
|
|
51
|
+
"social-media": [
|
|
52
|
+
"instagram", "facebook", "twitter", "post", "stories", "reels",
|
|
53
|
+
"social", "feed", "follower", "publicar", "rede social", "engajamento",
|
|
54
|
+
],
|
|
55
|
+
"government-data": [
|
|
56
|
+
"junta", "leiloeiro", "cadastro", "governo", "comercial", "tribunal",
|
|
57
|
+
"diario oficial", "certidao", "registro", "uf", "estado",
|
|
58
|
+
],
|
|
59
|
+
"web-automation": [
|
|
60
|
+
"browser", "selenium", "playwright", "automate", "click", "fill form",
|
|
61
|
+
"navegador", "automatizar", "automacao", "preencher",
|
|
62
|
+
],
|
|
63
|
+
"api-integration": [
|
|
64
|
+
"api", "endpoint", "webhook", "rest", "graph", "oauth", "token",
|
|
65
|
+
"integracao", "integrar", "conectar",
|
|
66
|
+
],
|
|
67
|
+
"analytics": [
|
|
68
|
+
"insight", "analytics", "metrics", "dashboard", "report", "stats",
|
|
69
|
+
"relatorio", "metricas", "analise", "estatistica",
|
|
70
|
+
],
|
|
71
|
+
"content-management": [
|
|
72
|
+
"publish", "schedule", "template", "content", "media", "upload",
|
|
73
|
+
"publicar", "agendar", "conteudo", "midia",
|
|
74
|
+
],
|
|
75
|
+
"legal": [
|
|
76
|
+
"advogado", "direito", "juridico", "lei", "processo",
|
|
77
|
+
"acao", "peticao", "recurso", "sentenca", "juiz",
|
|
78
|
+
"divorcio", "guarda", "alimentos", "pensao", "alimenticia", "inventario", "heranca", "partilha",
|
|
79
|
+
"acidente de trabalho", "acidente",
|
|
80
|
+
"familia", "criminal", "penal", "crime", "feminicidio", "maria da penha",
|
|
81
|
+
"violencia domestica", "medida protetiva", "stalking",
|
|
82
|
+
"danos morais", "responsabilidade civil", "indenizacao", "dano",
|
|
83
|
+
"consumidor", "cdc", "plano de saude",
|
|
84
|
+
"trabalhista", "clt", "rescisao", "fgts", "horas extras",
|
|
85
|
+
"previdenciario", "aposentadoria", "aposentar", "inss",
|
|
86
|
+
"imobiliario", "usucapiao", "despejo", "inquilinato",
|
|
87
|
+
"alienacao fiduciaria", "bem de familia",
|
|
88
|
+
"tributario", "imposto", "icms", "execucao fiscal",
|
|
89
|
+
"administrativo", "licitacao", "improbidade", "mandado de seguranca",
|
|
90
|
+
"empresarial", "societario", "falencia", "recuperacao judicial",
|
|
91
|
+
"empresa", "ltda", "cnpj", "mei", "eireli", "contrato social",
|
|
92
|
+
"contrato", "clausula", "contestacao", "apelacao", "agravo",
|
|
93
|
+
"habeas corpus", "mandado", "liminar", "tutela",
|
|
94
|
+
"cpc", "stj", "stf", "sumula", "jurisprudencia",
|
|
95
|
+
"oab", "honorarios", "custas",
|
|
96
|
+
],
|
|
97
|
+
"auction": [
|
|
98
|
+
"leilao", "leilao judicial", "leilao extrajudicial", "hasta publica",
|
|
99
|
+
"arrematacao", "arrematar", "arrematante", "lance", "desagio",
|
|
100
|
+
"edital leilao", "penhora", "adjudicacao", "praca",
|
|
101
|
+
"imissao na posse", "carta arrematacao", "vil preco",
|
|
102
|
+
"avaliacao imovel", "laudo", "perito", "matricula",
|
|
103
|
+
"leiloeiro", "comissao leiloeiro",
|
|
104
|
+
],
|
|
105
|
+
"security": [
|
|
106
|
+
"seguranca", "security", "owasp", "vulnerability", "incident",
|
|
107
|
+
"pentest", "firewall", "malware", "phishing", "cve",
|
|
108
|
+
"autenticacao", "criptografia", "encryption",
|
|
109
|
+
],
|
|
110
|
+
"image-generation": [
|
|
111
|
+
"imagem", "image", "gerar imagem", "generate image",
|
|
112
|
+
"stable diffusion", "comfyui", "midjourney", "dall-e",
|
|
113
|
+
"foto", "ilustracao", "arte", "design",
|
|
114
|
+
],
|
|
115
|
+
"monitoring": [
|
|
116
|
+
"monitor", "monitorar", "health", "status",
|
|
117
|
+
"audit", "auditoria", "sentinel", "check",
|
|
118
|
+
],
|
|
119
|
+
"context-management": [
|
|
120
|
+
"contexto", "context", "sessao", "session", "compactacao", "compaction",
|
|
121
|
+
"comprimir", "compress", "snapshot", "checkpoint", "briefing",
|
|
122
|
+
"continuidade", "continuity", "preservar", "preserve",
|
|
123
|
+
"memoria", "memory", "resumo", "summary",
|
|
124
|
+
"salvar estado", "save state", "context window", "janela de contexto",
|
|
125
|
+
"perda de dados", "data loss", "backup",
|
|
126
|
+
],
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
# ── Functions ──────────────────────────────────────────────────────────────
|
|
131
|
+
|
|
132
|
+
def ensure_registry():
|
|
133
|
+
"""Run scan if registry doesn't exist."""
|
|
134
|
+
if not REGISTRY_PATH.exists():
|
|
135
|
+
subprocess.run(
|
|
136
|
+
[sys.executable, str(SCAN_SCRIPT)],
|
|
137
|
+
capture_output=True, text=True
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def load_registry() -> list[dict]:
|
|
142
|
+
"""Load skills from registry.json."""
|
|
143
|
+
ensure_registry()
|
|
144
|
+
if not REGISTRY_PATH.exists():
|
|
145
|
+
return []
|
|
146
|
+
try:
|
|
147
|
+
data = json.loads(REGISTRY_PATH.read_text(encoding="utf-8"))
|
|
148
|
+
return data.get("skills", [])
|
|
149
|
+
except Exception:
|
|
150
|
+
return []
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def load_projects() -> dict:
|
|
154
|
+
"""Load project assignments."""
|
|
155
|
+
if not PROJECTS_PATH.exists():
|
|
156
|
+
return {"projects": []}
|
|
157
|
+
try:
|
|
158
|
+
return json.loads(PROJECTS_PATH.read_text(encoding="utf-8"))
|
|
159
|
+
except Exception:
|
|
160
|
+
return {"projects": []}
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def get_project_skills(project_name: str) -> set:
|
|
164
|
+
"""Get set of skill names assigned to a project."""
|
|
165
|
+
projects = load_projects()
|
|
166
|
+
for p in projects.get("projects", []):
|
|
167
|
+
if p.get("name", "").lower() == project_name.lower():
|
|
168
|
+
return set(p.get("skills", []))
|
|
169
|
+
return set()
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def query_to_capabilities(query: str) -> list[str]:
|
|
173
|
+
"""Map a query to capability categories using word boundary matching."""
|
|
174
|
+
q_lower = query.lower()
|
|
175
|
+
q_words = set(re.findall(r'[a-zA-ZÀ-ÿ]+', q_lower))
|
|
176
|
+
caps = []
|
|
177
|
+
for cap, keywords in CAPABILITY_KEYWORDS.items():
|
|
178
|
+
for kw in keywords:
|
|
179
|
+
# Multi-word keywords: substring match. Single-word: exact word match.
|
|
180
|
+
if " " in kw:
|
|
181
|
+
if kw in q_lower:
|
|
182
|
+
caps.append(cap)
|
|
183
|
+
break
|
|
184
|
+
elif kw in q_words:
|
|
185
|
+
caps.append(cap)
|
|
186
|
+
break
|
|
187
|
+
return caps
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def normalize(text: str) -> set[str]:
|
|
191
|
+
"""Normalize text to a set of lowercase words."""
|
|
192
|
+
return set(re.findall(r'[a-zA-ZÀ-ÿ]{3,}', text.lower()))
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def score_skill(skill: dict, query: str, project_skills: set = None) -> dict:
|
|
196
|
+
"""
|
|
197
|
+
Score a skill's relevance to a query.
|
|
198
|
+
|
|
199
|
+
Returns dict with score, reasons, and skill info.
|
|
200
|
+
"""
|
|
201
|
+
q_lower = query.lower()
|
|
202
|
+
score = 0
|
|
203
|
+
reasons = []
|
|
204
|
+
|
|
205
|
+
name = skill.get("name", "")
|
|
206
|
+
description = skill.get("description", "")
|
|
207
|
+
triggers = skill.get("triggers", [])
|
|
208
|
+
capabilities = skill.get("capabilities", [])
|
|
209
|
+
|
|
210
|
+
# 1. Skill name in query (+15)
|
|
211
|
+
if name.lower() in q_lower or name.lower().replace("-", " ") in q_lower:
|
|
212
|
+
score += 15
|
|
213
|
+
reasons.append(f"name:{name}")
|
|
214
|
+
|
|
215
|
+
# 2. Trigger keyword matches (+10 each) - word boundary matching
|
|
216
|
+
q_words = set(re.findall(r'[a-zA-ZÀ-ÿ]+', q_lower))
|
|
217
|
+
for trigger in triggers:
|
|
218
|
+
trigger_lower = trigger.lower()
|
|
219
|
+
# Multi-word triggers: substring match. Single-word: exact word match.
|
|
220
|
+
if " " in trigger_lower:
|
|
221
|
+
if trigger_lower in q_lower:
|
|
222
|
+
score += 10
|
|
223
|
+
reasons.append(f"trigger:{trigger}")
|
|
224
|
+
elif trigger_lower in q_words:
|
|
225
|
+
score += 10
|
|
226
|
+
reasons.append(f"trigger:{trigger}")
|
|
227
|
+
|
|
228
|
+
# 3. Capability category match (+5 each)
|
|
229
|
+
query_caps = query_to_capabilities(query)
|
|
230
|
+
for cap in capabilities:
|
|
231
|
+
if cap in query_caps:
|
|
232
|
+
score += 5
|
|
233
|
+
reasons.append(f"capability:{cap}")
|
|
234
|
+
|
|
235
|
+
# 4. Description word overlap (+1 each, max 10)
|
|
236
|
+
query_words = normalize(query)
|
|
237
|
+
desc_words = normalize(description)
|
|
238
|
+
overlap = query_words & desc_words
|
|
239
|
+
overlap_score = min(len(overlap), 10)
|
|
240
|
+
if overlap_score > 0:
|
|
241
|
+
score += overlap_score
|
|
242
|
+
reasons.append(f"word_overlap:{overlap_score}")
|
|
243
|
+
|
|
244
|
+
# 5. Project assignment boost (+20)
|
|
245
|
+
if project_skills and name in project_skills:
|
|
246
|
+
score += 20
|
|
247
|
+
reasons.append("project_boost")
|
|
248
|
+
|
|
249
|
+
return {
|
|
250
|
+
"name": name,
|
|
251
|
+
"score": score,
|
|
252
|
+
"reasons": reasons,
|
|
253
|
+
"location": skill.get("location", ""),
|
|
254
|
+
"skill_md": skill.get("skill_md", ""),
|
|
255
|
+
"capabilities": capabilities,
|
|
256
|
+
"status": skill.get("status", "unknown"),
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def match(query: str, project: str = None, top_n: int = 5, threshold: int = 5) -> list[dict]:
|
|
261
|
+
"""
|
|
262
|
+
Match a query against all registered skills.
|
|
263
|
+
|
|
264
|
+
Returns top N skills with score >= threshold, sorted by score descending.
|
|
265
|
+
"""
|
|
266
|
+
skills = load_registry()
|
|
267
|
+
if not skills:
|
|
268
|
+
return []
|
|
269
|
+
|
|
270
|
+
project_skills = get_project_skills(project) if project else set()
|
|
271
|
+
|
|
272
|
+
results = []
|
|
273
|
+
for skill in skills:
|
|
274
|
+
result = score_skill(skill, query, project_skills)
|
|
275
|
+
if result["score"] >= threshold:
|
|
276
|
+
results.append(result)
|
|
277
|
+
|
|
278
|
+
results.sort(key=lambda x: x["score"], reverse=True)
|
|
279
|
+
return results[:top_n]
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
# ── CLI Entry Point ────────────────────────────────────────────────────────
|
|
283
|
+
|
|
284
|
+
def main():
|
|
285
|
+
args = sys.argv[1:]
|
|
286
|
+
project = None
|
|
287
|
+
query_parts = []
|
|
288
|
+
|
|
289
|
+
i = 0
|
|
290
|
+
while i < len(args):
|
|
291
|
+
if args[i] == "--project" and i + 1 < len(args):
|
|
292
|
+
project = args[i + 1]
|
|
293
|
+
i += 2
|
|
294
|
+
else:
|
|
295
|
+
query_parts.append(args[i])
|
|
296
|
+
i += 1
|
|
297
|
+
|
|
298
|
+
query = " ".join(query_parts)
|
|
299
|
+
|
|
300
|
+
if not query:
|
|
301
|
+
print(json.dumps({
|
|
302
|
+
"error": "No query provided",
|
|
303
|
+
"usage": 'python match_skills.py "your query here"'
|
|
304
|
+
}, indent=2))
|
|
305
|
+
sys.exit(1)
|
|
306
|
+
|
|
307
|
+
results = match(query, project=project)
|
|
308
|
+
|
|
309
|
+
output = {
|
|
310
|
+
"query": query,
|
|
311
|
+
"project": project,
|
|
312
|
+
"matched": len(results),
|
|
313
|
+
"skills": results,
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if len(results) == 0:
|
|
317
|
+
output["recommendation"] = "No skills matched. Operate without skills or suggest creating a new one."
|
|
318
|
+
elif len(results) == 1:
|
|
319
|
+
output["recommendation"] = f"Single skill match: use '{results[0]['name']}' directly."
|
|
320
|
+
output["action"] = "load_skill"
|
|
321
|
+
else:
|
|
322
|
+
output["recommendation"] = f"Multiple skills matched ({len(results)}). Use orchestration."
|
|
323
|
+
output["action"] = "orchestrate"
|
|
324
|
+
|
|
325
|
+
print(json.dumps(output, indent=2, ensure_ascii=False))
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
if __name__ == "__main__":
|
|
329
|
+
main()
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Multi-Skill Orchestration Engine for Agent Orchestrator.
|
|
4
|
+
|
|
5
|
+
Given matched skills and a query, determines the orchestration pattern
|
|
6
|
+
and generates an execution plan for Claude to follow.
|
|
7
|
+
|
|
8
|
+
Patterns:
|
|
9
|
+
- single: One skill handles the entire request
|
|
10
|
+
- sequential: Skills form a pipeline (A output -> B input)
|
|
11
|
+
- parallel: Skills work independently on different aspects
|
|
12
|
+
- primary_support: One skill leads, others provide supporting data
|
|
13
|
+
|
|
14
|
+
Usage:
|
|
15
|
+
python orchestrate.py --skills web-scraper,whatsapp-cloud-api --query "monitorar precos e enviar alerta"
|
|
16
|
+
python orchestrate.py --match-result '{"skills": [...]}' --query "query"
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import json
|
|
20
|
+
import sys
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
|
|
23
|
+
# ── Configuration ──────────────────────────────────────────────────────────
|
|
24
|
+
|
|
25
|
+
# Resolve paths relative to this script's location
|
|
26
|
+
_SCRIPT_DIR = Path(__file__).resolve().parent
|
|
27
|
+
ORCHESTRATOR_DIR = _SCRIPT_DIR.parent
|
|
28
|
+
SKILLS_ROOT = ORCHESTRATOR_DIR.parent
|
|
29
|
+
DATA_DIR = ORCHESTRATOR_DIR / "data"
|
|
30
|
+
REGISTRY_PATH = DATA_DIR / "registry.json"
|
|
31
|
+
|
|
32
|
+
# Define which capabilities are typically "producers" vs "consumers"
|
|
33
|
+
# Producers generate data; consumers act on data
|
|
34
|
+
PRODUCER_CAPABILITIES = {"data-extraction", "government-data", "analytics"}
|
|
35
|
+
CONSUMER_CAPABILITIES = {"messaging", "social-media", "content-management"}
|
|
36
|
+
HYBRID_CAPABILITIES = {"api-integration", "web-automation"}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# ── Functions ──────────────────────────────────────────────────────────────
|
|
40
|
+
|
|
41
|
+
def load_registry() -> dict[str, dict]:
|
|
42
|
+
"""Load registry as name->skill dict."""
|
|
43
|
+
if not REGISTRY_PATH.exists():
|
|
44
|
+
return {}
|
|
45
|
+
try:
|
|
46
|
+
data = json.loads(REGISTRY_PATH.read_text(encoding="utf-8"))
|
|
47
|
+
return {s["name"]: s for s in data.get("skills", [])}
|
|
48
|
+
except Exception:
|
|
49
|
+
return {}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def get_skill_role(skill: dict) -> str:
|
|
53
|
+
"""Determine if a skill is primarily a producer, consumer, or hybrid.
|
|
54
|
+
|
|
55
|
+
Uses weighted scoring: more specific capabilities (data-extraction,
|
|
56
|
+
messaging) outweigh generic ones (api-integration, content-management).
|
|
57
|
+
"""
|
|
58
|
+
caps = set(skill.get("capabilities", []))
|
|
59
|
+
|
|
60
|
+
producer_count = len(caps & PRODUCER_CAPABILITIES)
|
|
61
|
+
consumer_count = len(caps & CONSUMER_CAPABILITIES)
|
|
62
|
+
|
|
63
|
+
# If skill has both producer and consumer caps, use the dominant one
|
|
64
|
+
if producer_count > consumer_count:
|
|
65
|
+
return "producer"
|
|
66
|
+
elif consumer_count > producer_count:
|
|
67
|
+
return "consumer"
|
|
68
|
+
elif producer_count > 0 and consumer_count > 0:
|
|
69
|
+
# Equal weight - check if core name suggests a role
|
|
70
|
+
name = skill.get("name", "").lower()
|
|
71
|
+
if any(kw in name for kw in ["scraper", "extract", "collect", "data", "junta"]):
|
|
72
|
+
return "producer"
|
|
73
|
+
if any(kw in name for kw in ["whatsapp", "instagram", "messenger", "notify"]):
|
|
74
|
+
return "consumer"
|
|
75
|
+
return "hybrid"
|
|
76
|
+
else:
|
|
77
|
+
return "hybrid"
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def classify_pattern(skills: list[dict], query: str) -> str:
|
|
81
|
+
"""
|
|
82
|
+
Determine the orchestration pattern based on skill roles and query.
|
|
83
|
+
|
|
84
|
+
Rules:
|
|
85
|
+
1. Single skill -> "single"
|
|
86
|
+
2. Producer(s) + Consumer(s) -> "sequential" (data flows producer->consumer)
|
|
87
|
+
3. All same role -> "parallel" (independent work)
|
|
88
|
+
4. One high-score + others lower -> "primary_support"
|
|
89
|
+
"""
|
|
90
|
+
if len(skills) <= 1:
|
|
91
|
+
return "single"
|
|
92
|
+
|
|
93
|
+
roles = [get_skill_role(s) for s in skills]
|
|
94
|
+
has_producer = "producer" in roles
|
|
95
|
+
has_consumer = "consumer" in roles
|
|
96
|
+
|
|
97
|
+
# Producer -> Consumer pipeline
|
|
98
|
+
if has_producer and has_consumer:
|
|
99
|
+
return "sequential"
|
|
100
|
+
|
|
101
|
+
# Check if one skill dominates by score
|
|
102
|
+
scores = [s.get("score", 0) for s in skills]
|
|
103
|
+
if len(scores) >= 2:
|
|
104
|
+
scores_sorted = sorted(scores, reverse=True)
|
|
105
|
+
if scores_sorted[0] >= scores_sorted[1] * 2:
|
|
106
|
+
return "primary_support"
|
|
107
|
+
|
|
108
|
+
# All same role or no clear pipeline
|
|
109
|
+
return "parallel"
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def generate_plan(skills: list[dict], query: str, pattern: str) -> dict:
|
|
113
|
+
"""Generate an execution plan based on the pattern."""
|
|
114
|
+
|
|
115
|
+
if pattern == "single":
|
|
116
|
+
skill = skills[0]
|
|
117
|
+
return {
|
|
118
|
+
"pattern": "single",
|
|
119
|
+
"description": f"Use '{skill['name']}' to handle the entire request.",
|
|
120
|
+
"steps": [
|
|
121
|
+
{
|
|
122
|
+
"order": 1,
|
|
123
|
+
"skill": skill["name"],
|
|
124
|
+
"skill_md": skill.get("skill_md", skill.get("location", "")),
|
|
125
|
+
"action": f"Load SKILL.md and follow its workflow for: {query}",
|
|
126
|
+
"input": "user_query",
|
|
127
|
+
"output": "result",
|
|
128
|
+
}
|
|
129
|
+
],
|
|
130
|
+
"data_flow": "user_query -> result",
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
elif pattern == "sequential":
|
|
134
|
+
# Order: producers first, then consumers
|
|
135
|
+
producers = [s for s in skills if get_skill_role(s) in ("producer", "hybrid")]
|
|
136
|
+
consumers = [s for s in skills if get_skill_role(s) == "consumer"]
|
|
137
|
+
|
|
138
|
+
# If no clear producers, use score order
|
|
139
|
+
if not producers:
|
|
140
|
+
producers = [skills[0]]
|
|
141
|
+
consumers = skills[1:]
|
|
142
|
+
|
|
143
|
+
ordered = producers + consumers
|
|
144
|
+
steps = []
|
|
145
|
+
for i, skill in enumerate(ordered):
|
|
146
|
+
role = get_skill_role(skill)
|
|
147
|
+
if i == 0:
|
|
148
|
+
input_src = "user_query"
|
|
149
|
+
action = f"Extract/collect data: {query}"
|
|
150
|
+
else:
|
|
151
|
+
prev = ordered[i - 1]["name"]
|
|
152
|
+
input_src = f"{prev}.output"
|
|
153
|
+
if role == "consumer":
|
|
154
|
+
action = f"Process/deliver data from {prev}"
|
|
155
|
+
else:
|
|
156
|
+
action = f"Continue processing with data from {prev}"
|
|
157
|
+
|
|
158
|
+
steps.append({
|
|
159
|
+
"order": i + 1,
|
|
160
|
+
"skill": skill["name"],
|
|
161
|
+
"skill_md": skill.get("skill_md", skill.get("location", "")),
|
|
162
|
+
"action": action,
|
|
163
|
+
"input": input_src,
|
|
164
|
+
"output": f"{skill['name']}.output",
|
|
165
|
+
"role": role,
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
flow_parts = [s["skill"] for s in steps]
|
|
169
|
+
data_flow = " -> ".join(["user_query"] + flow_parts + ["result"])
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
"pattern": "sequential",
|
|
173
|
+
"description": f"Pipeline: {' -> '.join(flow_parts)}",
|
|
174
|
+
"steps": steps,
|
|
175
|
+
"data_flow": data_flow,
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
elif pattern == "parallel":
|
|
179
|
+
steps = []
|
|
180
|
+
for i, skill in enumerate(skills):
|
|
181
|
+
steps.append({
|
|
182
|
+
"order": 1, # All run at the same "order" level
|
|
183
|
+
"skill": skill["name"],
|
|
184
|
+
"skill_md": skill.get("skill_md", skill.get("location", "")),
|
|
185
|
+
"action": f"Handle independently: aspect of '{query}' related to {', '.join(skill.get('capabilities', []))}",
|
|
186
|
+
"input": "user_query",
|
|
187
|
+
"output": f"{skill['name']}.output",
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
return {
|
|
191
|
+
"pattern": "parallel",
|
|
192
|
+
"description": f"Execute {len(skills)} skills in parallel, each handling their domain.",
|
|
193
|
+
"steps": steps,
|
|
194
|
+
"data_flow": "user_query -> [parallel] -> aggregated_result",
|
|
195
|
+
"aggregation": "Combine results from all skills into a unified response.",
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
elif pattern == "primary_support":
|
|
199
|
+
primary = skills[0] # Highest score
|
|
200
|
+
support = skills[1:]
|
|
201
|
+
|
|
202
|
+
steps = [
|
|
203
|
+
{
|
|
204
|
+
"order": 1,
|
|
205
|
+
"skill": primary["name"],
|
|
206
|
+
"skill_md": primary.get("skill_md", primary.get("location", "")),
|
|
207
|
+
"action": f"Primary: handle main request: {query}",
|
|
208
|
+
"input": "user_query",
|
|
209
|
+
"output": f"{primary['name']}.output",
|
|
210
|
+
"role": "primary",
|
|
211
|
+
}
|
|
212
|
+
]
|
|
213
|
+
|
|
214
|
+
for i, skill in enumerate(support):
|
|
215
|
+
steps.append({
|
|
216
|
+
"order": 2,
|
|
217
|
+
"skill": skill["name"],
|
|
218
|
+
"skill_md": skill.get("skill_md", skill.get("location", "")),
|
|
219
|
+
"action": f"Support: provide {', '.join(skill.get('capabilities', []))} data if needed",
|
|
220
|
+
"input": "user_query",
|
|
221
|
+
"output": f"{skill['name']}.output",
|
|
222
|
+
"role": "support",
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
return {
|
|
226
|
+
"pattern": "primary_support",
|
|
227
|
+
"description": f"Primary: '{primary['name']}'. Support: {', '.join(s['name'] for s in support)}.",
|
|
228
|
+
"steps": steps,
|
|
229
|
+
"data_flow": f"user_query -> {primary['name']} (primary) + support skills as needed -> result",
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return {"pattern": "unknown", "steps": [], "data_flow": ""}
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
# ── CLI Entry Point ────────────────────────────────────────────────────────
|
|
236
|
+
|
|
237
|
+
def main():
|
|
238
|
+
args = sys.argv[1:]
|
|
239
|
+
skill_names = []
|
|
240
|
+
query = ""
|
|
241
|
+
match_result = None
|
|
242
|
+
|
|
243
|
+
i = 0
|
|
244
|
+
while i < len(args):
|
|
245
|
+
if args[i] == "--skills" and i + 1 < len(args):
|
|
246
|
+
skill_names = [s.strip() for s in args[i + 1].split(",")]
|
|
247
|
+
i += 2
|
|
248
|
+
elif args[i] == "--query" and i + 1 < len(args):
|
|
249
|
+
query = args[i + 1]
|
|
250
|
+
i += 2
|
|
251
|
+
elif args[i] == "--match-result" and i + 1 < len(args):
|
|
252
|
+
match_result = json.loads(args[i + 1])
|
|
253
|
+
i += 2
|
|
254
|
+
else:
|
|
255
|
+
# Treat as query if no flag
|
|
256
|
+
query = args[i]
|
|
257
|
+
i += 1
|
|
258
|
+
|
|
259
|
+
# Get skill data from match result or registry
|
|
260
|
+
skills = []
|
|
261
|
+
if match_result:
|
|
262
|
+
skills = match_result.get("skills", [])
|
|
263
|
+
elif skill_names:
|
|
264
|
+
registry = load_registry()
|
|
265
|
+
for name in skill_names:
|
|
266
|
+
if name in registry:
|
|
267
|
+
skill_data = registry[name]
|
|
268
|
+
skill_data["score"] = 10 # default score
|
|
269
|
+
skills.append(skill_data)
|
|
270
|
+
|
|
271
|
+
if not skills:
|
|
272
|
+
print(json.dumps({
|
|
273
|
+
"error": "No skills provided",
|
|
274
|
+
"usage": 'python orchestrate.py --skills skill1,skill2 --query "your query"'
|
|
275
|
+
}, indent=2))
|
|
276
|
+
sys.exit(1)
|
|
277
|
+
|
|
278
|
+
if not query:
|
|
279
|
+
print(json.dumps({
|
|
280
|
+
"error": "No query provided",
|
|
281
|
+
"usage": 'python orchestrate.py --skills skill1,skill2 --query "your query"'
|
|
282
|
+
}, indent=2))
|
|
283
|
+
sys.exit(1)
|
|
284
|
+
|
|
285
|
+
# Classify and generate plan
|
|
286
|
+
pattern = classify_pattern(skills, query)
|
|
287
|
+
plan = generate_plan(skills, query, pattern)
|
|
288
|
+
plan["query"] = query
|
|
289
|
+
plan["skill_count"] = len(skills)
|
|
290
|
+
|
|
291
|
+
# Add instructions for Claude
|
|
292
|
+
plan["instructions"] = []
|
|
293
|
+
for step in plan.get("steps", []):
|
|
294
|
+
skill_md = step.get("skill_md", "")
|
|
295
|
+
if skill_md:
|
|
296
|
+
plan["instructions"].append(
|
|
297
|
+
f"Step {step['order']}: Read {skill_md} and follow its workflow for: {step['action']}"
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
print(json.dumps(plan, indent=2, ensure_ascii=False))
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
if __name__ == "__main__":
|
|
304
|
+
main()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pyyaml>=6.0
|