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.
Files changed (368) hide show
  1. package/package.json +1 -1
  2. package/templates/.agents/agents/backend-specialist.md +263 -0
  3. package/templates/.agents/agents/code-archaeologist.md +106 -0
  4. package/templates/.agents/agents/database-architect.md +226 -0
  5. package/templates/.agents/agents/debugger.md +225 -0
  6. package/templates/.agents/agents/devops-engineer.md +242 -0
  7. package/templates/.agents/agents/documentation-writer.md +104 -0
  8. package/templates/.agents/agents/explorer-agent.md +73 -0
  9. package/templates/.agents/agents/frontend-specialist.md +593 -0
  10. package/templates/.agents/agents/game-developer.md +162 -0
  11. package/templates/.agents/agents/mobile-developer.md +377 -0
  12. package/templates/.agents/agents/orchestrator.md +416 -0
  13. package/templates/.agents/agents/penetration-tester.md +188 -0
  14. package/templates/.agents/agents/performance-optimizer.md +187 -0
  15. package/templates/.agents/agents/product-manager.md +112 -0
  16. package/templates/.agents/agents/product-owner.md +95 -0
  17. package/templates/.agents/agents/project-planner.md +406 -0
  18. package/templates/.agents/agents/qa-automation-engineer.md +103 -0
  19. package/templates/.agents/agents/security-auditor.md +170 -0
  20. package/templates/.agents/agents/seo-specialist.md +111 -0
  21. package/templates/.agents/agents/test-engineer.md +158 -0
  22. package/templates/.agents/rules/GEMINI.md +219 -0
  23. package/templates/.agents/scripts/auto_preview.py +148 -0
  24. package/templates/.agents/scripts/checklist.py +217 -0
  25. package/templates/.agents/scripts/session_manager.py +120 -0
  26. package/templates/.agents/scripts/verify_all.py +327 -0
  27. package/templates/.agents/workflows/brainstorm.md +113 -0
  28. package/templates/.agents/workflows/create.md +59 -0
  29. package/templates/.agents/workflows/debug.md +103 -0
  30. package/templates/.agents/workflows/deploy.md +176 -0
  31. package/templates/.agents/workflows/enhance.md +63 -0
  32. package/templates/.agents/workflows/orchestrate.md +237 -0
  33. package/templates/.agents/workflows/plan.md +89 -0
  34. package/templates/.agents/workflows/preview.md +81 -0
  35. package/templates/.agents/workflows/setup-brain.md +39 -0
  36. package/templates/.agents/workflows/status.md +86 -0
  37. package/templates/.agents/workflows/test.md +144 -0
  38. package/templates/.agents/workflows/ui-ux-pro-max.md +296 -0
  39. package/templates/skills_normal/api-patterns/scripts/api_validator.py +211 -0
  40. package/templates/skills_normal/database-design/scripts/schema_validator.py +172 -0
  41. package/templates/skills_normal/frontend-design/scripts/accessibility_checker.py +183 -0
  42. package/templates/skills_normal/frontend-design/scripts/ux_audit.py +722 -0
  43. package/templates/skills_normal/git-pushing/scripts/smart_commit.sh +19 -0
  44. package/templates/skills_normal/lint-and-validate/scripts/lint_runner.py +184 -0
  45. package/templates/skills_normal/lint-and-validate/scripts/type_coverage.py +173 -0
  46. package/templates/skills_normal/performance-profiling/scripts/lighthouse_audit.py +76 -0
  47. package/templates/skills_normal/senior-fullstack/scripts/code_quality_analyzer.py +114 -0
  48. package/templates/skills_normal/senior-fullstack/scripts/fullstack_scaffolder.py +114 -0
  49. package/templates/skills_normal/senior-fullstack/scripts/project_scaffolder.py +114 -0
  50. package/templates/skills_normal/seo-fundamentals/scripts/seo_checker.py +219 -0
  51. package/templates/skills_normal/testing-patterns/scripts/test_runner.py +219 -0
  52. package/templates/skills_normal/vulnerability-scanner/scripts/security_scan.py +458 -0
  53. package/templates/vault/007/scripts/config.py +472 -0
  54. package/templates/vault/007/scripts/full_audit.py +1306 -0
  55. package/templates/vault/007/scripts/quick_scan.py +481 -0
  56. package/templates/vault/007/scripts/requirements.txt +26 -0
  57. package/templates/vault/007/scripts/scanners/__init__.py +0 -0
  58. package/templates/vault/007/scripts/scanners/dependency_scanner.py +1305 -0
  59. package/templates/vault/007/scripts/scanners/injection_scanner.py +1104 -0
  60. package/templates/vault/007/scripts/scanners/secrets_scanner.py +1008 -0
  61. package/templates/vault/007/scripts/score_calculator.py +693 -0
  62. package/templates/vault/agent-orchestrator/scripts/match_skills.py +329 -0
  63. package/templates/vault/agent-orchestrator/scripts/orchestrate.py +304 -0
  64. package/templates/vault/agent-orchestrator/scripts/requirements.txt +1 -0
  65. package/templates/vault/agent-orchestrator/scripts/scan_registry.py +508 -0
  66. package/templates/vault/ai-studio-image/scripts/config.py +613 -0
  67. package/templates/vault/ai-studio-image/scripts/generate.py +630 -0
  68. package/templates/vault/ai-studio-image/scripts/prompt_engine.py +424 -0
  69. package/templates/vault/ai-studio-image/scripts/requirements.txt +4 -0
  70. package/templates/vault/ai-studio-image/scripts/templates.py +349 -0
  71. package/templates/vault/android_ui_verification/scripts/verify_ui.sh +32 -0
  72. package/templates/vault/apify-audience-analysis/reference/scripts/run_actor.js +363 -0
  73. package/templates/vault/apify-brand-reputation-monitoring/reference/scripts/run_actor.js +363 -0
  74. package/templates/vault/apify-competitor-intelligence/reference/scripts/run_actor.js +363 -0
  75. package/templates/vault/apify-content-analytics/reference/scripts/run_actor.js +363 -0
  76. package/templates/vault/apify-ecommerce/reference/scripts/package.json +3 -0
  77. package/templates/vault/apify-ecommerce/reference/scripts/run_actor.js +369 -0
  78. package/templates/vault/apify-influencer-discovery/reference/scripts/run_actor.js +363 -0
  79. package/templates/vault/apify-lead-generation/reference/scripts/run_actor.js +363 -0
  80. package/templates/vault/apify-market-research/reference/scripts/run_actor.js +363 -0
  81. package/templates/vault/apify-trend-analysis/reference/scripts/run_actor.js +363 -0
  82. package/templates/vault/apify-ultimate-scraper/reference/scripts/run_actor.js +363 -0
  83. package/templates/vault/audio-transcriber/scripts/install-requirements.sh +190 -0
  84. package/templates/vault/audio-transcriber/scripts/transcribe.py +486 -0
  85. package/templates/vault/claude-monitor/scripts/api_bench.py +240 -0
  86. package/templates/vault/claude-monitor/scripts/config.py +69 -0
  87. package/templates/vault/claude-monitor/scripts/health_check.py +362 -0
  88. package/templates/vault/claude-monitor/scripts/monitor.py +296 -0
  89. package/templates/vault/content-creator/scripts/brand_voice_analyzer.py +185 -0
  90. package/templates/vault/content-creator/scripts/seo_optimizer.py +419 -0
  91. package/templates/vault/context-agent/scripts/active_context.py +227 -0
  92. package/templates/vault/context-agent/scripts/compressor.py +149 -0
  93. package/templates/vault/context-agent/scripts/config.py +69 -0
  94. package/templates/vault/context-agent/scripts/context_loader.py +155 -0
  95. package/templates/vault/context-agent/scripts/context_manager.py +302 -0
  96. package/templates/vault/context-agent/scripts/models.py +103 -0
  97. package/templates/vault/context-agent/scripts/project_registry.py +132 -0
  98. package/templates/vault/context-agent/scripts/requirements.txt +6 -0
  99. package/templates/vault/context-agent/scripts/search.py +115 -0
  100. package/templates/vault/context-agent/scripts/session_parser.py +206 -0
  101. package/templates/vault/context-agent/scripts/session_summary.py +319 -0
  102. package/templates/vault/context-guardian/scripts/context_snapshot.py +229 -0
  103. package/templates/vault/docx/ooxml/scripts/pack.py +159 -0
  104. package/templates/vault/docx/ooxml/scripts/unpack.py +29 -0
  105. package/templates/vault/docx/ooxml/scripts/validate.py +69 -0
  106. package/templates/vault/docx/ooxml/scripts/validation/__init__.py +15 -0
  107. package/templates/vault/docx/ooxml/scripts/validation/base.py +951 -0
  108. package/templates/vault/docx/ooxml/scripts/validation/docx.py +274 -0
  109. package/templates/vault/docx/ooxml/scripts/validation/pptx.py +315 -0
  110. package/templates/vault/docx/ooxml/scripts/validation/redlining.py +279 -0
  111. package/templates/vault/docx/scripts/__init__.py +1 -0
  112. package/templates/vault/docx/scripts/document.py +1276 -0
  113. package/templates/vault/docx/scripts/templates/comments.xml +3 -0
  114. package/templates/vault/docx/scripts/templates/commentsExtended.xml +3 -0
  115. package/templates/vault/docx/scripts/templates/commentsExtensible.xml +3 -0
  116. package/templates/vault/docx/scripts/templates/commentsIds.xml +3 -0
  117. package/templates/vault/docx/scripts/templates/people.xml +3 -0
  118. package/templates/vault/docx/scripts/utilities.py +374 -0
  119. package/templates/vault/docx-official/ooxml/scripts/pack.py +159 -0
  120. package/templates/vault/docx-official/ooxml/scripts/unpack.py +29 -0
  121. package/templates/vault/docx-official/ooxml/scripts/validate.py +69 -0
  122. package/templates/vault/docx-official/ooxml/scripts/validation/__init__.py +15 -0
  123. package/templates/vault/docx-official/ooxml/scripts/validation/base.py +951 -0
  124. package/templates/vault/docx-official/ooxml/scripts/validation/docx.py +274 -0
  125. package/templates/vault/docx-official/ooxml/scripts/validation/pptx.py +315 -0
  126. package/templates/vault/docx-official/ooxml/scripts/validation/redlining.py +279 -0
  127. package/templates/vault/docx-official/scripts/__init__.py +1 -0
  128. package/templates/vault/docx-official/scripts/document.py +1276 -0
  129. package/templates/vault/docx-official/scripts/templates/comments.xml +3 -0
  130. package/templates/vault/docx-official/scripts/templates/commentsExtended.xml +3 -0
  131. package/templates/vault/docx-official/scripts/templates/commentsExtensible.xml +3 -0
  132. package/templates/vault/docx-official/scripts/templates/commentsIds.xml +3 -0
  133. package/templates/vault/docx-official/scripts/templates/people.xml +3 -0
  134. package/templates/vault/docx-official/scripts/utilities.py +374 -0
  135. package/templates/vault/geo-fundamentals/scripts/geo_checker.py +289 -0
  136. package/templates/vault/helm-chart-scaffolding/scripts/validate-chart.sh +244 -0
  137. package/templates/vault/i18n-localization/scripts/i18n_checker.py +241 -0
  138. package/templates/vault/instagram/scripts/account_setup.py +233 -0
  139. package/templates/vault/instagram/scripts/analyze.py +221 -0
  140. package/templates/vault/instagram/scripts/api_client.py +444 -0
  141. package/templates/vault/instagram/scripts/auth.py +411 -0
  142. package/templates/vault/instagram/scripts/comments.py +160 -0
  143. package/templates/vault/instagram/scripts/config.py +111 -0
  144. package/templates/vault/instagram/scripts/db.py +467 -0
  145. package/templates/vault/instagram/scripts/export.py +138 -0
  146. package/templates/vault/instagram/scripts/governance.py +233 -0
  147. package/templates/vault/instagram/scripts/hashtags.py +114 -0
  148. package/templates/vault/instagram/scripts/insights.py +170 -0
  149. package/templates/vault/instagram/scripts/media.py +65 -0
  150. package/templates/vault/instagram/scripts/messages.py +103 -0
  151. package/templates/vault/instagram/scripts/profile.py +58 -0
  152. package/templates/vault/instagram/scripts/publish.py +449 -0
  153. package/templates/vault/instagram/scripts/requirements.txt +5 -0
  154. package/templates/vault/instagram/scripts/run_all.py +189 -0
  155. package/templates/vault/instagram/scripts/schedule.py +189 -0
  156. package/templates/vault/instagram/scripts/serve_api.py +234 -0
  157. package/templates/vault/instagram/scripts/templates.py +155 -0
  158. package/templates/vault/junta-leiloeiros/scripts/db.py +216 -0
  159. package/templates/vault/junta-leiloeiros/scripts/export.py +137 -0
  160. package/templates/vault/junta-leiloeiros/scripts/requirements.txt +15 -0
  161. package/templates/vault/junta-leiloeiros/scripts/run_all.py +190 -0
  162. package/templates/vault/junta-leiloeiros/scripts/scraper/__init__.py +4 -0
  163. package/templates/vault/junta-leiloeiros/scripts/scraper/base_scraper.py +209 -0
  164. package/templates/vault/junta-leiloeiros/scripts/scraper/generic_scraper.py +110 -0
  165. package/templates/vault/junta-leiloeiros/scripts/scraper/jucap.py +110 -0
  166. package/templates/vault/junta-leiloeiros/scripts/scraper/juceac.py +72 -0
  167. package/templates/vault/junta-leiloeiros/scripts/scraper/juceal.py +72 -0
  168. package/templates/vault/junta-leiloeiros/scripts/scraper/juceb.py +68 -0
  169. package/templates/vault/junta-leiloeiros/scripts/scraper/jucec.py +63 -0
  170. package/templates/vault/junta-leiloeiros/scripts/scraper/jucema.py +211 -0
  171. package/templates/vault/junta-leiloeiros/scripts/scraper/jucemg.py +218 -0
  172. package/templates/vault/junta-leiloeiros/scripts/scraper/jucep.py +70 -0
  173. package/templates/vault/junta-leiloeiros/scripts/scraper/jucepa.py +74 -0
  174. package/templates/vault/junta-leiloeiros/scripts/scraper/jucepar.py +80 -0
  175. package/templates/vault/junta-leiloeiros/scripts/scraper/jucepe.py +78 -0
  176. package/templates/vault/junta-leiloeiros/scripts/scraper/jucepi.py +69 -0
  177. package/templates/vault/junta-leiloeiros/scripts/scraper/jucer.py +256 -0
  178. package/templates/vault/junta-leiloeiros/scripts/scraper/jucerja.py +170 -0
  179. package/templates/vault/junta-leiloeiros/scripts/scraper/jucern.py +71 -0
  180. package/templates/vault/junta-leiloeiros/scripts/scraper/jucesc.py +89 -0
  181. package/templates/vault/junta-leiloeiros/scripts/scraper/jucesp.py +233 -0
  182. package/templates/vault/junta-leiloeiros/scripts/scraper/jucetins.py +134 -0
  183. package/templates/vault/junta-leiloeiros/scripts/scraper/jucis_df.py +63 -0
  184. package/templates/vault/junta-leiloeiros/scripts/scraper/jucisrs.py +299 -0
  185. package/templates/vault/junta-leiloeiros/scripts/scraper/states.py +99 -0
  186. package/templates/vault/junta-leiloeiros/scripts/serve_api.py +164 -0
  187. package/templates/vault/junta-leiloeiros/scripts/web_scraper_fallback.py +233 -0
  188. package/templates/vault/last30days/scripts/last30days.py +521 -0
  189. package/templates/vault/last30days/scripts/lib/__init__.py +1 -0
  190. package/templates/vault/last30days/scripts/lib/cache.py +152 -0
  191. package/templates/vault/last30days/scripts/lib/dates.py +124 -0
  192. package/templates/vault/last30days/scripts/lib/dedupe.py +120 -0
  193. package/templates/vault/last30days/scripts/lib/env.py +149 -0
  194. package/templates/vault/last30days/scripts/lib/http.py +152 -0
  195. package/templates/vault/last30days/scripts/lib/models.py +175 -0
  196. package/templates/vault/last30days/scripts/lib/normalize.py +160 -0
  197. package/templates/vault/last30days/scripts/lib/openai_reddit.py +230 -0
  198. package/templates/vault/last30days/scripts/lib/reddit_enrich.py +232 -0
  199. package/templates/vault/last30days/scripts/lib/render.py +383 -0
  200. package/templates/vault/last30days/scripts/lib/schema.py +336 -0
  201. package/templates/vault/last30days/scripts/lib/score.py +311 -0
  202. package/templates/vault/last30days/scripts/lib/ui.py +324 -0
  203. package/templates/vault/last30days/scripts/lib/websearch.py +401 -0
  204. package/templates/vault/last30days/scripts/lib/xai_x.py +217 -0
  205. package/templates/vault/leiloeiro-avaliacao/scripts/governance.py +106 -0
  206. package/templates/vault/leiloeiro-avaliacao/scripts/requirements.txt +1 -0
  207. package/templates/vault/leiloeiro-edital/scripts/governance.py +106 -0
  208. package/templates/vault/leiloeiro-edital/scripts/requirements.txt +1 -0
  209. package/templates/vault/leiloeiro-ia/scripts/governance.py +106 -0
  210. package/templates/vault/leiloeiro-ia/scripts/requirements.txt +1 -0
  211. package/templates/vault/leiloeiro-juridico/scripts/governance.py +106 -0
  212. package/templates/vault/leiloeiro-juridico/scripts/requirements.txt +1 -0
  213. package/templates/vault/leiloeiro-mercado/scripts/governance.py +106 -0
  214. package/templates/vault/leiloeiro-mercado/scripts/requirements.txt +1 -0
  215. package/templates/vault/leiloeiro-risco/scripts/governance.py +106 -0
  216. package/templates/vault/leiloeiro-risco/scripts/requirements.txt +1 -0
  217. package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/database.ts +24 -0
  218. package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/db.ts +35 -0
  219. package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/index.ts +2 -0
  220. package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/migrations.ts +31 -0
  221. package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/db/schema.sql +8 -0
  222. package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/index.ts +44 -0
  223. package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/routes/todos.ts +155 -0
  224. package/templates/vault/loki-mode/examples/todo-app-generated/backend/src/types/index.ts +35 -0
  225. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/App.css +384 -0
  226. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/App.tsx +81 -0
  227. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/api/todos.ts +57 -0
  228. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/ConfirmDialog.tsx +26 -0
  229. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/EmptyState.tsx +8 -0
  230. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/TodoForm.tsx +43 -0
  231. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/TodoItem.tsx +36 -0
  232. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/components/TodoList.tsx +27 -0
  233. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/hooks/useTodos.ts +81 -0
  234. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/index.css +48 -0
  235. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/main.tsx +10 -0
  236. package/templates/vault/loki-mode/examples/todo-app-generated/frontend/src/vite-env.d.ts +1 -0
  237. package/templates/vault/loki-mode/scripts/export-to-vibe-kanban.sh +178 -0
  238. package/templates/vault/loki-mode/scripts/loki-wrapper.sh +281 -0
  239. package/templates/vault/loki-mode/scripts/take-screenshots.js +55 -0
  240. package/templates/vault/matematico-tao/scripts/complexity_analyzer.py +544 -0
  241. package/templates/vault/matematico-tao/scripts/dependency_graph.py +538 -0
  242. package/templates/vault/mcp-builder/scripts/connections.py +151 -0
  243. package/templates/vault/mcp-builder/scripts/evaluation.py +373 -0
  244. package/templates/vault/mcp-builder/scripts/example_evaluation.xml +22 -0
  245. package/templates/vault/mcp-builder/scripts/requirements.txt +2 -0
  246. package/templates/vault/mobile-design/scripts/mobile_audit.py +670 -0
  247. package/templates/vault/notebooklm/scripts/__init__.py +81 -0
  248. package/templates/vault/notebooklm/scripts/ask_question.py +256 -0
  249. package/templates/vault/notebooklm/scripts/auth_manager.py +358 -0
  250. package/templates/vault/notebooklm/scripts/browser_session.py +255 -0
  251. package/templates/vault/notebooklm/scripts/browser_utils.py +107 -0
  252. package/templates/vault/notebooklm/scripts/cleanup_manager.py +302 -0
  253. package/templates/vault/notebooklm/scripts/config.py +44 -0
  254. package/templates/vault/notebooklm/scripts/notebook_manager.py +410 -0
  255. package/templates/vault/notebooklm/scripts/run.py +102 -0
  256. package/templates/vault/notebooklm/scripts/setup_environment.py +204 -0
  257. package/templates/vault/pdf/scripts/check_bounding_boxes.py +70 -0
  258. package/templates/vault/pdf/scripts/check_bounding_boxes_test.py +226 -0
  259. package/templates/vault/pdf/scripts/check_fillable_fields.py +12 -0
  260. package/templates/vault/pdf/scripts/convert_pdf_to_images.py +35 -0
  261. package/templates/vault/pdf/scripts/create_validation_image.py +41 -0
  262. package/templates/vault/pdf/scripts/extract_form_field_info.py +152 -0
  263. package/templates/vault/pdf/scripts/fill_fillable_fields.py +114 -0
  264. package/templates/vault/pdf/scripts/fill_pdf_form_with_annotations.py +108 -0
  265. package/templates/vault/pdf-official/scripts/check_bounding_boxes.py +70 -0
  266. package/templates/vault/pdf-official/scripts/check_bounding_boxes_test.py +226 -0
  267. package/templates/vault/pdf-official/scripts/check_fillable_fields.py +12 -0
  268. package/templates/vault/pdf-official/scripts/convert_pdf_to_images.py +35 -0
  269. package/templates/vault/pdf-official/scripts/create_validation_image.py +41 -0
  270. package/templates/vault/pdf-official/scripts/extract_form_field_info.py +152 -0
  271. package/templates/vault/pdf-official/scripts/fill_fillable_fields.py +114 -0
  272. package/templates/vault/pdf-official/scripts/fill_pdf_form_with_annotations.py +108 -0
  273. package/templates/vault/planning-with-files/scripts/check-complete.sh +44 -0
  274. package/templates/vault/planning-with-files/scripts/init-session.sh +120 -0
  275. package/templates/vault/pptx/ooxml/scripts/pack.py +159 -0
  276. package/templates/vault/pptx/ooxml/scripts/unpack.py +29 -0
  277. package/templates/vault/pptx/ooxml/scripts/validate.py +69 -0
  278. package/templates/vault/pptx/ooxml/scripts/validation/__init__.py +15 -0
  279. package/templates/vault/pptx/ooxml/scripts/validation/base.py +951 -0
  280. package/templates/vault/pptx/ooxml/scripts/validation/docx.py +274 -0
  281. package/templates/vault/pptx/ooxml/scripts/validation/pptx.py +315 -0
  282. package/templates/vault/pptx/ooxml/scripts/validation/redlining.py +279 -0
  283. package/templates/vault/pptx/scripts/html2pptx.js +979 -0
  284. package/templates/vault/pptx/scripts/inventory.py +1020 -0
  285. package/templates/vault/pptx/scripts/rearrange.py +231 -0
  286. package/templates/vault/pptx/scripts/replace.py +385 -0
  287. package/templates/vault/pptx/scripts/thumbnail.py +450 -0
  288. package/templates/vault/pptx-official/ooxml/scripts/pack.py +159 -0
  289. package/templates/vault/pptx-official/ooxml/scripts/unpack.py +29 -0
  290. package/templates/vault/pptx-official/ooxml/scripts/validate.py +69 -0
  291. package/templates/vault/pptx-official/ooxml/scripts/validation/__init__.py +15 -0
  292. package/templates/vault/pptx-official/ooxml/scripts/validation/base.py +951 -0
  293. package/templates/vault/pptx-official/ooxml/scripts/validation/docx.py +274 -0
  294. package/templates/vault/pptx-official/ooxml/scripts/validation/pptx.py +315 -0
  295. package/templates/vault/pptx-official/ooxml/scripts/validation/redlining.py +279 -0
  296. package/templates/vault/pptx-official/scripts/html2pptx.js +979 -0
  297. package/templates/vault/pptx-official/scripts/inventory.py +1020 -0
  298. package/templates/vault/pptx-official/scripts/rearrange.py +231 -0
  299. package/templates/vault/pptx-official/scripts/replace.py +385 -0
  300. package/templates/vault/pptx-official/scripts/thumbnail.py +450 -0
  301. package/templates/vault/product-manager-toolkit/scripts/customer_interview_analyzer.py +441 -0
  302. package/templates/vault/product-manager-toolkit/scripts/rice_prioritizer.py +296 -0
  303. package/templates/vault/prompt-engineering-patterns/scripts/optimize-prompt.py +279 -0
  304. package/templates/vault/scripts/.skill_cache.json +7538 -0
  305. package/templates/vault/scripts/skill_search.py +228 -0
  306. package/templates/vault/senior-architect/scripts/architecture_diagram_generator.py +114 -0
  307. package/templates/vault/senior-architect/scripts/dependency_analyzer.py +114 -0
  308. package/templates/vault/senior-architect/scripts/project_architect.py +114 -0
  309. package/templates/vault/shopify-development/scripts/requirements.txt +19 -0
  310. package/templates/vault/shopify-development/scripts/shopify_graphql.py +428 -0
  311. package/templates/vault/shopify-development/scripts/shopify_init.py +441 -0
  312. package/templates/vault/shopify-development/scripts/tests/test_shopify_init.py +379 -0
  313. package/templates/vault/skill-creator/scripts/init_skill.py +303 -0
  314. package/templates/vault/skill-creator/scripts/package_skill.py +110 -0
  315. package/templates/vault/skill-creator/scripts/quick_validate.py +95 -0
  316. package/templates/vault/skill-installer/scripts/detect_skills.py +318 -0
  317. package/templates/vault/skill-installer/scripts/install_skill.py +1708 -0
  318. package/templates/vault/skill-installer/scripts/package_skill.py +417 -0
  319. package/templates/vault/skill-installer/scripts/requirements.txt +1 -0
  320. package/templates/vault/skill-installer/scripts/validate_skill.py +430 -0
  321. package/templates/vault/skill-sentinel/scripts/analyzers/__init__.py +13 -0
  322. package/templates/vault/skill-sentinel/scripts/analyzers/code_quality.py +247 -0
  323. package/templates/vault/skill-sentinel/scripts/analyzers/cross_skill.py +134 -0
  324. package/templates/vault/skill-sentinel/scripts/analyzers/dependencies.py +121 -0
  325. package/templates/vault/skill-sentinel/scripts/analyzers/documentation.py +189 -0
  326. package/templates/vault/skill-sentinel/scripts/analyzers/governance_audit.py +153 -0
  327. package/templates/vault/skill-sentinel/scripts/analyzers/performance.py +164 -0
  328. package/templates/vault/skill-sentinel/scripts/analyzers/security.py +189 -0
  329. package/templates/vault/skill-sentinel/scripts/config.py +158 -0
  330. package/templates/vault/skill-sentinel/scripts/cost_optimizer.py +146 -0
  331. package/templates/vault/skill-sentinel/scripts/db.py +354 -0
  332. package/templates/vault/skill-sentinel/scripts/governance.py +58 -0
  333. package/templates/vault/skill-sentinel/scripts/recommender.py +228 -0
  334. package/templates/vault/skill-sentinel/scripts/report_generator.py +224 -0
  335. package/templates/vault/skill-sentinel/scripts/requirements.txt +1 -0
  336. package/templates/vault/skill-sentinel/scripts/run_audit.py +290 -0
  337. package/templates/vault/skill-sentinel/scripts/scanner.py +271 -0
  338. package/templates/vault/stability-ai/scripts/config.py +266 -0
  339. package/templates/vault/stability-ai/scripts/generate.py +687 -0
  340. package/templates/vault/stability-ai/scripts/requirements.txt +4 -0
  341. package/templates/vault/stability-ai/scripts/styles.py +174 -0
  342. package/templates/vault/telegram/assets/boilerplate/nodejs/src/bot-client.ts +86 -0
  343. package/templates/vault/telegram/assets/boilerplate/nodejs/src/handlers.ts +79 -0
  344. package/templates/vault/telegram/assets/boilerplate/nodejs/src/index.ts +32 -0
  345. package/templates/vault/telegram/scripts/send_message.py +143 -0
  346. package/templates/vault/telegram/scripts/setup_project.py +103 -0
  347. package/templates/vault/telegram/scripts/test_bot.py +144 -0
  348. package/templates/vault/typescript-expert/scripts/ts_diagnostic.py +203 -0
  349. package/templates/vault/ui-ux-pro-max/scripts/__pycache__/core.cpython-314.pyc +0 -0
  350. package/templates/vault/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-314.pyc +0 -0
  351. package/templates/vault/ui-ux-pro-max/scripts/core.py +257 -0
  352. package/templates/vault/ui-ux-pro-max/scripts/design_system.py +487 -0
  353. package/templates/vault/ui-ux-pro-max/scripts/search.py +76 -0
  354. package/templates/vault/videodb/scripts/ws_listener.py +204 -0
  355. package/templates/vault/web-artifacts-builder/scripts/bundle-artifact.sh +54 -0
  356. package/templates/vault/web-artifacts-builder/scripts/init-artifact.sh +322 -0
  357. package/templates/vault/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
  358. package/templates/vault/webapp-testing/scripts/with_server.py +106 -0
  359. package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/index.ts +125 -0
  360. package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/template-manager.ts +67 -0
  361. package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/types.ts +216 -0
  362. package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/webhook-handler.ts +173 -0
  363. package/templates/vault/whatsapp-cloud-api/assets/boilerplate/nodejs/src/whatsapp-client.ts +193 -0
  364. package/templates/vault/whatsapp-cloud-api/scripts/send_test_message.py +137 -0
  365. package/templates/vault/whatsapp-cloud-api/scripts/setup_project.py +118 -0
  366. package/templates/vault/whatsapp-cloud-api/scripts/validate_config.py +190 -0
  367. package/templates/vault/youtube-summarizer/scripts/extract-transcript.py +65 -0
  368. 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()