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,103 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Modelos de dados do Context Agent.
|
|
3
|
+
Dataclasses puras sem dependências externas.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from dataclasses import dataclass, field
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class SessionEntry:
|
|
13
|
+
"""Uma entrada individual do log JSONL do Claude Code."""
|
|
14
|
+
type: str # "user" | "assistant" | "queue-operation"
|
|
15
|
+
timestamp: str # ISO 8601
|
|
16
|
+
session_id: str
|
|
17
|
+
slug: str = ""
|
|
18
|
+
role: str = "" # "user" | "assistant"
|
|
19
|
+
content: str = "" # Texto da mensagem
|
|
20
|
+
tool_calls: list = field(default_factory=list) # [{name, input}]
|
|
21
|
+
token_usage: dict = field(default_factory=dict) # {input, output, cache_read}
|
|
22
|
+
model: str = ""
|
|
23
|
+
files_modified: list = field(default_factory=list)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass
|
|
27
|
+
class PendingTask:
|
|
28
|
+
"""Tarefa pendente identificada em uma sessão."""
|
|
29
|
+
description: str
|
|
30
|
+
priority: str = "medium" # "high" | "medium" | "low"
|
|
31
|
+
source_session: int = 0 # Número da sessão onde foi criada
|
|
32
|
+
created_date: str = ""
|
|
33
|
+
context: str = "" # Contexto adicional sobre a tarefa
|
|
34
|
+
completed: bool = False
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass
|
|
38
|
+
class ProjectInfo:
|
|
39
|
+
"""Informações de um projeto/skill rastreado."""
|
|
40
|
+
name: str
|
|
41
|
+
path: str = ""
|
|
42
|
+
status: str = "active" # "active" | "paused" | "completed"
|
|
43
|
+
last_touched: str = "" # Data da última interação
|
|
44
|
+
last_session: int = 0 # Número da última sessão
|
|
45
|
+
next_actions: list = field(default_factory=list)
|
|
46
|
+
dependencies: list = field(default_factory=list)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass
|
|
50
|
+
class SessionSummary:
|
|
51
|
+
"""Resumo estruturado de uma sessão do Claude Code."""
|
|
52
|
+
session_number: int
|
|
53
|
+
session_id: str = ""
|
|
54
|
+
slug: str = ""
|
|
55
|
+
date: str = "" # YYYY-MM-DD
|
|
56
|
+
start_time: str = "" # HH:MM
|
|
57
|
+
end_time: str = "" # HH:MM
|
|
58
|
+
duration_minutes: int = 0
|
|
59
|
+
model: str = ""
|
|
60
|
+
|
|
61
|
+
# Conteúdo
|
|
62
|
+
topics: list = field(default_factory=list)
|
|
63
|
+
decisions: list = field(default_factory=list)
|
|
64
|
+
tasks_completed: list = field(default_factory=list)
|
|
65
|
+
tasks_pending: list = field(default_factory=list) # list[PendingTask]
|
|
66
|
+
files_modified: list = field(default_factory=list) # list[{path, action}]
|
|
67
|
+
key_findings: list = field(default_factory=list)
|
|
68
|
+
errors_resolved: list = field(default_factory=list) # list[{error, solution}]
|
|
69
|
+
open_questions: list = field(default_factory=list)
|
|
70
|
+
technical_debt: list = field(default_factory=list)
|
|
71
|
+
|
|
72
|
+
# Métricas
|
|
73
|
+
total_input_tokens: int = 0
|
|
74
|
+
total_output_tokens: int = 0
|
|
75
|
+
total_cache_tokens: int = 0
|
|
76
|
+
message_count: int = 0
|
|
77
|
+
tool_call_count: int = 0
|
|
78
|
+
|
|
79
|
+
# Projetos tocados nesta sessão
|
|
80
|
+
projects_touched: list = field(default_factory=list)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@dataclass
|
|
84
|
+
class ActiveContext:
|
|
85
|
+
"""Contexto ativo consolidado de todas as sessões."""
|
|
86
|
+
last_updated: str = ""
|
|
87
|
+
projects: list = field(default_factory=list) # list[ProjectInfo]
|
|
88
|
+
pending_tasks: list = field(default_factory=list) # list[PendingTask]
|
|
89
|
+
recent_decisions: list = field(default_factory=list) # list[{session, text}]
|
|
90
|
+
active_blockers: list = field(default_factory=list)
|
|
91
|
+
conventions: list = field(default_factory=list)
|
|
92
|
+
recent_sessions: list = field(default_factory=list) # list[{number, summary}]
|
|
93
|
+
total_sessions: int = 0
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
@dataclass
|
|
97
|
+
class SearchResult:
|
|
98
|
+
"""Resultado de busca no histórico de sessões."""
|
|
99
|
+
session_number: int
|
|
100
|
+
date: str
|
|
101
|
+
snippet: str
|
|
102
|
+
section: str # Em qual seção foi encontrado
|
|
103
|
+
relevance: float = 0.0
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Registro e tracking de projetos/skills.
|
|
3
|
+
Mantém PROJECT_REGISTRY.md atualizado.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import re
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
from config import (
|
|
11
|
+
PROJECT_REGISTRY_PATH,
|
|
12
|
+
SKILLS_ROOT,
|
|
13
|
+
KNOWN_PROJECTS,
|
|
14
|
+
)
|
|
15
|
+
from models import ProjectInfo
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def load_registry() -> list[ProjectInfo]:
|
|
19
|
+
"""Carrega projetos do PROJECT_REGISTRY.md."""
|
|
20
|
+
if not PROJECT_REGISTRY_PATH.exists():
|
|
21
|
+
return _discover_projects()
|
|
22
|
+
|
|
23
|
+
text = PROJECT_REGISTRY_PATH.read_text(encoding="utf-8")
|
|
24
|
+
projects = []
|
|
25
|
+
in_table = False
|
|
26
|
+
|
|
27
|
+
for line in text.splitlines():
|
|
28
|
+
if line.startswith("|") and "Projeto" in line:
|
|
29
|
+
in_table = True
|
|
30
|
+
continue
|
|
31
|
+
if in_table and line.startswith("|---"):
|
|
32
|
+
continue
|
|
33
|
+
if in_table and line.startswith("|"):
|
|
34
|
+
cells = [c.strip() for c in line.split("|")[1:-1]]
|
|
35
|
+
if len(cells) >= 4:
|
|
36
|
+
projects.append(ProjectInfo(
|
|
37
|
+
name=cells[0],
|
|
38
|
+
path=cells[1] if len(cells) > 4 else "",
|
|
39
|
+
status=cells[2] if len(cells) > 4 else cells[1],
|
|
40
|
+
last_touched=cells[3] if len(cells) > 4 else cells[2],
|
|
41
|
+
last_session=_extract_session_number(cells[-1]) if cells[-1] else 0,
|
|
42
|
+
next_actions=[a.strip() for a in (cells[4] if len(cells) > 4 else cells[3]).split(";") if a.strip()],
|
|
43
|
+
))
|
|
44
|
+
elif in_table and not line.strip():
|
|
45
|
+
in_table = False
|
|
46
|
+
|
|
47
|
+
return projects if projects else _discover_projects()
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _extract_session_number(text: str) -> int:
|
|
51
|
+
"""Extrai número de sessão de texto como 'session-005'."""
|
|
52
|
+
m = re.search(r"session-(\d+)", text)
|
|
53
|
+
return int(m.group(1)) if m else 0
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _discover_projects() -> list[ProjectInfo]:
|
|
57
|
+
"""Auto-detecta projetos a partir da estrutura de diretórios."""
|
|
58
|
+
projects = []
|
|
59
|
+
for name, display_name in KNOWN_PROJECTS.items():
|
|
60
|
+
project_path = SKILLS_ROOT / name
|
|
61
|
+
if project_path.exists() and project_path.is_dir():
|
|
62
|
+
projects.append(ProjectInfo(
|
|
63
|
+
name=display_name,
|
|
64
|
+
path=str(project_path),
|
|
65
|
+
status="active",
|
|
66
|
+
last_touched=datetime.now().strftime("%Y-%m-%d"),
|
|
67
|
+
))
|
|
68
|
+
return projects
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def detect_projects_from_session(files_modified: list[dict], tool_calls: list[dict]) -> list[str]:
|
|
72
|
+
"""Detecta quais projetos foram tocados numa sessão via paths."""
|
|
73
|
+
touched = set()
|
|
74
|
+
|
|
75
|
+
# Verificar arquivos modificados
|
|
76
|
+
all_paths = [f.get("path", "") for f in files_modified]
|
|
77
|
+
|
|
78
|
+
# Verificar tool_calls com file_path
|
|
79
|
+
for tc in tool_calls:
|
|
80
|
+
inp = tc.get("input", {})
|
|
81
|
+
if isinstance(inp, dict):
|
|
82
|
+
fp = inp.get("file_path", "") or inp.get("path", "")
|
|
83
|
+
if fp:
|
|
84
|
+
all_paths.append(fp)
|
|
85
|
+
|
|
86
|
+
skills_root_str = str(SKILLS_ROOT).replace("\\", "/").lower()
|
|
87
|
+
for p in all_paths:
|
|
88
|
+
p_norm = p.replace("\\", "/").lower()
|
|
89
|
+
if skills_root_str in p_norm:
|
|
90
|
+
relative = p_norm.split(skills_root_str)[-1].lstrip("/")
|
|
91
|
+
top_dir = relative.split("/")[0] if "/" in relative else relative
|
|
92
|
+
if top_dir in KNOWN_PROJECTS:
|
|
93
|
+
touched.add(KNOWN_PROJECTS[top_dir])
|
|
94
|
+
|
|
95
|
+
return list(touched)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def update_project(projects: list[ProjectInfo], name: str, **fields) -> list[ProjectInfo]:
|
|
99
|
+
"""Atualiza campos de um projeto existente ou cria novo."""
|
|
100
|
+
for p in projects:
|
|
101
|
+
if p.name == name:
|
|
102
|
+
for k, v in fields.items():
|
|
103
|
+
if hasattr(p, k):
|
|
104
|
+
setattr(p, k, v)
|
|
105
|
+
return projects
|
|
106
|
+
|
|
107
|
+
# Projeto novo
|
|
108
|
+
new_project = ProjectInfo(name=name, **fields)
|
|
109
|
+
projects.append(new_project)
|
|
110
|
+
return projects
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def save_registry(projects: list[ProjectInfo]):
|
|
114
|
+
"""Salva PROJECT_REGISTRY.md."""
|
|
115
|
+
PROJECT_REGISTRY_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
116
|
+
now = datetime.now().strftime("%Y-%m-%d %H:%M")
|
|
117
|
+
|
|
118
|
+
lines = [
|
|
119
|
+
f"# Registro de Projetos — Atualizado em {now}",
|
|
120
|
+
"",
|
|
121
|
+
"| Projeto | Status | Última Interação | Próximas Ações |",
|
|
122
|
+
"|---------|--------|------------------|----------------|",
|
|
123
|
+
]
|
|
124
|
+
for p in projects:
|
|
125
|
+
actions = "; ".join(p.next_actions) if p.next_actions else "—"
|
|
126
|
+
session_ref = f"session-{p.last_session:03d}" if p.last_session else "—"
|
|
127
|
+
lines.append(
|
|
128
|
+
f"| {p.name} | {p.status} | {p.last_touched} ({session_ref}) | {actions} |"
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
lines.append("")
|
|
132
|
+
PROJECT_REGISTRY_PATH.write_text("\n".join(lines), encoding="utf-8")
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Busca full-text via SQLite FTS5 no histórico de sessões.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import sqlite3
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from config import DB_PATH, MAX_SEARCH_RESULTS
|
|
9
|
+
from models import SearchResult
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _get_connection() -> sqlite3.Connection:
|
|
13
|
+
"""Retorna conexão SQLite com FTS5."""
|
|
14
|
+
DB_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
15
|
+
conn = sqlite3.connect(str(DB_PATH))
|
|
16
|
+
conn.execute("PRAGMA journal_mode=WAL")
|
|
17
|
+
return conn
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def init_search_db():
|
|
21
|
+
"""Cria tabela FTS5 se não existir."""
|
|
22
|
+
conn = _get_connection()
|
|
23
|
+
conn.execute("""
|
|
24
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS session_search USING fts5(
|
|
25
|
+
session_number,
|
|
26
|
+
date,
|
|
27
|
+
section,
|
|
28
|
+
content,
|
|
29
|
+
tokenize='unicode61'
|
|
30
|
+
)
|
|
31
|
+
""")
|
|
32
|
+
conn.commit()
|
|
33
|
+
conn.close()
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def index_session(session_number: int, date: str, sections: dict[str, str]):
|
|
37
|
+
"""
|
|
38
|
+
Indexa conteúdo de uma sessão.
|
|
39
|
+
sections: {"topics": "texto", "decisions": "texto", ...}
|
|
40
|
+
"""
|
|
41
|
+
conn = _get_connection()
|
|
42
|
+
# Remove entradas antigas da mesma sessão
|
|
43
|
+
conn.execute(
|
|
44
|
+
"DELETE FROM session_search WHERE session_number = ?",
|
|
45
|
+
(str(session_number),),
|
|
46
|
+
)
|
|
47
|
+
for section_name, content in sections.items():
|
|
48
|
+
if content.strip():
|
|
49
|
+
conn.execute(
|
|
50
|
+
"INSERT INTO session_search (session_number, date, section, content) VALUES (?, ?, ?, ?)",
|
|
51
|
+
(str(session_number), date, section_name, content),
|
|
52
|
+
)
|
|
53
|
+
conn.commit()
|
|
54
|
+
conn.close()
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def search(query: str, limit: int = MAX_SEARCH_RESULTS) -> list[SearchResult]:
|
|
58
|
+
"""Busca full-text no histórico."""
|
|
59
|
+
conn = _get_connection()
|
|
60
|
+
try:
|
|
61
|
+
rows = conn.execute(
|
|
62
|
+
"""
|
|
63
|
+
SELECT session_number, date, section, snippet(session_search, 3, '>>>', '<<<', '...', 40)
|
|
64
|
+
FROM session_search
|
|
65
|
+
WHERE session_search MATCH ?
|
|
66
|
+
ORDER BY rank
|
|
67
|
+
LIMIT ?
|
|
68
|
+
""",
|
|
69
|
+
(query, limit),
|
|
70
|
+
).fetchall()
|
|
71
|
+
except sqlite3.OperationalError:
|
|
72
|
+
# Tabela não existe ou query inválida
|
|
73
|
+
return []
|
|
74
|
+
finally:
|
|
75
|
+
conn.close()
|
|
76
|
+
|
|
77
|
+
results = []
|
|
78
|
+
for row in rows:
|
|
79
|
+
results.append(SearchResult(
|
|
80
|
+
session_number=int(row[0]),
|
|
81
|
+
date=row[1],
|
|
82
|
+
section=row[2],
|
|
83
|
+
snippet=row[3],
|
|
84
|
+
))
|
|
85
|
+
return results
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def reindex_all(sessions_dir: Path):
|
|
89
|
+
"""Reconstrói índice a partir dos arquivos de sessão."""
|
|
90
|
+
conn = _get_connection()
|
|
91
|
+
conn.execute("DELETE FROM session_search")
|
|
92
|
+
conn.commit()
|
|
93
|
+
conn.close()
|
|
94
|
+
|
|
95
|
+
for session_file in sorted(sessions_dir.glob("session-*.md")):
|
|
96
|
+
try:
|
|
97
|
+
num = int(session_file.stem.split("-")[1])
|
|
98
|
+
except (IndexError, ValueError):
|
|
99
|
+
continue
|
|
100
|
+
|
|
101
|
+
text = session_file.read_text(encoding="utf-8")
|
|
102
|
+
date = ""
|
|
103
|
+
sections = {}
|
|
104
|
+
current_section = "general"
|
|
105
|
+
|
|
106
|
+
for line in text.splitlines():
|
|
107
|
+
if line.startswith("# Sessão") and "—" in line:
|
|
108
|
+
date = line.split("—")[-1].strip()
|
|
109
|
+
elif line.startswith("## "):
|
|
110
|
+
current_section = line[3:].strip().lower()
|
|
111
|
+
else:
|
|
112
|
+
sections.setdefault(current_section, "")
|
|
113
|
+
sections[current_section] += line + "\n"
|
|
114
|
+
|
|
115
|
+
index_session(num, date, sections)
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Parser dos logs JSONL do Claude Code.
|
|
3
|
+
Lê arquivos de sessão e extrai informações estruturadas.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import json
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
from typing import Optional
|
|
10
|
+
|
|
11
|
+
from config import CLAUDE_SESSION_DIR, FILE_MODIFYING_TOOLS
|
|
12
|
+
from models import SessionEntry
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def parse_session_file(path: Path) -> list[SessionEntry]:
|
|
16
|
+
"""Lê um arquivo JSONL e retorna lista de SessionEntry."""
|
|
17
|
+
entries = []
|
|
18
|
+
with open(path, "r", encoding="utf-8") as f:
|
|
19
|
+
for line in f:
|
|
20
|
+
line = line.strip()
|
|
21
|
+
if not line:
|
|
22
|
+
continue
|
|
23
|
+
try:
|
|
24
|
+
raw = json.loads(line)
|
|
25
|
+
entry = _parse_raw_entry(raw)
|
|
26
|
+
if entry:
|
|
27
|
+
entries.append(entry)
|
|
28
|
+
except json.JSONDecodeError:
|
|
29
|
+
continue
|
|
30
|
+
return entries
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _parse_raw_entry(raw: dict) -> Optional[SessionEntry]:
|
|
34
|
+
"""Converte um dict JSON bruto em SessionEntry."""
|
|
35
|
+
entry_type = raw.get("type", "")
|
|
36
|
+
|
|
37
|
+
if entry_type == "queue-operation":
|
|
38
|
+
return SessionEntry(
|
|
39
|
+
type="queue",
|
|
40
|
+
timestamp=raw.get("timestamp", ""),
|
|
41
|
+
session_id=raw.get("sessionId", ""),
|
|
42
|
+
content=raw.get("content", ""),
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
if entry_type not in ("user", "assistant"):
|
|
46
|
+
return None
|
|
47
|
+
|
|
48
|
+
msg = raw.get("message", {})
|
|
49
|
+
role = msg.get("role", "")
|
|
50
|
+
slug = raw.get("slug", "")
|
|
51
|
+
session_id = raw.get("sessionId", "")
|
|
52
|
+
timestamp = raw.get("timestamp", "")
|
|
53
|
+
|
|
54
|
+
# Extrair texto e tool_calls do content
|
|
55
|
+
text_parts = []
|
|
56
|
+
tool_calls = []
|
|
57
|
+
files_modified = []
|
|
58
|
+
model = msg.get("model", "")
|
|
59
|
+
|
|
60
|
+
content = msg.get("content", "")
|
|
61
|
+
if isinstance(content, str):
|
|
62
|
+
text_parts.append(content)
|
|
63
|
+
elif isinstance(content, list):
|
|
64
|
+
for block in content:
|
|
65
|
+
if not isinstance(block, dict):
|
|
66
|
+
continue
|
|
67
|
+
block_type = block.get("type", "")
|
|
68
|
+
if block_type == "text":
|
|
69
|
+
text_parts.append(block.get("text", ""))
|
|
70
|
+
elif block_type == "tool_use":
|
|
71
|
+
tool_name = block.get("name", "")
|
|
72
|
+
tool_input = block.get("input", {})
|
|
73
|
+
tool_calls.append({"name": tool_name, "input": tool_input})
|
|
74
|
+
# Detectar arquivos modificados
|
|
75
|
+
if tool_name in FILE_MODIFYING_TOOLS:
|
|
76
|
+
fp = tool_input.get("file_path", "")
|
|
77
|
+
if fp:
|
|
78
|
+
files_modified.append({"path": fp, "action": tool_name.lower()})
|
|
79
|
+
elif block_type == "tool_result":
|
|
80
|
+
# Resultados de ferramentas (em mensagens do user)
|
|
81
|
+
result_content = block.get("content", "")
|
|
82
|
+
if isinstance(result_content, list):
|
|
83
|
+
for rc in result_content:
|
|
84
|
+
if isinstance(rc, dict) and rc.get("type") == "text":
|
|
85
|
+
text_parts.append(rc.get("text", ""))
|
|
86
|
+
elif isinstance(result_content, str):
|
|
87
|
+
text_parts.append(result_content)
|
|
88
|
+
|
|
89
|
+
# Token usage
|
|
90
|
+
usage = msg.get("usage", {})
|
|
91
|
+
token_usage = {}
|
|
92
|
+
if usage:
|
|
93
|
+
token_usage = {
|
|
94
|
+
"input": usage.get("input_tokens", 0),
|
|
95
|
+
"output": usage.get("output_tokens", 0),
|
|
96
|
+
"cache_read": usage.get("cache_read_input_tokens", 0),
|
|
97
|
+
"cache_creation": usage.get("cache_creation_input_tokens", 0),
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return SessionEntry(
|
|
101
|
+
type=entry_type,
|
|
102
|
+
timestamp=timestamp,
|
|
103
|
+
session_id=session_id,
|
|
104
|
+
slug=slug,
|
|
105
|
+
role=role,
|
|
106
|
+
content="\n".join(text_parts),
|
|
107
|
+
tool_calls=tool_calls,
|
|
108
|
+
token_usage=token_usage,
|
|
109
|
+
model=model,
|
|
110
|
+
files_modified=files_modified,
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def extract_user_messages(entries: list[SessionEntry]) -> list[str]:
|
|
115
|
+
"""Extrai apenas o texto das mensagens do usuário."""
|
|
116
|
+
return [e.content for e in entries if e.role == "user" and e.content.strip()]
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def extract_assistant_messages(entries: list[SessionEntry]) -> list[str]:
|
|
120
|
+
"""Extrai apenas o texto das respostas do assistente."""
|
|
121
|
+
return [e.content for e in entries if e.role == "assistant" and e.content.strip()]
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def extract_tool_calls(entries: list[SessionEntry]) -> list[dict]:
|
|
125
|
+
"""Extrai todas as chamadas de ferramentas."""
|
|
126
|
+
calls = []
|
|
127
|
+
for e in entries:
|
|
128
|
+
calls.extend(e.tool_calls)
|
|
129
|
+
return calls
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def extract_files_modified(entries: list[SessionEntry]) -> list[dict]:
|
|
133
|
+
"""Extrai lista de arquivos modificados (sem duplicatas)."""
|
|
134
|
+
seen = set()
|
|
135
|
+
files = []
|
|
136
|
+
for e in entries:
|
|
137
|
+
for f in e.files_modified:
|
|
138
|
+
key = f["path"]
|
|
139
|
+
if key not in seen:
|
|
140
|
+
seen.add(key)
|
|
141
|
+
files.append(f)
|
|
142
|
+
return files
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def get_session_metadata(entries: list[SessionEntry]) -> dict:
|
|
146
|
+
"""Extrai metadados da sessão: slug, timestamps, modelo, tokens."""
|
|
147
|
+
if not entries:
|
|
148
|
+
return {}
|
|
149
|
+
|
|
150
|
+
timestamps = [e.timestamp for e in entries if e.timestamp]
|
|
151
|
+
slugs = [e.slug for e in entries if e.slug]
|
|
152
|
+
models = [e.model for e in entries if e.model]
|
|
153
|
+
|
|
154
|
+
total_input = sum(e.token_usage.get("input", 0) for e in entries)
|
|
155
|
+
total_output = sum(e.token_usage.get("output", 0) for e in entries)
|
|
156
|
+
total_cache = sum(e.token_usage.get("cache_read", 0) for e in entries)
|
|
157
|
+
|
|
158
|
+
user_msgs = [e for e in entries if e.role == "user"]
|
|
159
|
+
assistant_msgs = [e for e in entries if e.role == "assistant"]
|
|
160
|
+
|
|
161
|
+
# Calcular duração
|
|
162
|
+
duration_minutes = 0
|
|
163
|
+
if len(timestamps) >= 2:
|
|
164
|
+
try:
|
|
165
|
+
t_start = datetime.fromisoformat(timestamps[0].replace("Z", "+00:00"))
|
|
166
|
+
t_end = datetime.fromisoformat(timestamps[-1].replace("Z", "+00:00"))
|
|
167
|
+
duration_minutes = int((t_end - t_start).total_seconds() / 60)
|
|
168
|
+
except (ValueError, IndexError):
|
|
169
|
+
pass
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
"slug": slugs[0] if slugs else "",
|
|
173
|
+
"session_id": entries[0].session_id if entries else "",
|
|
174
|
+
"start_time": timestamps[0] if timestamps else "",
|
|
175
|
+
"end_time": timestamps[-1] if timestamps else "",
|
|
176
|
+
"duration_minutes": duration_minutes,
|
|
177
|
+
"model": models[0] if models else "",
|
|
178
|
+
"total_input_tokens": total_input,
|
|
179
|
+
"total_output_tokens": total_output,
|
|
180
|
+
"total_cache_tokens": total_cache,
|
|
181
|
+
"message_count": len(user_msgs) + len(assistant_msgs),
|
|
182
|
+
"tool_call_count": sum(len(e.tool_calls) for e in entries),
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def get_latest_session_file() -> Optional[Path]:
|
|
187
|
+
"""Encontra o arquivo JSONL mais recente."""
|
|
188
|
+
if not CLAUDE_SESSION_DIR.exists():
|
|
189
|
+
return None
|
|
190
|
+
jsonl_files = sorted(
|
|
191
|
+
CLAUDE_SESSION_DIR.glob("*.jsonl"),
|
|
192
|
+
key=lambda p: p.stat().st_mtime,
|
|
193
|
+
reverse=True,
|
|
194
|
+
)
|
|
195
|
+
return jsonl_files[0] if jsonl_files else None
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def get_all_session_files() -> list[Path]:
|
|
199
|
+
"""Retorna todos os arquivos JSONL ordenados por data de modificação."""
|
|
200
|
+
if not CLAUDE_SESSION_DIR.exists():
|
|
201
|
+
return []
|
|
202
|
+
return sorted(
|
|
203
|
+
CLAUDE_SESSION_DIR.glob("*.jsonl"),
|
|
204
|
+
key=lambda p: p.stat().st_mtime,
|
|
205
|
+
reverse=True,
|
|
206
|
+
)
|