@thanhvn14/csvibe 0.1.3 → 0.1.5
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/.github/agents/schemas/base-output.schema.json +88 -0
- package/.github/agents/schemas/brainstorm-output.schema.json +88 -0
- package/.github/agents/schemas/scout-output.schema.json +60 -0
- package/.github/agents/scripts/fetch-copilot-tools.js +245 -0
- package/.github/agents/scripts/lib/parse-agent-file.js +275 -0
- package/.github/agents/scripts/package-lock.json +78 -0
- package/.github/agents/scripts/package.json +22 -0
- package/.github/agents/scripts/schemas/agent-frontmatter.schema.json +83 -0
- package/.github/agents/scripts/validate-agent-all.js +157 -0
- package/.github/agents/scripts/validate-agent-frontmatter.js +96 -0
- package/.github/agents/scripts/validate-agent-handoffs.js +169 -0
- package/.github/agents/scripts/validate-agent-output.js +157 -0
- package/.github/agents/scripts/validate-agent-tools.js +278 -0
- package/.github/skills/.env.example +100 -0
- package/.github/skills/.install-state.json +23 -0
- package/.github/skills/README.md +149 -0
- package/.github/skills/ai-multimodal/.env.example +204 -0
- package/.github/skills/ai-multimodal/scripts/.coverage +0 -0
- package/.github/skills/ai-multimodal/scripts/check_setup.py +305 -0
- package/.github/skills/ai-multimodal/scripts/document_converter.py +395 -0
- package/.github/skills/ai-multimodal/scripts/gemini_batch_process.py +1184 -0
- package/.github/skills/ai-multimodal/scripts/media_optimizer.py +506 -0
- package/.github/skills/ai-multimodal/scripts/requirements.txt +26 -0
- package/.github/skills/better-auth/scripts/.coverage +0 -0
- package/.github/skills/better-auth/scripts/better_auth_init.py +521 -0
- package/.github/skills/better-auth/scripts/requirements.txt +15 -0
- package/.github/skills/chrome-devtools/scripts/README.md +272 -0
- package/.github/skills/chrome-devtools/scripts/__tests__/selector.test.js +210 -0
- package/.github/skills/chrome-devtools/scripts/aria-snapshot.js +362 -0
- package/.github/skills/chrome-devtools/scripts/click.js +83 -0
- package/.github/skills/chrome-devtools/scripts/console.js +79 -0
- package/.github/skills/chrome-devtools/scripts/evaluate.js +53 -0
- package/.github/skills/chrome-devtools/scripts/fill.js +76 -0
- package/.github/skills/chrome-devtools/scripts/inject-auth.js +229 -0
- package/.github/skills/chrome-devtools/scripts/install-deps.sh +181 -0
- package/.github/skills/chrome-devtools/scripts/install.sh +83 -0
- package/.github/skills/chrome-devtools/scripts/lib/browser.js +318 -0
- package/.github/skills/chrome-devtools/scripts/lib/selector.js +178 -0
- package/.github/skills/chrome-devtools/scripts/navigate.js +54 -0
- package/.github/skills/chrome-devtools/scripts/network.js +106 -0
- package/.github/skills/chrome-devtools/scripts/package-lock.json +1589 -0
- package/.github/skills/chrome-devtools/scripts/package.json +16 -0
- package/.github/skills/chrome-devtools/scripts/performance.js +149 -0
- package/.github/skills/chrome-devtools/scripts/screenshot.js +198 -0
- package/.github/skills/chrome-devtools/scripts/select-ref.js +131 -0
- package/.github/skills/chrome-devtools/scripts/snapshot.js +135 -0
- package/.github/skills/common/README.md +120 -0
- package/.github/skills/common/api_key_helper.py +411 -0
- package/.github/skills/common/api_key_rotator.py +248 -0
- package/.github/skills/databases/scripts/.coverage +0 -0
- package/.github/skills/databases/scripts/db_backup.py +502 -0
- package/.github/skills/databases/scripts/db_migrate.py +425 -0
- package/.github/skills/databases/scripts/db_performance_check.py +456 -0
- package/.github/skills/databases/scripts/requirements.txt +20 -0
- package/.github/skills/debugging/scripts/find-polluter.sh +63 -0
- package/.github/skills/devops/.env.example +76 -0
- package/.github/skills/devops/scripts/cloudflare_deploy.py +269 -0
- package/.github/skills/devops/scripts/docker_optimize.py +331 -0
- package/.github/skills/devops/scripts/requirements.txt +20 -0
- package/.github/skills/docs-seeker/.env.example +15 -0
- package/.github/skills/docs-seeker/package.json +25 -0
- package/.github/skills/docs-seeker/scripts/analyze-llms-txt.js +211 -0
- package/.github/skills/docs-seeker/scripts/detect-topic.js +172 -0
- package/.github/skills/docs-seeker/scripts/fetch-docs.js +213 -0
- package/.github/skills/docs-seeker/scripts/utils/env-loader.js +94 -0
- package/.github/skills/document-skills/docx/LICENSE.txt +30 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/mce/mc.xsd +75 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/.github/skills/document-skills/docx/ooxml/scripts/pack.py +159 -0
- package/.github/skills/document-skills/docx/ooxml/scripts/unpack.py +29 -0
- package/.github/skills/document-skills/docx/ooxml/scripts/validate.py +69 -0
- package/.github/skills/document-skills/docx/ooxml/scripts/validation/__init__.py +15 -0
- package/.github/skills/document-skills/docx/ooxml/scripts/validation/base.py +951 -0
- package/.github/skills/document-skills/docx/ooxml/scripts/validation/docx.py +274 -0
- package/.github/skills/document-skills/docx/ooxml/scripts/validation/pptx.py +315 -0
- package/.github/skills/document-skills/docx/ooxml/scripts/validation/redlining.py +279 -0
- package/.github/skills/document-skills/docx/scripts/__init__.py +1 -0
- package/.github/skills/document-skills/docx/scripts/document.py +1276 -0
- package/.github/skills/document-skills/docx/scripts/templates/comments.xml +3 -0
- package/.github/skills/document-skills/docx/scripts/templates/commentsExtended.xml +3 -0
- package/.github/skills/document-skills/docx/scripts/templates/commentsExtensible.xml +3 -0
- package/.github/skills/document-skills/docx/scripts/templates/commentsIds.xml +3 -0
- package/.github/skills/document-skills/docx/scripts/templates/people.xml +3 -0
- package/.github/skills/document-skills/docx/scripts/utilities.py +374 -0
- package/.github/skills/document-skills/pdf/LICENSE.txt +30 -0
- package/.github/skills/document-skills/pdf/scripts/check_bounding_boxes.py +70 -0
- package/.github/skills/document-skills/pdf/scripts/check_bounding_boxes_test.py +226 -0
- package/.github/skills/document-skills/pdf/scripts/check_fillable_fields.py +12 -0
- package/.github/skills/document-skills/pdf/scripts/convert_pdf_to_images.py +35 -0
- package/.github/skills/document-skills/pdf/scripts/create_validation_image.py +41 -0
- package/.github/skills/document-skills/pdf/scripts/extract_form_field_info.py +152 -0
- package/.github/skills/document-skills/pdf/scripts/fill_fillable_fields.py +114 -0
- package/.github/skills/document-skills/pdf/scripts/fill_pdf_form_with_annotations.py +108 -0
- package/.github/skills/document-skills/pptx/LICENSE.txt +30 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/mce/mc.xsd +75 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/.github/skills/document-skills/pptx/ooxml/scripts/pack.py +159 -0
- package/.github/skills/document-skills/pptx/ooxml/scripts/unpack.py +29 -0
- package/.github/skills/document-skills/pptx/ooxml/scripts/validate.py +69 -0
- package/.github/skills/document-skills/pptx/ooxml/scripts/validation/__init__.py +15 -0
- package/.github/skills/document-skills/pptx/ooxml/scripts/validation/base.py +951 -0
- package/.github/skills/document-skills/pptx/ooxml/scripts/validation/docx.py +274 -0
- package/.github/skills/document-skills/pptx/ooxml/scripts/validation/pptx.py +315 -0
- package/.github/skills/document-skills/pptx/ooxml/scripts/validation/redlining.py +279 -0
- package/.github/skills/document-skills/pptx/scripts/html2pptx.js +979 -0
- package/.github/skills/document-skills/pptx/scripts/inventory.py +1020 -0
- package/.github/skills/document-skills/pptx/scripts/rearrange.py +231 -0
- package/.github/skills/document-skills/pptx/scripts/replace.py +385 -0
- package/.github/skills/document-skills/pptx/scripts/thumbnail.py +450 -0
- package/.github/skills/document-skills/xlsx/LICENSE.txt +30 -0
- package/.github/skills/document-skills/xlsx/recalc.py +190 -0
- package/.github/skills/install.ps1 +1220 -0
- package/.github/skills/install.sh +1032 -0
- package/.github/skills/markdown-novel-viewer/assets/directory-browser.css +215 -0
- package/.github/skills/markdown-novel-viewer/assets/favicon.png +0 -0
- package/.github/skills/markdown-novel-viewer/assets/novel-theme.css +818 -0
- package/.github/skills/markdown-novel-viewer/assets/reader.js +262 -0
- package/.github/skills/markdown-novel-viewer/assets/template.html +80 -0
- package/.github/skills/markdown-novel-viewer/package-lock.json +146 -0
- package/.github/skills/markdown-novel-viewer/package.json +15 -0
- package/.github/skills/markdown-novel-viewer/scripts/lib/http-server.cjs +434 -0
- package/.github/skills/markdown-novel-viewer/scripts/lib/markdown-renderer.cjs +272 -0
- package/.github/skills/markdown-novel-viewer/scripts/lib/plan-navigator.cjs +509 -0
- package/.github/skills/markdown-novel-viewer/scripts/lib/port-finder.cjs +48 -0
- package/.github/skills/markdown-novel-viewer/scripts/lib/process-mgr.cjs +150 -0
- package/.github/skills/markdown-novel-viewer/scripts/server.cjs +411 -0
- package/.github/skills/mcp-builder/LICENSE.txt +202 -0
- package/.github/skills/mcp-builder/scripts/connections.py +151 -0
- package/.github/skills/mcp-builder/scripts/evaluation.py +373 -0
- package/.github/skills/mcp-builder/scripts/example_evaluation.xml +22 -0
- package/.github/skills/mcp-builder/scripts/requirements.txt +2 -0
- package/.github/skills/mcp-management/README.md +219 -0
- package/.github/skills/mcp-management/assets/tools.json +3146 -0
- package/.github/skills/mcp-management/package-lock.json +6 -0
- package/.github/skills/mcp-management/scripts/.env.example +10 -0
- package/.github/skills/mcp-management/scripts/cli.ts +195 -0
- package/.github/skills/mcp-management/scripts/dist/analyze-tools.js +70 -0
- package/.github/skills/mcp-management/scripts/dist/cli.js +160 -0
- package/.github/skills/mcp-management/scripts/dist/mcp-client.js +183 -0
- package/.github/skills/mcp-management/scripts/mcp-client.ts +230 -0
- package/.github/skills/mcp-management/scripts/package.json +20 -0
- package/.github/skills/media-processing/scripts/README.md +111 -0
- package/.github/skills/media-processing/scripts/batch-remove-background.sh +124 -0
- package/.github/skills/media-processing/scripts/batch_resize.py +342 -0
- package/.github/skills/media-processing/scripts/media_convert.py +311 -0
- package/.github/skills/media-processing/scripts/remove-background.sh +96 -0
- package/.github/skills/media-processing/scripts/remove-bg-node.js +158 -0
- package/.github/skills/media-processing/scripts/requirements.txt +24 -0
- package/.github/skills/media-processing/scripts/video_optimize.py +414 -0
- package/.github/skills/payment-integration/README.md +185 -0
- package/.github/skills/payment-integration/scripts/.env.example +20 -0
- package/.github/skills/payment-integration/scripts/checkout-helper.js +244 -0
- package/.github/skills/payment-integration/scripts/package.json +17 -0
- package/.github/skills/payment-integration/scripts/polar-webhook-verify.js +202 -0
- package/.github/skills/payment-integration/scripts/sepay-webhook-verify.js +193 -0
- package/.github/skills/payment-integration/scripts/test-scripts.js +237 -0
- package/.github/skills/plans-kanban/assets/dashboard-template.html +119 -0
- package/.github/skills/plans-kanban/assets/dashboard.css +1594 -0
- package/.github/skills/plans-kanban/assets/dashboard.js +596 -0
- package/.github/skills/plans-kanban/assets/favicon.png +0 -0
- package/.github/skills/plans-kanban/package-lock.json +123 -0
- package/.github/skills/plans-kanban/package.json +13 -0
- package/.github/skills/plans-kanban/scripts/lib/dashboard-renderer.cjs +884 -0
- package/.github/skills/plans-kanban/scripts/lib/http-server.cjs +310 -0
- package/.github/skills/plans-kanban/scripts/lib/plan-metadata-extractor.cjs +489 -0
- package/.github/skills/plans-kanban/scripts/lib/plan-parser.cjs +175 -0
- package/.github/skills/plans-kanban/scripts/lib/plan-scanner.cjs +272 -0
- package/.github/skills/plans-kanban/scripts/lib/port-finder.cjs +48 -0
- package/.github/skills/plans-kanban/scripts/lib/process-mgr.cjs +128 -0
- package/.github/skills/plans-kanban/scripts/server.cjs +260 -0
- package/.github/skills/repomix/scripts/.coverage +0 -0
- package/.github/skills/repomix/scripts/README.md +179 -0
- package/.github/skills/repomix/scripts/repomix_batch.py +455 -0
- package/.github/skills/repomix/scripts/repos.example.json +15 -0
- package/.github/skills/repomix/scripts/requirements.txt +15 -0
- package/.github/skills/scout-validation/scripts/lib/broad-pattern-detector.cjs +124 -0
- package/.github/skills/scout-validation/scripts/lib/path-checker.cjs +66 -0
- package/.github/skills/scout-validation/scripts/lib/schema-validator.cjs +45 -0
- package/.github/skills/scout-validation/scripts/package.json +11 -0
- package/.github/skills/scout-validation/scripts/validate-scout-output.cjs +219 -0
- package/.github/skills/scout-validation/test/broad-pattern-output.json +18 -0
- package/.github/skills/scout-validation/test/invalid-path-output.json +18 -0
- package/.github/skills/scout-validation/test/valid-scout-output.json +26 -0
- package/.github/skills/sequential-thinking/.env.example +8 -0
- package/.github/skills/sequential-thinking/README.md +183 -0
- package/.github/skills/sequential-thinking/package.json +31 -0
- package/.github/skills/sequential-thinking/scripts/format-thought.js +159 -0
- package/.github/skills/sequential-thinking/scripts/process-thought.js +236 -0
- package/.github/skills/shopify/README.md +66 -0
- package/.github/skills/shopify/scripts/.coverage +0 -0
- package/.github/skills/shopify/scripts/requirements.txt +19 -0
- package/.github/skills/shopify/scripts/shopify_init.py +423 -0
- package/.github/skills/skill-creator/LICENSE.txt +202 -0
- package/.github/skills/skill-creator/scripts/init_skill.py +303 -0
- package/.github/skills/skill-creator/scripts/package_skill.py +110 -0
- package/.github/skills/skill-creator/scripts/quick_validate.py +65 -0
- package/.github/skills/ui-styling/LICENSE.txt +202 -0
- package/.github/skills/ui-styling/canvas-fonts/ArsenalSC-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/BigShoulders-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/BigShoulders-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/BigShoulders-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Boldonse-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/Boldonse-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/CrimsonPro-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/DMMono-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/DMMono-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/EricaOne-OFL.txt +94 -0
- package/.github/skills/ui-styling/canvas-fonts/EricaOne-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/GeistMono-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/GeistMono-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/GeistMono-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Gloock-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/Gloock-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/IBMPlexMono-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/InstrumentSans-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Italiana-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/Italiana-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Jura-Light.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Jura-Medium.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Jura-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/LibreBaskerville-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Lora-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Lora-BoldItalic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Lora-Italic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Lora-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/Lora-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/NationalPark-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/NationalPark-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/NationalPark-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Outfit-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Outfit-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/Outfit-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/PixelifySans-Medium.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/PixelifySans-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/PoiretOne-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/PoiretOne-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/RedHatMono-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/RedHatMono-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/RedHatMono-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Silkscreen-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/Silkscreen-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/SmoochSans-Medium.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/SmoochSans-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/Tektur-Medium.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Tektur-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/Tektur-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/WorkSans-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/WorkSans-Italic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/WorkSans-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/WorkSans-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/YoungSerif-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/YoungSerif-Regular.ttf +0 -0
- package/.github/skills/ui-styling/scripts/.coverage +0 -0
- package/.github/skills/ui-styling/scripts/requirements.txt +17 -0
- package/.github/skills/ui-styling/scripts/shadcn_add.py +292 -0
- package/.github/skills/ui-styling/scripts/tailwind_config_gen.py +456 -0
- package/.github/skills/ui-ux-pro-max/data/charts.csv +26 -0
- package/.github/skills/ui-ux-pro-max/data/colors.csv +97 -0
- package/.github/skills/ui-ux-pro-max/data/landing.csv +31 -0
- package/.github/skills/ui-ux-pro-max/data/products.csv +97 -0
- package/.github/skills/ui-ux-pro-max/data/prompts.csv +24 -0
- package/.github/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/.github/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +51 -0
- package/.github/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/.github/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/.github/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/.github/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/.github/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/.github/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/.github/skills/ui-ux-pro-max/data/styles.csv +59 -0
- package/.github/skills/ui-ux-pro-max/data/typography.csv +58 -0
- package/.github/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/.github/skills/ui-ux-pro-max/scripts/core.py +236 -0
- package/.github/skills/ui-ux-pro-max/scripts/search.py +76 -0
- package/.github/skills/web-frameworks/scripts/.coverage +0 -0
- package/.github/skills/web-frameworks/scripts/__init__.py +0 -0
- package/.github/skills/web-frameworks/scripts/nextjs_init.py +547 -0
- package/.github/skills/web-frameworks/scripts/requirements.txt +16 -0
- package/.github/skills/web-frameworks/scripts/turborepo_migrate.py +394 -0
- package/dist/config/constants.d.ts +3 -0
- package/dist/config/constants.d.ts.map +1 -1
- package/dist/config/constants.js +5 -1
- package/dist/config/constants.js.map +1 -1
- package/dist/domains/github/github-client.d.ts +5 -0
- package/dist/domains/github/github-client.d.ts.map +1 -1
- package/dist/domains/github/github-client.js +44 -0
- package/dist/domains/github/github-client.js.map +1 -1
- package/dist/utils/downloader.d.ts +3 -1
- package/dist/utils/downloader.d.ts.map +1 -1
- package/dist/utils/downloader.js +48 -11
- package/dist/utils/downloader.js.map +1 -1
- package/dist/utils/scaffolder.d.ts.map +1 -1
- package/dist/utils/scaffolder.js +2 -0
- package/dist/utils/scaffolder.js.map +1 -1
- package/package.json +3 -1
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Validate ai-multimodal skill setup and configuration.
|
|
4
|
+
|
|
5
|
+
Checks:
|
|
6
|
+
- API key presence and format
|
|
7
|
+
- Python dependencies
|
|
8
|
+
- Centralized resolver availability
|
|
9
|
+
- Directory structure
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
import sys
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
# Color codes for terminal output
|
|
17
|
+
GREEN = '\033[92m'
|
|
18
|
+
YELLOW = '\033[93m'
|
|
19
|
+
RED = '\033[91m'
|
|
20
|
+
BLUE = '\033[94m'
|
|
21
|
+
RESET = '\033[0m'
|
|
22
|
+
BOLD = '\033[1m'
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def print_header(text):
|
|
26
|
+
"""Print section header."""
|
|
27
|
+
print(f"\n{BOLD}{BLUE}{'='*60}{RESET}")
|
|
28
|
+
print(f"{BOLD}{BLUE}{text}{RESET}")
|
|
29
|
+
print(f"{BOLD}{BLUE}{'='*60}{RESET}\n")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def print_success(text):
|
|
33
|
+
"""Print success message."""
|
|
34
|
+
print(f"{GREEN}✓ {text}{RESET}")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def print_warning(text):
|
|
38
|
+
"""Print warning message."""
|
|
39
|
+
print(f"{YELLOW}⚠ {text}{RESET}")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def print_error(text):
|
|
43
|
+
"""Print error message."""
|
|
44
|
+
print(f"{RED}✗ {text}{RESET}")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def print_info(text):
|
|
48
|
+
"""Print info message."""
|
|
49
|
+
print(f"{BLUE}ℹ {text}{RESET}")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def check_dependencies():
|
|
53
|
+
"""Check if required Python packages are installed."""
|
|
54
|
+
print_header("Checking Python Dependencies")
|
|
55
|
+
|
|
56
|
+
dependencies = {
|
|
57
|
+
'google.genai': 'google-genai',
|
|
58
|
+
'dotenv': 'python-dotenv',
|
|
59
|
+
'PIL': 'pillow'
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
missing = []
|
|
63
|
+
|
|
64
|
+
for module_name, package_name in dependencies.items():
|
|
65
|
+
try:
|
|
66
|
+
__import__(module_name)
|
|
67
|
+
print_success(f"{package_name} is installed")
|
|
68
|
+
except ImportError:
|
|
69
|
+
print_error(f"{package_name} is NOT installed")
|
|
70
|
+
missing.append(package_name)
|
|
71
|
+
|
|
72
|
+
if missing:
|
|
73
|
+
print_error("\nMissing dependencies detected!")
|
|
74
|
+
print_info(f"Install with: pip install {' '.join(missing)}")
|
|
75
|
+
return False
|
|
76
|
+
|
|
77
|
+
return True
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def check_centralized_resolver():
|
|
81
|
+
"""Check if centralized resolver is available."""
|
|
82
|
+
print_header("Checking Centralized Resolver")
|
|
83
|
+
|
|
84
|
+
resolver_path = Path.home() / '.claude' / 'scripts' / 'resolve_env.py'
|
|
85
|
+
|
|
86
|
+
if resolver_path.exists():
|
|
87
|
+
print_success(f"Centralized resolver found: {resolver_path}")
|
|
88
|
+
|
|
89
|
+
# Try to import it
|
|
90
|
+
sys.path.insert(0, str(resolver_path.parent))
|
|
91
|
+
try:
|
|
92
|
+
from resolve_env import resolve_env
|
|
93
|
+
print_success("Centralized resolver can be imported")
|
|
94
|
+
return True
|
|
95
|
+
except ImportError as e:
|
|
96
|
+
print_error(f"Centralized resolver exists but cannot be imported: {e}")
|
|
97
|
+
return False
|
|
98
|
+
else:
|
|
99
|
+
print_warning(f"Centralized resolver not found: {resolver_path}")
|
|
100
|
+
print_info("Skill will use fallback resolution logic")
|
|
101
|
+
return True # Not critical, fallback works
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def find_api_key():
|
|
105
|
+
"""Find and validate API key using centralized resolver."""
|
|
106
|
+
print_header("Checking API Key Configuration")
|
|
107
|
+
|
|
108
|
+
# Try to use centralized resolver
|
|
109
|
+
sys.path.insert(0, str(Path.home() / '.claude' / 'scripts'))
|
|
110
|
+
try:
|
|
111
|
+
from resolve_env import resolve_env
|
|
112
|
+
|
|
113
|
+
print_info("Using centralized resolver...")
|
|
114
|
+
api_key = resolve_env('GEMINI_API_KEY', skill='ai-multimodal')
|
|
115
|
+
|
|
116
|
+
if api_key:
|
|
117
|
+
print_success("API key found via centralized resolver")
|
|
118
|
+
print_info(f"Key preview: {api_key[:20]}...{api_key[-4:]}")
|
|
119
|
+
|
|
120
|
+
# Show hierarchy
|
|
121
|
+
print_info("\nTo see where the key was found, run:")
|
|
122
|
+
print_info("python ~/.claude/scripts/resolve_env.py GEMINI_API_KEY --skill ai-multimodal --verbose")
|
|
123
|
+
|
|
124
|
+
return api_key
|
|
125
|
+
else:
|
|
126
|
+
print_error("API key not found in any location")
|
|
127
|
+
return None
|
|
128
|
+
|
|
129
|
+
except ImportError:
|
|
130
|
+
print_warning("Centralized resolver not available, using fallback")
|
|
131
|
+
|
|
132
|
+
# Fallback: check environment
|
|
133
|
+
api_key = os.getenv('GEMINI_API_KEY')
|
|
134
|
+
if api_key:
|
|
135
|
+
print_success("API key found in process.env")
|
|
136
|
+
print_info(f"Key preview: {api_key[:20]}...{api_key[-4:]}")
|
|
137
|
+
return api_key
|
|
138
|
+
else:
|
|
139
|
+
print_error("API key not found")
|
|
140
|
+
return None
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def validate_api_key_format(api_key):
|
|
144
|
+
"""Basic validation of API key format."""
|
|
145
|
+
if not api_key:
|
|
146
|
+
return False
|
|
147
|
+
|
|
148
|
+
# Google AI Studio keys typically start with 'AIza'
|
|
149
|
+
if api_key.startswith('AIza'):
|
|
150
|
+
print_success("API key format looks valid (Google AI Studio)")
|
|
151
|
+
return True
|
|
152
|
+
elif len(api_key) > 20:
|
|
153
|
+
print_warning("API key format not recognized (may be Vertex AI or custom)")
|
|
154
|
+
return True
|
|
155
|
+
else:
|
|
156
|
+
print_error("API key format looks invalid (too short)")
|
|
157
|
+
return False
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def test_api_connection(api_key):
|
|
161
|
+
"""Test API connection with a simple request."""
|
|
162
|
+
print_header("Testing API Connection")
|
|
163
|
+
|
|
164
|
+
try:
|
|
165
|
+
from google import genai
|
|
166
|
+
|
|
167
|
+
print_info("Initializing Gemini client...")
|
|
168
|
+
client = genai.Client(api_key=api_key)
|
|
169
|
+
|
|
170
|
+
print_info("Fetching available models...")
|
|
171
|
+
# List models to verify API key works
|
|
172
|
+
models = list(client.models.list())
|
|
173
|
+
|
|
174
|
+
print_success(f"API connection successful! Found {len(models)} available models")
|
|
175
|
+
|
|
176
|
+
# Show some available models
|
|
177
|
+
print_info("\nSample available models:")
|
|
178
|
+
for model in models[:5]:
|
|
179
|
+
print(f" - {model.name}")
|
|
180
|
+
|
|
181
|
+
return True
|
|
182
|
+
|
|
183
|
+
except ImportError:
|
|
184
|
+
print_error("google-genai package not installed")
|
|
185
|
+
return False
|
|
186
|
+
except Exception as e:
|
|
187
|
+
print_error(f"API connection failed: {str(e)}")
|
|
188
|
+
return False
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def check_directory_structure():
|
|
192
|
+
"""Verify skill directory structure."""
|
|
193
|
+
print_header("Checking Directory Structure")
|
|
194
|
+
|
|
195
|
+
script_dir = Path(__file__).parent
|
|
196
|
+
skill_dir = script_dir.parent
|
|
197
|
+
|
|
198
|
+
required_files = [
|
|
199
|
+
('SKILL.md', skill_dir / 'SKILL.md'),
|
|
200
|
+
('.env.example', skill_dir / '.env.example'),
|
|
201
|
+
('gemini_batch_process.py', script_dir / 'gemini_batch_process.py'),
|
|
202
|
+
]
|
|
203
|
+
|
|
204
|
+
all_exist = True
|
|
205
|
+
|
|
206
|
+
for name, path in required_files:
|
|
207
|
+
if path.exists():
|
|
208
|
+
print_success(f"{name} exists")
|
|
209
|
+
else:
|
|
210
|
+
print_error(f"{name} NOT found at {path}")
|
|
211
|
+
all_exist = False
|
|
212
|
+
|
|
213
|
+
return all_exist
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def provide_setup_instructions():
|
|
217
|
+
"""Provide setup instructions if configuration is incomplete."""
|
|
218
|
+
print_header("Setup Instructions")
|
|
219
|
+
|
|
220
|
+
print_info("To configure the ai-multimodal skill:")
|
|
221
|
+
print("\n1. Get a Gemini API key:")
|
|
222
|
+
print(" → Visit: https://aistudio.google.com/apikey")
|
|
223
|
+
|
|
224
|
+
print("\n2. Configure the API key (choose one method):")
|
|
225
|
+
|
|
226
|
+
print(f"\n Option A: User global config (recommended)")
|
|
227
|
+
print(f" $ echo 'GEMINI_API_KEY=your-api-key-here' >> ~/.claude/.env")
|
|
228
|
+
|
|
229
|
+
script_dir = Path(__file__).parent
|
|
230
|
+
skill_dir = script_dir.parent
|
|
231
|
+
|
|
232
|
+
print(f"\n Option B: Skill-specific config")
|
|
233
|
+
print(f" $ cd {skill_dir}")
|
|
234
|
+
print(f" $ cp .env.example .env")
|
|
235
|
+
print(f" $ # Edit .env and add your API key")
|
|
236
|
+
|
|
237
|
+
print(f"\n Option C: Runtime environment (temporary)")
|
|
238
|
+
print(f" $ export GEMINI_API_KEY='your-api-key-here'")
|
|
239
|
+
|
|
240
|
+
print("\n3. Verify setup:")
|
|
241
|
+
print(f" $ python {Path(__file__)}")
|
|
242
|
+
|
|
243
|
+
print("\n4. Debug if needed:")
|
|
244
|
+
print(f" $ python ~/.claude/scripts/resolve_env.py --show-hierarchy --skill ai-multimodal")
|
|
245
|
+
print(f" $ python ~/.claude/scripts/resolve_env.py GEMINI_API_KEY --skill ai-multimodal --verbose")
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def main():
|
|
249
|
+
"""Run all setup checks."""
|
|
250
|
+
print(f"\n{BOLD}AI Multimodal Skill - Setup Checker{RESET}")
|
|
251
|
+
|
|
252
|
+
all_passed = True
|
|
253
|
+
|
|
254
|
+
# Check directory structure
|
|
255
|
+
if not check_directory_structure():
|
|
256
|
+
all_passed = False
|
|
257
|
+
|
|
258
|
+
# Check centralized resolver
|
|
259
|
+
check_centralized_resolver()
|
|
260
|
+
|
|
261
|
+
# Check dependencies
|
|
262
|
+
if not check_dependencies():
|
|
263
|
+
all_passed = False
|
|
264
|
+
provide_setup_instructions()
|
|
265
|
+
sys.exit(1)
|
|
266
|
+
|
|
267
|
+
# Check API key
|
|
268
|
+
api_key = find_api_key()
|
|
269
|
+
|
|
270
|
+
if not api_key:
|
|
271
|
+
print_error("\n❌ GEMINI_API_KEY not found in any location")
|
|
272
|
+
all_passed = False
|
|
273
|
+
provide_setup_instructions()
|
|
274
|
+
sys.exit(1)
|
|
275
|
+
|
|
276
|
+
# Validate API key format
|
|
277
|
+
if not validate_api_key_format(api_key):
|
|
278
|
+
all_passed = False
|
|
279
|
+
|
|
280
|
+
# Test API connection
|
|
281
|
+
if not test_api_connection(api_key):
|
|
282
|
+
all_passed = False
|
|
283
|
+
|
|
284
|
+
# Final summary
|
|
285
|
+
print_header("Setup Summary")
|
|
286
|
+
|
|
287
|
+
if all_passed:
|
|
288
|
+
print_success("✅ All checks passed! The ai-multimodal skill is ready to use.")
|
|
289
|
+
print_info("\nNext steps:")
|
|
290
|
+
print(" • Read SKILL.md for usage examples")
|
|
291
|
+
print(" • Try: python scripts/gemini_batch_process.py --help")
|
|
292
|
+
print("\nImage generation models:")
|
|
293
|
+
print(" • gemini-2.5-flash-image - Nano Banana Flash (DEFAULT - fast)")
|
|
294
|
+
print(" • imagen-4.0-generate-001 - Imagen 4 (alternative - production)")
|
|
295
|
+
print(" • gemini-3-pro-image-preview - Nano Banana Pro (4K text, reasoning)")
|
|
296
|
+
print("\nExample (uses default model):")
|
|
297
|
+
print(" python scripts/gemini_batch_process.py --task generate \\")
|
|
298
|
+
print(" --prompt 'A sunset over mountains' --aspect-ratio 16:9 --size 2K")
|
|
299
|
+
else:
|
|
300
|
+
print_error("❌ Some checks failed. Please fix the issues above.")
|
|
301
|
+
sys.exit(1)
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
if __name__ == '__main__':
|
|
305
|
+
main()
|
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Convert documents to Markdown using Gemini API.
|
|
4
|
+
|
|
5
|
+
Supports all document types:
|
|
6
|
+
- PDF documents (native vision processing)
|
|
7
|
+
- Images (JPEG, PNG, WEBP, HEIC)
|
|
8
|
+
- Office documents (DOCX, XLSX, PPTX)
|
|
9
|
+
- HTML, TXT, and other text formats
|
|
10
|
+
|
|
11
|
+
Features:
|
|
12
|
+
- Converts to clean markdown format
|
|
13
|
+
- Preserves structure, tables, and formatting
|
|
14
|
+
- Extracts text from images and scanned documents
|
|
15
|
+
- Batch conversion support
|
|
16
|
+
- Saves to docs/assets/document-extraction.md by default
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import argparse
|
|
20
|
+
import os
|
|
21
|
+
import sys
|
|
22
|
+
import time
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
from typing import Optional, List, Dict, Any
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
from google import genai
|
|
28
|
+
from google.genai import types
|
|
29
|
+
except ImportError:
|
|
30
|
+
print("Error: google-genai package not installed")
|
|
31
|
+
print("Install with: pip install google-genai")
|
|
32
|
+
sys.exit(1)
|
|
33
|
+
|
|
34
|
+
try:
|
|
35
|
+
from dotenv import load_dotenv
|
|
36
|
+
except ImportError:
|
|
37
|
+
load_dotenv = None
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def find_api_key() -> Optional[str]:
|
|
41
|
+
"""Find Gemini API key using correct priority order.
|
|
42
|
+
|
|
43
|
+
Priority order (highest to lowest):
|
|
44
|
+
1. process.env (runtime environment variables)
|
|
45
|
+
2. .claude/skills/ai-multimodal/.env (skill-specific config)
|
|
46
|
+
3. .claude/skills/.env (shared skills config)
|
|
47
|
+
4. .claude/.env (Claude global config)
|
|
48
|
+
"""
|
|
49
|
+
# Priority 1: Already in process.env (highest)
|
|
50
|
+
api_key = os.getenv('GEMINI_API_KEY')
|
|
51
|
+
if api_key:
|
|
52
|
+
return api_key
|
|
53
|
+
|
|
54
|
+
# Load .env files if dotenv available
|
|
55
|
+
if load_dotenv:
|
|
56
|
+
# Determine base paths
|
|
57
|
+
script_dir = Path(__file__).parent
|
|
58
|
+
skill_dir = script_dir.parent # .claude/skills/ai-multimodal
|
|
59
|
+
skills_dir = skill_dir.parent # .claude/skills
|
|
60
|
+
claude_dir = skills_dir.parent # .claude
|
|
61
|
+
|
|
62
|
+
# Priority 2: Skill-specific .env
|
|
63
|
+
env_file = skill_dir / '.env'
|
|
64
|
+
if env_file.exists():
|
|
65
|
+
load_dotenv(env_file)
|
|
66
|
+
api_key = os.getenv('GEMINI_API_KEY')
|
|
67
|
+
if api_key:
|
|
68
|
+
return api_key
|
|
69
|
+
|
|
70
|
+
# Priority 3: Shared skills .env
|
|
71
|
+
env_file = skills_dir / '.env'
|
|
72
|
+
if env_file.exists():
|
|
73
|
+
load_dotenv(env_file)
|
|
74
|
+
api_key = os.getenv('GEMINI_API_KEY')
|
|
75
|
+
if api_key:
|
|
76
|
+
return api_key
|
|
77
|
+
|
|
78
|
+
# Priority 4: Claude global .env
|
|
79
|
+
env_file = claude_dir / '.env'
|
|
80
|
+
if env_file.exists():
|
|
81
|
+
load_dotenv(env_file)
|
|
82
|
+
api_key = os.getenv('GEMINI_API_KEY')
|
|
83
|
+
if api_key:
|
|
84
|
+
return api_key
|
|
85
|
+
|
|
86
|
+
return None
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def find_project_root() -> Path:
|
|
90
|
+
"""Find project root directory."""
|
|
91
|
+
script_dir = Path(__file__).parent
|
|
92
|
+
|
|
93
|
+
# Look for .git or .claude directory
|
|
94
|
+
for parent in [script_dir] + list(script_dir.parents):
|
|
95
|
+
if (parent / '.git').exists() or (parent / '.claude').exists():
|
|
96
|
+
return parent
|
|
97
|
+
|
|
98
|
+
return script_dir
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def get_mime_type(file_path: str) -> str:
|
|
102
|
+
"""Determine MIME type from file extension."""
|
|
103
|
+
ext = Path(file_path).suffix.lower()
|
|
104
|
+
|
|
105
|
+
mime_types = {
|
|
106
|
+
# Documents
|
|
107
|
+
'.pdf': 'application/pdf',
|
|
108
|
+
'.txt': 'text/plain',
|
|
109
|
+
'.html': 'text/html',
|
|
110
|
+
'.htm': 'text/html',
|
|
111
|
+
'.md': 'text/markdown',
|
|
112
|
+
'.csv': 'text/csv',
|
|
113
|
+
# Images
|
|
114
|
+
'.jpg': 'image/jpeg',
|
|
115
|
+
'.jpeg': 'image/jpeg',
|
|
116
|
+
'.png': 'image/png',
|
|
117
|
+
'.webp': 'image/webp',
|
|
118
|
+
'.heic': 'image/heic',
|
|
119
|
+
'.heif': 'image/heif',
|
|
120
|
+
# Office (need to be uploaded as binary)
|
|
121
|
+
'.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
122
|
+
'.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
123
|
+
'.pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return mime_types.get(ext, 'application/octet-stream')
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def upload_file(client: genai.Client, file_path: str, verbose: bool = False) -> Any:
|
|
130
|
+
"""Upload file to Gemini File API."""
|
|
131
|
+
if verbose:
|
|
132
|
+
print(f"Uploading {file_path}...")
|
|
133
|
+
|
|
134
|
+
myfile = client.files.upload(file=file_path)
|
|
135
|
+
|
|
136
|
+
# Wait for processing if needed
|
|
137
|
+
max_wait = 300 # 5 minutes
|
|
138
|
+
elapsed = 0
|
|
139
|
+
while myfile.state.name == 'PROCESSING' and elapsed < max_wait:
|
|
140
|
+
time.sleep(2)
|
|
141
|
+
myfile = client.files.get(name=myfile.name)
|
|
142
|
+
elapsed += 2
|
|
143
|
+
if verbose and elapsed % 10 == 0:
|
|
144
|
+
print(f" Processing... {elapsed}s")
|
|
145
|
+
|
|
146
|
+
if myfile.state.name == 'FAILED':
|
|
147
|
+
raise ValueError(f"File processing failed: {file_path}")
|
|
148
|
+
|
|
149
|
+
if myfile.state.name == 'PROCESSING':
|
|
150
|
+
raise TimeoutError(f"Processing timeout after {max_wait}s: {file_path}")
|
|
151
|
+
|
|
152
|
+
if verbose:
|
|
153
|
+
print(f" Uploaded: {myfile.name}")
|
|
154
|
+
|
|
155
|
+
return myfile
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def convert_to_markdown(
|
|
159
|
+
client: genai.Client,
|
|
160
|
+
file_path: str,
|
|
161
|
+
model: str = 'gemini-2.5-flash',
|
|
162
|
+
custom_prompt: Optional[str] = None,
|
|
163
|
+
verbose: bool = False,
|
|
164
|
+
max_retries: int = 3
|
|
165
|
+
) -> Dict[str, Any]:
|
|
166
|
+
"""Convert a document to markdown using Gemini."""
|
|
167
|
+
|
|
168
|
+
for attempt in range(max_retries):
|
|
169
|
+
try:
|
|
170
|
+
file_path_obj = Path(file_path)
|
|
171
|
+
file_size = file_path_obj.stat().st_size
|
|
172
|
+
use_file_api = file_size > 20 * 1024 * 1024 # >20MB
|
|
173
|
+
|
|
174
|
+
# Default prompt for markdown conversion
|
|
175
|
+
if custom_prompt:
|
|
176
|
+
prompt = custom_prompt
|
|
177
|
+
else:
|
|
178
|
+
prompt = """Convert this document to clean, well-formatted Markdown.
|
|
179
|
+
|
|
180
|
+
Requirements:
|
|
181
|
+
- Preserve all content, structure, and formatting
|
|
182
|
+
- Convert tables to markdown table format
|
|
183
|
+
- Maintain heading hierarchy (# ## ### etc)
|
|
184
|
+
- Preserve lists, code blocks, and quotes
|
|
185
|
+
- Extract text from images if present
|
|
186
|
+
- Keep formatting consistent and readable
|
|
187
|
+
|
|
188
|
+
Output only the markdown content without any preamble or explanation."""
|
|
189
|
+
|
|
190
|
+
# Upload or inline the file
|
|
191
|
+
if use_file_api:
|
|
192
|
+
myfile = upload_file(client, str(file_path), verbose)
|
|
193
|
+
content = [prompt, myfile]
|
|
194
|
+
else:
|
|
195
|
+
with open(file_path, 'rb') as f:
|
|
196
|
+
file_bytes = f.read()
|
|
197
|
+
|
|
198
|
+
mime_type = get_mime_type(str(file_path))
|
|
199
|
+
content = [
|
|
200
|
+
prompt,
|
|
201
|
+
types.Part.from_bytes(data=file_bytes, mime_type=mime_type)
|
|
202
|
+
]
|
|
203
|
+
|
|
204
|
+
# Generate markdown
|
|
205
|
+
response = client.models.generate_content(
|
|
206
|
+
model=model,
|
|
207
|
+
contents=content
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
markdown_content = response.text if hasattr(response, 'text') else ''
|
|
211
|
+
|
|
212
|
+
return {
|
|
213
|
+
'file': str(file_path),
|
|
214
|
+
'status': 'success',
|
|
215
|
+
'markdown': markdown_content
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
except Exception as e:
|
|
219
|
+
if attempt == max_retries - 1:
|
|
220
|
+
return {
|
|
221
|
+
'file': str(file_path),
|
|
222
|
+
'status': 'error',
|
|
223
|
+
'error': str(e),
|
|
224
|
+
'markdown': None
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
wait_time = 2 ** attempt
|
|
228
|
+
if verbose:
|
|
229
|
+
print(f" Retry {attempt + 1} after {wait_time}s: {e}")
|
|
230
|
+
time.sleep(wait_time)
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def batch_convert(
|
|
234
|
+
files: List[str],
|
|
235
|
+
output_file: Optional[str] = None,
|
|
236
|
+
auto_name: bool = False,
|
|
237
|
+
model: str = 'gemini-2.5-flash',
|
|
238
|
+
custom_prompt: Optional[str] = None,
|
|
239
|
+
verbose: bool = False
|
|
240
|
+
) -> List[Dict[str, Any]]:
|
|
241
|
+
"""Batch convert multiple files to markdown."""
|
|
242
|
+
|
|
243
|
+
api_key = find_api_key()
|
|
244
|
+
if not api_key:
|
|
245
|
+
print("Error: GEMINI_API_KEY not found")
|
|
246
|
+
print("Set via: export GEMINI_API_KEY='your-key'")
|
|
247
|
+
print("Or create .env file with: GEMINI_API_KEY=your-key")
|
|
248
|
+
sys.exit(1)
|
|
249
|
+
|
|
250
|
+
client = genai.Client(api_key=api_key)
|
|
251
|
+
results = []
|
|
252
|
+
|
|
253
|
+
# Determine output path
|
|
254
|
+
if not output_file:
|
|
255
|
+
project_root = find_project_root()
|
|
256
|
+
output_dir = project_root / 'docs' / 'assets'
|
|
257
|
+
|
|
258
|
+
if auto_name and len(files) == 1:
|
|
259
|
+
# Auto-generate meaningful filename from input
|
|
260
|
+
input_path = Path(files[0])
|
|
261
|
+
base_name = input_path.stem
|
|
262
|
+
output_file = str(output_dir / f"{base_name}-extraction.md")
|
|
263
|
+
else:
|
|
264
|
+
output_file = str(output_dir / 'document-extraction.md')
|
|
265
|
+
|
|
266
|
+
output_path = Path(output_file)
|
|
267
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
268
|
+
|
|
269
|
+
# Process each file
|
|
270
|
+
for i, file_path in enumerate(files, 1):
|
|
271
|
+
if verbose:
|
|
272
|
+
print(f"\n[{i}/{len(files)}] Converting: {file_path}")
|
|
273
|
+
|
|
274
|
+
result = convert_to_markdown(
|
|
275
|
+
client=client,
|
|
276
|
+
file_path=file_path,
|
|
277
|
+
model=model,
|
|
278
|
+
custom_prompt=custom_prompt,
|
|
279
|
+
verbose=verbose
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
results.append(result)
|
|
283
|
+
|
|
284
|
+
if verbose:
|
|
285
|
+
status = result.get('status', 'unknown')
|
|
286
|
+
print(f" Status: {status}")
|
|
287
|
+
|
|
288
|
+
# Save combined markdown
|
|
289
|
+
with open(output_path, 'w', encoding='utf-8') as f:
|
|
290
|
+
f.write("# Document Extraction Results\n\n")
|
|
291
|
+
f.write(f"Converted {len(files)} document(s) to markdown.\n\n")
|
|
292
|
+
f.write("---\n\n")
|
|
293
|
+
|
|
294
|
+
for result in results:
|
|
295
|
+
f.write(f"## {Path(result['file']).name}\n\n")
|
|
296
|
+
|
|
297
|
+
if result['status'] == 'success' and result.get('markdown'):
|
|
298
|
+
f.write(result['markdown'])
|
|
299
|
+
f.write("\n\n")
|
|
300
|
+
elif result['status'] == 'success':
|
|
301
|
+
f.write("**Note**: Conversion succeeded but no content was returned.\n\n")
|
|
302
|
+
else:
|
|
303
|
+
f.write(f"**Error**: {result.get('error', 'Unknown error')}\n\n")
|
|
304
|
+
|
|
305
|
+
f.write("---\n\n")
|
|
306
|
+
|
|
307
|
+
if verbose or True: # Always show output location
|
|
308
|
+
print(f"\n{'='*50}")
|
|
309
|
+
print(f"Converted: {len(results)} file(s)")
|
|
310
|
+
print(f"Success: {sum(1 for r in results if r['status'] == 'success')}")
|
|
311
|
+
print(f"Failed: {sum(1 for r in results if r['status'] == 'error')}")
|
|
312
|
+
print(f"Output saved to: {output_path}")
|
|
313
|
+
|
|
314
|
+
return results
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def main():
|
|
318
|
+
parser = argparse.ArgumentParser(
|
|
319
|
+
description='Convert documents to Markdown using Gemini API',
|
|
320
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
321
|
+
epilog="""
|
|
322
|
+
Examples:
|
|
323
|
+
# Convert single PDF to markdown (default name)
|
|
324
|
+
%(prog)s --input document.pdf
|
|
325
|
+
|
|
326
|
+
# Auto-generate meaningful filename
|
|
327
|
+
%(prog)s --input testpdf.pdf --auto-name
|
|
328
|
+
# Output: docs/assets/testpdf-extraction.md
|
|
329
|
+
|
|
330
|
+
# Convert multiple files
|
|
331
|
+
%(prog)s --input doc1.pdf doc2.docx image.png
|
|
332
|
+
|
|
333
|
+
# Specify custom output location
|
|
334
|
+
%(prog)s --input document.pdf --output ./output.md
|
|
335
|
+
|
|
336
|
+
# Use custom prompt
|
|
337
|
+
%(prog)s --input document.pdf --prompt "Extract only the tables as markdown"
|
|
338
|
+
|
|
339
|
+
# Batch convert directory
|
|
340
|
+
%(prog)s --input ./documents/*.pdf --verbose
|
|
341
|
+
|
|
342
|
+
Supported formats:
|
|
343
|
+
- PDF documents (up to 1,000 pages)
|
|
344
|
+
- Images (JPEG, PNG, WEBP, HEIC)
|
|
345
|
+
- Office documents (DOCX, XLSX, PPTX)
|
|
346
|
+
- Text formats (TXT, HTML, Markdown, CSV)
|
|
347
|
+
|
|
348
|
+
Default output: <project-root>/docs/assets/document-extraction.md
|
|
349
|
+
"""
|
|
350
|
+
)
|
|
351
|
+
|
|
352
|
+
parser.add_argument('--input', '-i', nargs='+', required=True,
|
|
353
|
+
help='Input file(s) to convert')
|
|
354
|
+
parser.add_argument('--output', '-o',
|
|
355
|
+
help='Output markdown file (default: docs/assets/document-extraction.md)')
|
|
356
|
+
parser.add_argument('--auto-name', '-a', action='store_true',
|
|
357
|
+
help='Auto-generate meaningful output filename from input (e.g., document.pdf -> document-extraction.md)')
|
|
358
|
+
parser.add_argument('--model', default='gemini-2.5-flash',
|
|
359
|
+
help='Gemini model to use (default: gemini-2.5-flash)')
|
|
360
|
+
parser.add_argument('--prompt', '-p',
|
|
361
|
+
help='Custom prompt for conversion')
|
|
362
|
+
parser.add_argument('--verbose', '-v', action='store_true',
|
|
363
|
+
help='Verbose output')
|
|
364
|
+
|
|
365
|
+
args = parser.parse_args()
|
|
366
|
+
|
|
367
|
+
# Validate input files
|
|
368
|
+
files = []
|
|
369
|
+
for file_pattern in args.input:
|
|
370
|
+
file_path = Path(file_pattern)
|
|
371
|
+
if file_path.exists() and file_path.is_file():
|
|
372
|
+
files.append(str(file_path))
|
|
373
|
+
else:
|
|
374
|
+
# Try glob pattern
|
|
375
|
+
import glob
|
|
376
|
+
matched = glob.glob(file_pattern)
|
|
377
|
+
files.extend([f for f in matched if Path(f).is_file()])
|
|
378
|
+
|
|
379
|
+
if not files:
|
|
380
|
+
print("Error: No valid input files found")
|
|
381
|
+
sys.exit(1)
|
|
382
|
+
|
|
383
|
+
# Convert files
|
|
384
|
+
batch_convert(
|
|
385
|
+
files=files,
|
|
386
|
+
output_file=args.output,
|
|
387
|
+
auto_name=args.auto_name,
|
|
388
|
+
model=args.model,
|
|
389
|
+
custom_prompt=args.prompt,
|
|
390
|
+
verbose=args.verbose
|
|
391
|
+
)
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
if __name__ == '__main__':
|
|
395
|
+
main()
|