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,255 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Browser Session Management for NotebookLM
|
|
4
|
+
Individual browser session for persistent NotebookLM conversations
|
|
5
|
+
Based on the original NotebookLM API implementation
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import time
|
|
9
|
+
import sys
|
|
10
|
+
from typing import Any, Dict, Optional
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
from patchright.sync_api import BrowserContext, Page
|
|
14
|
+
|
|
15
|
+
# Add parent directory to path
|
|
16
|
+
sys.path.insert(0, str(Path(__file__).parent))
|
|
17
|
+
|
|
18
|
+
from browser_utils import StealthUtils
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class BrowserSession:
|
|
22
|
+
"""
|
|
23
|
+
Represents a single persistent browser session for NotebookLM
|
|
24
|
+
|
|
25
|
+
Each session gets its own Page (tab) within a shared BrowserContext,
|
|
26
|
+
allowing for contextual conversations where NotebookLM remembers
|
|
27
|
+
previous messages.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def __init__(self, session_id: str, context: BrowserContext, notebook_url: str):
|
|
31
|
+
"""
|
|
32
|
+
Initialize a new browser session
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
session_id: Unique identifier for this session
|
|
36
|
+
context: Browser context (shared or dedicated)
|
|
37
|
+
notebook_url: Target NotebookLM URL for this session
|
|
38
|
+
"""
|
|
39
|
+
self.id = session_id
|
|
40
|
+
self.created_at = time.time()
|
|
41
|
+
self.last_activity = time.time()
|
|
42
|
+
self.message_count = 0
|
|
43
|
+
self.notebook_url = notebook_url
|
|
44
|
+
self.context = context
|
|
45
|
+
self.page = None
|
|
46
|
+
self.stealth = StealthUtils()
|
|
47
|
+
|
|
48
|
+
# Initialize the session
|
|
49
|
+
self._initialize()
|
|
50
|
+
|
|
51
|
+
def _initialize(self):
|
|
52
|
+
"""Initialize the browser session and navigate to NotebookLM"""
|
|
53
|
+
print(f"🚀 Creating session {self.id}...")
|
|
54
|
+
|
|
55
|
+
# Create new page (tab) in context
|
|
56
|
+
self.page = self.context.new_page()
|
|
57
|
+
print(f" 🌐 Navigating to NotebookLM...")
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
# Navigate to notebook
|
|
61
|
+
self.page.goto(self.notebook_url, wait_until="domcontentloaded", timeout=30000)
|
|
62
|
+
|
|
63
|
+
# Check if login is needed
|
|
64
|
+
if "accounts.google.com" in self.page.url:
|
|
65
|
+
raise RuntimeError("Authentication required. Please run auth_manager.py setup first.")
|
|
66
|
+
|
|
67
|
+
# Wait for page to be ready
|
|
68
|
+
self._wait_for_ready()
|
|
69
|
+
|
|
70
|
+
# Simulate human inspection
|
|
71
|
+
self.stealth.random_mouse_movement(self.page)
|
|
72
|
+
self.stealth.random_delay(300, 600)
|
|
73
|
+
|
|
74
|
+
print(f"✅ Session {self.id} ready!")
|
|
75
|
+
|
|
76
|
+
except Exception as e:
|
|
77
|
+
print(f"❌ Failed to initialize session: {e}")
|
|
78
|
+
if self.page:
|
|
79
|
+
self.page.close()
|
|
80
|
+
raise
|
|
81
|
+
|
|
82
|
+
def _wait_for_ready(self):
|
|
83
|
+
"""Wait for NotebookLM page to be ready"""
|
|
84
|
+
try:
|
|
85
|
+
# Wait for chat input
|
|
86
|
+
self.page.wait_for_selector("textarea.query-box-input", timeout=10000, state="visible")
|
|
87
|
+
except Exception:
|
|
88
|
+
# Try alternative selector
|
|
89
|
+
self.page.wait_for_selector('textarea[aria-label="Feld für Anfragen"]', timeout=5000, state="visible")
|
|
90
|
+
|
|
91
|
+
def ask(self, question: str) -> Dict[str, Any]:
|
|
92
|
+
"""
|
|
93
|
+
Ask a question in this session
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
question: The question to ask
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
Dict with status, question, answer, session_id
|
|
100
|
+
"""
|
|
101
|
+
try:
|
|
102
|
+
self.last_activity = time.time()
|
|
103
|
+
self.message_count += 1
|
|
104
|
+
|
|
105
|
+
print(f"💬 [{self.id}] Asking: {question}")
|
|
106
|
+
|
|
107
|
+
# Snapshot current answer to detect new response
|
|
108
|
+
previous_answer = self._snapshot_latest_response()
|
|
109
|
+
|
|
110
|
+
# Find chat input
|
|
111
|
+
chat_input_selector = "textarea.query-box-input"
|
|
112
|
+
try:
|
|
113
|
+
self.page.wait_for_selector(chat_input_selector, timeout=5000, state="visible")
|
|
114
|
+
except Exception:
|
|
115
|
+
chat_input_selector = 'textarea[aria-label="Feld für Anfragen"]'
|
|
116
|
+
self.page.wait_for_selector(chat_input_selector, timeout=5000, state="visible")
|
|
117
|
+
|
|
118
|
+
# Click and type with human-like behavior
|
|
119
|
+
self.stealth.realistic_click(self.page, chat_input_selector)
|
|
120
|
+
self.stealth.human_type(self.page, chat_input_selector, question)
|
|
121
|
+
|
|
122
|
+
# Small pause before submit
|
|
123
|
+
self.stealth.random_delay(300, 800)
|
|
124
|
+
|
|
125
|
+
# Submit
|
|
126
|
+
self.page.keyboard.press("Enter")
|
|
127
|
+
|
|
128
|
+
# Wait for response
|
|
129
|
+
print(" ⏳ Waiting for response...")
|
|
130
|
+
self.stealth.random_delay(1500, 3000)
|
|
131
|
+
|
|
132
|
+
# Get new answer
|
|
133
|
+
answer = self._wait_for_latest_answer(previous_answer)
|
|
134
|
+
|
|
135
|
+
if not answer:
|
|
136
|
+
raise Exception("Empty response from NotebookLM")
|
|
137
|
+
|
|
138
|
+
print(f" ✅ Got response ({len(answer)} chars)")
|
|
139
|
+
|
|
140
|
+
return {
|
|
141
|
+
"status": "success",
|
|
142
|
+
"question": question,
|
|
143
|
+
"answer": answer,
|
|
144
|
+
"session_id": self.id,
|
|
145
|
+
"notebook_url": self.notebook_url
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
except Exception as e:
|
|
149
|
+
print(f" ❌ Error: {e}")
|
|
150
|
+
return {
|
|
151
|
+
"status": "error",
|
|
152
|
+
"question": question,
|
|
153
|
+
"error": str(e),
|
|
154
|
+
"session_id": self.id
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
def _snapshot_latest_response(self) -> Optional[str]:
|
|
158
|
+
"""Get the current latest response text"""
|
|
159
|
+
try:
|
|
160
|
+
# Use correct NotebookLM selector
|
|
161
|
+
responses = self.page.query_selector_all(".to-user-container .message-text-content")
|
|
162
|
+
if responses:
|
|
163
|
+
return responses[-1].inner_text()
|
|
164
|
+
except Exception:
|
|
165
|
+
pass
|
|
166
|
+
return None
|
|
167
|
+
|
|
168
|
+
def _wait_for_latest_answer(self, previous_answer: Optional[str], timeout: int = 120) -> str:
|
|
169
|
+
"""Wait for and extract the new answer"""
|
|
170
|
+
start_time = time.time()
|
|
171
|
+
last_candidate = None
|
|
172
|
+
stable_count = 0
|
|
173
|
+
|
|
174
|
+
while time.time() - start_time < timeout:
|
|
175
|
+
# Check if NotebookLM is still thinking (most reliable indicator)
|
|
176
|
+
try:
|
|
177
|
+
thinking_element = self.page.query_selector('div.thinking-message')
|
|
178
|
+
if thinking_element and thinking_element.is_visible():
|
|
179
|
+
time.sleep(0.5)
|
|
180
|
+
continue
|
|
181
|
+
except Exception:
|
|
182
|
+
pass
|
|
183
|
+
|
|
184
|
+
try:
|
|
185
|
+
# Use correct NotebookLM selector
|
|
186
|
+
responses = self.page.query_selector_all(".to-user-container .message-text-content")
|
|
187
|
+
|
|
188
|
+
if responses:
|
|
189
|
+
latest_text = responses[-1].inner_text().strip()
|
|
190
|
+
|
|
191
|
+
# Check if it's a new response
|
|
192
|
+
if latest_text and latest_text != previous_answer:
|
|
193
|
+
# Check if text is stable (3 consecutive polls)
|
|
194
|
+
if latest_text == last_candidate:
|
|
195
|
+
stable_count += 1
|
|
196
|
+
if stable_count >= 3:
|
|
197
|
+
return latest_text
|
|
198
|
+
else:
|
|
199
|
+
stable_count = 1
|
|
200
|
+
last_candidate = latest_text
|
|
201
|
+
|
|
202
|
+
except Exception:
|
|
203
|
+
pass
|
|
204
|
+
|
|
205
|
+
time.sleep(0.5)
|
|
206
|
+
|
|
207
|
+
raise TimeoutError(f"No response received within {timeout} seconds")
|
|
208
|
+
|
|
209
|
+
def reset(self):
|
|
210
|
+
"""Reset the chat by reloading the page"""
|
|
211
|
+
print(f"🔄 Resetting session {self.id}...")
|
|
212
|
+
|
|
213
|
+
self.page.reload(wait_until="domcontentloaded")
|
|
214
|
+
self._wait_for_ready()
|
|
215
|
+
|
|
216
|
+
previous_count = self.message_count
|
|
217
|
+
self.message_count = 0
|
|
218
|
+
self.last_activity = time.time()
|
|
219
|
+
|
|
220
|
+
print(f"✅ Session reset (cleared {previous_count} messages)")
|
|
221
|
+
return previous_count
|
|
222
|
+
|
|
223
|
+
def close(self):
|
|
224
|
+
"""Close this session and clean up resources"""
|
|
225
|
+
print(f"🛑 Closing session {self.id}...")
|
|
226
|
+
|
|
227
|
+
if self.page:
|
|
228
|
+
try:
|
|
229
|
+
self.page.close()
|
|
230
|
+
except Exception as e:
|
|
231
|
+
print(f" ⚠️ Error closing page: {e}")
|
|
232
|
+
|
|
233
|
+
print(f"✅ Session {self.id} closed")
|
|
234
|
+
|
|
235
|
+
def get_info(self) -> Dict[str, Any]:
|
|
236
|
+
"""Get information about this session"""
|
|
237
|
+
return {
|
|
238
|
+
"id": self.id,
|
|
239
|
+
"created_at": self.created_at,
|
|
240
|
+
"last_activity": self.last_activity,
|
|
241
|
+
"age_seconds": time.time() - self.created_at,
|
|
242
|
+
"inactive_seconds": time.time() - self.last_activity,
|
|
243
|
+
"message_count": self.message_count,
|
|
244
|
+
"notebook_url": self.notebook_url
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
def is_expired(self, timeout_seconds: int = 900) -> bool:
|
|
248
|
+
"""Check if session has expired (default: 15 minutes)"""
|
|
249
|
+
return (time.time() - self.last_activity) > timeout_seconds
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
if __name__ == "__main__":
|
|
253
|
+
# Example usage
|
|
254
|
+
print("Browser Session Module - Use ask_question.py for main interface")
|
|
255
|
+
print("This module provides low-level browser session management.")
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Browser Utilities for NotebookLM Skill
|
|
3
|
+
Handles browser launching, stealth features, and common interactions
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import json
|
|
7
|
+
import time
|
|
8
|
+
import random
|
|
9
|
+
from typing import Optional, List
|
|
10
|
+
|
|
11
|
+
from patchright.sync_api import Playwright, BrowserContext, Page
|
|
12
|
+
from config import BROWSER_PROFILE_DIR, STATE_FILE, BROWSER_ARGS, USER_AGENT
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class BrowserFactory:
|
|
16
|
+
"""Factory for creating configured browser contexts"""
|
|
17
|
+
|
|
18
|
+
@staticmethod
|
|
19
|
+
def launch_persistent_context(
|
|
20
|
+
playwright: Playwright,
|
|
21
|
+
headless: bool = True,
|
|
22
|
+
user_data_dir: str = str(BROWSER_PROFILE_DIR)
|
|
23
|
+
) -> BrowserContext:
|
|
24
|
+
"""
|
|
25
|
+
Launch a persistent browser context with anti-detection features
|
|
26
|
+
and cookie workaround.
|
|
27
|
+
"""
|
|
28
|
+
# Launch persistent context
|
|
29
|
+
context = playwright.chromium.launch_persistent_context(
|
|
30
|
+
user_data_dir=user_data_dir,
|
|
31
|
+
channel="chrome", # Use real Chrome
|
|
32
|
+
headless=headless,
|
|
33
|
+
no_viewport=True,
|
|
34
|
+
ignore_default_args=["--enable-automation"],
|
|
35
|
+
user_agent=USER_AGENT,
|
|
36
|
+
args=BROWSER_ARGS
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
# Cookie Workaround for Playwright bug #36139
|
|
40
|
+
# Session cookies (expires=-1) don't persist in user_data_dir automatically
|
|
41
|
+
BrowserFactory._inject_cookies(context)
|
|
42
|
+
|
|
43
|
+
return context
|
|
44
|
+
|
|
45
|
+
@staticmethod
|
|
46
|
+
def _inject_cookies(context: BrowserContext):
|
|
47
|
+
"""Inject cookies from state.json if available"""
|
|
48
|
+
if STATE_FILE.exists():
|
|
49
|
+
try:
|
|
50
|
+
with open(STATE_FILE, 'r') as f:
|
|
51
|
+
state = json.load(f)
|
|
52
|
+
if 'cookies' in state and len(state['cookies']) > 0:
|
|
53
|
+
context.add_cookies(state['cookies'])
|
|
54
|
+
# print(f" 🔧 Injected {len(state['cookies'])} cookies from state.json")
|
|
55
|
+
except Exception as e:
|
|
56
|
+
print(f" ⚠️ Could not load state.json: {e}")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class StealthUtils:
|
|
60
|
+
"""Human-like interaction utilities"""
|
|
61
|
+
|
|
62
|
+
@staticmethod
|
|
63
|
+
def random_delay(min_ms: int = 100, max_ms: int = 500):
|
|
64
|
+
"""Add random delay"""
|
|
65
|
+
time.sleep(random.uniform(min_ms / 1000, max_ms / 1000))
|
|
66
|
+
|
|
67
|
+
@staticmethod
|
|
68
|
+
def human_type(page: Page, selector: str, text: str, wpm_min: int = 320, wpm_max: int = 480):
|
|
69
|
+
"""Type with human-like speed"""
|
|
70
|
+
element = page.query_selector(selector)
|
|
71
|
+
if not element:
|
|
72
|
+
# Try waiting if not immediately found
|
|
73
|
+
try:
|
|
74
|
+
element = page.wait_for_selector(selector, timeout=2000)
|
|
75
|
+
except:
|
|
76
|
+
pass
|
|
77
|
+
|
|
78
|
+
if not element:
|
|
79
|
+
print(f"⚠️ Element not found for typing: {selector}")
|
|
80
|
+
return
|
|
81
|
+
|
|
82
|
+
# Click to focus
|
|
83
|
+
element.click()
|
|
84
|
+
|
|
85
|
+
# Type
|
|
86
|
+
for char in text:
|
|
87
|
+
element.type(char, delay=random.uniform(25, 75))
|
|
88
|
+
if random.random() < 0.05:
|
|
89
|
+
time.sleep(random.uniform(0.15, 0.4))
|
|
90
|
+
|
|
91
|
+
@staticmethod
|
|
92
|
+
def realistic_click(page: Page, selector: str):
|
|
93
|
+
"""Click with realistic movement"""
|
|
94
|
+
element = page.query_selector(selector)
|
|
95
|
+
if not element:
|
|
96
|
+
return
|
|
97
|
+
|
|
98
|
+
# Optional: Move mouse to element (simplified)
|
|
99
|
+
box = element.bounding_box()
|
|
100
|
+
if box:
|
|
101
|
+
x = box['x'] + box['width'] / 2
|
|
102
|
+
y = box['y'] + box['height'] / 2
|
|
103
|
+
page.mouse.move(x, y, steps=5)
|
|
104
|
+
|
|
105
|
+
StealthUtils.random_delay(100, 300)
|
|
106
|
+
element.click()
|
|
107
|
+
StealthUtils.random_delay(100, 300)
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Cleanup Manager for NotebookLM Skill
|
|
4
|
+
Manages cleanup of skill data and browser state
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import shutil
|
|
8
|
+
import argparse
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Dict, List, Any
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class CleanupManager:
|
|
14
|
+
"""
|
|
15
|
+
Manages cleanup of NotebookLM skill data
|
|
16
|
+
|
|
17
|
+
Features:
|
|
18
|
+
- Preview what will be deleted
|
|
19
|
+
- Selective cleanup options
|
|
20
|
+
- Library preservation
|
|
21
|
+
- Safe deletion with confirmation
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def __init__(self):
|
|
25
|
+
"""Initialize the cleanup manager"""
|
|
26
|
+
# Skill directory paths
|
|
27
|
+
self.skill_dir = Path(__file__).parent.parent
|
|
28
|
+
self.data_dir = self.skill_dir / "data"
|
|
29
|
+
|
|
30
|
+
def get_cleanup_paths(self, preserve_library: bool = False) -> Dict[str, Any]:
|
|
31
|
+
"""
|
|
32
|
+
Get paths that would be cleaned up
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
preserve_library: Keep library.json if True
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
Dict with paths and sizes
|
|
39
|
+
|
|
40
|
+
Note: .venv is NEVER deleted - it's part of the skill infrastructure
|
|
41
|
+
"""
|
|
42
|
+
paths = {
|
|
43
|
+
'browser_state': [],
|
|
44
|
+
'sessions': [],
|
|
45
|
+
'library': [],
|
|
46
|
+
'auth': [],
|
|
47
|
+
'other': []
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
total_size = 0
|
|
51
|
+
|
|
52
|
+
if self.data_dir.exists():
|
|
53
|
+
# Browser state
|
|
54
|
+
browser_state_dir = self.data_dir / "browser_state"
|
|
55
|
+
if browser_state_dir.exists():
|
|
56
|
+
for item in browser_state_dir.iterdir():
|
|
57
|
+
size = self._get_size(item)
|
|
58
|
+
paths['browser_state'].append({
|
|
59
|
+
'path': str(item),
|
|
60
|
+
'size': size,
|
|
61
|
+
'type': 'dir' if item.is_dir() else 'file'
|
|
62
|
+
})
|
|
63
|
+
total_size += size
|
|
64
|
+
|
|
65
|
+
# Sessions
|
|
66
|
+
sessions_file = self.data_dir / "sessions.json"
|
|
67
|
+
if sessions_file.exists():
|
|
68
|
+
size = sessions_file.stat().st_size
|
|
69
|
+
paths['sessions'].append({
|
|
70
|
+
'path': str(sessions_file),
|
|
71
|
+
'size': size,
|
|
72
|
+
'type': 'file'
|
|
73
|
+
})
|
|
74
|
+
total_size += size
|
|
75
|
+
|
|
76
|
+
# Library (unless preserved)
|
|
77
|
+
if not preserve_library:
|
|
78
|
+
library_file = self.data_dir / "library.json"
|
|
79
|
+
if library_file.exists():
|
|
80
|
+
size = library_file.stat().st_size
|
|
81
|
+
paths['library'].append({
|
|
82
|
+
'path': str(library_file),
|
|
83
|
+
'size': size,
|
|
84
|
+
'type': 'file'
|
|
85
|
+
})
|
|
86
|
+
total_size += size
|
|
87
|
+
|
|
88
|
+
# Auth info
|
|
89
|
+
auth_info = self.data_dir / "auth_info.json"
|
|
90
|
+
if auth_info.exists():
|
|
91
|
+
size = auth_info.stat().st_size
|
|
92
|
+
paths['auth'].append({
|
|
93
|
+
'path': str(auth_info),
|
|
94
|
+
'size': size,
|
|
95
|
+
'type': 'file'
|
|
96
|
+
})
|
|
97
|
+
total_size += size
|
|
98
|
+
|
|
99
|
+
# Other files in data dir (but NEVER .venv!)
|
|
100
|
+
for item in self.data_dir.iterdir():
|
|
101
|
+
if item.name not in ['browser_state', 'sessions.json', 'library.json', 'auth_info.json']:
|
|
102
|
+
size = self._get_size(item)
|
|
103
|
+
paths['other'].append({
|
|
104
|
+
'path': str(item),
|
|
105
|
+
'size': size,
|
|
106
|
+
'type': 'dir' if item.is_dir() else 'file'
|
|
107
|
+
})
|
|
108
|
+
total_size += size
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
'categories': paths,
|
|
112
|
+
'total_size': total_size,
|
|
113
|
+
'total_items': sum(len(items) for items in paths.values())
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
def _get_size(self, path: Path) -> int:
|
|
117
|
+
"""Get size of file or directory in bytes"""
|
|
118
|
+
if path.is_file():
|
|
119
|
+
return path.stat().st_size
|
|
120
|
+
elif path.is_dir():
|
|
121
|
+
total = 0
|
|
122
|
+
try:
|
|
123
|
+
for item in path.rglob('*'):
|
|
124
|
+
if item.is_file():
|
|
125
|
+
total += item.stat().st_size
|
|
126
|
+
except Exception:
|
|
127
|
+
pass
|
|
128
|
+
return total
|
|
129
|
+
return 0
|
|
130
|
+
|
|
131
|
+
def _format_size(self, size: int) -> str:
|
|
132
|
+
"""Format size in human-readable form"""
|
|
133
|
+
for unit in ['B', 'KB', 'MB', 'GB']:
|
|
134
|
+
if size < 1024:
|
|
135
|
+
return f"{size:.1f} {unit}"
|
|
136
|
+
size /= 1024
|
|
137
|
+
return f"{size:.1f} TB"
|
|
138
|
+
|
|
139
|
+
def perform_cleanup(
|
|
140
|
+
self,
|
|
141
|
+
preserve_library: bool = False,
|
|
142
|
+
dry_run: bool = False
|
|
143
|
+
) -> Dict[str, Any]:
|
|
144
|
+
"""
|
|
145
|
+
Perform the actual cleanup
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
preserve_library: Keep library.json if True
|
|
149
|
+
dry_run: Preview only, don't delete
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
Dict with cleanup results
|
|
153
|
+
"""
|
|
154
|
+
cleanup_data = self.get_cleanup_paths(preserve_library)
|
|
155
|
+
deleted_items = []
|
|
156
|
+
failed_items = []
|
|
157
|
+
deleted_size = 0
|
|
158
|
+
|
|
159
|
+
if dry_run:
|
|
160
|
+
return {
|
|
161
|
+
'dry_run': True,
|
|
162
|
+
'would_delete': cleanup_data['total_items'],
|
|
163
|
+
'would_free': cleanup_data['total_size']
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
# Perform deletion
|
|
167
|
+
for category, items in cleanup_data['categories'].items():
|
|
168
|
+
for item_info in items:
|
|
169
|
+
path = Path(item_info['path'])
|
|
170
|
+
try:
|
|
171
|
+
if path.exists():
|
|
172
|
+
if path.is_dir():
|
|
173
|
+
shutil.rmtree(path)
|
|
174
|
+
else:
|
|
175
|
+
path.unlink()
|
|
176
|
+
deleted_items.append(str(path))
|
|
177
|
+
deleted_size += item_info['size']
|
|
178
|
+
print(f" ✅ Deleted: {path.name}")
|
|
179
|
+
except Exception as e:
|
|
180
|
+
failed_items.append({
|
|
181
|
+
'path': str(path),
|
|
182
|
+
'error': str(e)
|
|
183
|
+
})
|
|
184
|
+
print(f" ❌ Failed: {path.name} ({e})")
|
|
185
|
+
|
|
186
|
+
# Recreate browser_state dir if everything was deleted
|
|
187
|
+
if not preserve_library and not failed_items:
|
|
188
|
+
browser_state_dir = self.data_dir / "browser_state"
|
|
189
|
+
browser_state_dir.mkdir(parents=True, exist_ok=True)
|
|
190
|
+
|
|
191
|
+
return {
|
|
192
|
+
'deleted_items': deleted_items,
|
|
193
|
+
'failed_items': failed_items,
|
|
194
|
+
'deleted_size': deleted_size,
|
|
195
|
+
'deleted_count': len(deleted_items),
|
|
196
|
+
'failed_count': len(failed_items)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
def print_cleanup_preview(self, preserve_library: bool = False):
|
|
200
|
+
"""Print a preview of what will be cleaned"""
|
|
201
|
+
data = self.get_cleanup_paths(preserve_library)
|
|
202
|
+
|
|
203
|
+
print("\n🔍 Cleanup Preview")
|
|
204
|
+
print("=" * 60)
|
|
205
|
+
|
|
206
|
+
for category, items in data['categories'].items():
|
|
207
|
+
if items:
|
|
208
|
+
print(f"\n📁 {category.replace('_', ' ').title()}:")
|
|
209
|
+
for item in items:
|
|
210
|
+
path = Path(item['path'])
|
|
211
|
+
size_str = self._format_size(item['size'])
|
|
212
|
+
type_icon = "📂" if item['type'] == 'dir' else "📄"
|
|
213
|
+
print(f" {type_icon} {path.name:<30} {size_str:>10}")
|
|
214
|
+
|
|
215
|
+
print("\n" + "=" * 60)
|
|
216
|
+
print(f"Total items: {data['total_items']}")
|
|
217
|
+
print(f"Total size: {self._format_size(data['total_size'])}")
|
|
218
|
+
|
|
219
|
+
if preserve_library:
|
|
220
|
+
print("\n📚 Library will be preserved")
|
|
221
|
+
|
|
222
|
+
print("\nThis preview shows what would be deleted.")
|
|
223
|
+
print("Use --confirm to actually perform the cleanup.")
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def main():
|
|
227
|
+
"""Command-line interface for cleanup management"""
|
|
228
|
+
parser = argparse.ArgumentParser(
|
|
229
|
+
description='Clean up NotebookLM skill data',
|
|
230
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
231
|
+
epilog="""
|
|
232
|
+
Examples:
|
|
233
|
+
# Preview what will be deleted
|
|
234
|
+
python cleanup_manager.py
|
|
235
|
+
|
|
236
|
+
# Perform cleanup (delete everything)
|
|
237
|
+
python cleanup_manager.py --confirm
|
|
238
|
+
|
|
239
|
+
# Cleanup but keep library
|
|
240
|
+
python cleanup_manager.py --confirm --preserve-library
|
|
241
|
+
|
|
242
|
+
# Force cleanup without preview
|
|
243
|
+
python cleanup_manager.py --confirm --force
|
|
244
|
+
"""
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
parser.add_argument(
|
|
248
|
+
'--confirm',
|
|
249
|
+
action='store_true',
|
|
250
|
+
help='Actually perform the cleanup (without this, only preview)'
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
parser.add_argument(
|
|
254
|
+
'--preserve-library',
|
|
255
|
+
action='store_true',
|
|
256
|
+
help='Keep the notebook library (library.json)'
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
parser.add_argument(
|
|
260
|
+
'--force',
|
|
261
|
+
action='store_true',
|
|
262
|
+
help='Skip confirmation prompt'
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
args = parser.parse_args()
|
|
266
|
+
|
|
267
|
+
# Initialize manager
|
|
268
|
+
manager = CleanupManager()
|
|
269
|
+
|
|
270
|
+
if args.confirm:
|
|
271
|
+
# Show preview first unless forced
|
|
272
|
+
if not args.force:
|
|
273
|
+
manager.print_cleanup_preview(args.preserve_library)
|
|
274
|
+
|
|
275
|
+
print("\n⚠️ WARNING: This will delete the files shown above!")
|
|
276
|
+
print(" Note: .venv is preserved (part of skill infrastructure)")
|
|
277
|
+
response = input("Are you sure? (yes/no): ")
|
|
278
|
+
|
|
279
|
+
if response.lower() != 'yes':
|
|
280
|
+
print("Cleanup cancelled.")
|
|
281
|
+
return
|
|
282
|
+
|
|
283
|
+
# Perform cleanup
|
|
284
|
+
print("\n🗑️ Performing cleanup...")
|
|
285
|
+
result = manager.perform_cleanup(args.preserve_library, dry_run=False)
|
|
286
|
+
|
|
287
|
+
print(f"\n✅ Cleanup complete!")
|
|
288
|
+
print(f" Deleted: {result['deleted_count']} items")
|
|
289
|
+
print(f" Freed: {manager._format_size(result['deleted_size'])}")
|
|
290
|
+
|
|
291
|
+
if result['failed_count'] > 0:
|
|
292
|
+
print(f" ⚠️ Failed: {result['failed_count']} items")
|
|
293
|
+
|
|
294
|
+
else:
|
|
295
|
+
# Just show preview
|
|
296
|
+
manager.print_cleanup_preview(args.preserve_library)
|
|
297
|
+
print("\n💡 Note: Virtual environment (.venv) is never deleted")
|
|
298
|
+
print(" It's part of the skill infrastructure, not user data")
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
if __name__ == "__main__":
|
|
302
|
+
main()
|