├── testdata ├── skills │ ├── .gitignore │ ├── mcp-builder │ │ ├── scripts │ │ │ ├── requirements.txt │ │ │ └── example_evaluation.xml │ │ └── mcp-builder │ │ │ └── scripts │ │ │ ├── requirements.txt │ │ │ └── example_evaluation.xml │ ├── document-skills │ │ ├── docx │ │ │ ├── scripts │ │ │ │ ├── __init__.py │ │ │ │ └── templates │ │ │ │ │ └── people.xml │ │ │ ├── ooxml │ │ │ │ ├── scripts │ │ │ │ │ ├── validation │ │ │ │ │ │ └── __init__.py │ │ │ │ │ ├── unpack.py │ │ │ │ │ └── validate.py │ │ │ │ └── schemas │ │ │ │ │ ├── ISO-IEC29500-4_2016 │ │ │ │ │ ├── vml-presentationDrawing.xsd │ │ │ │ │ ├── dml-lockedCanvas.xsd │ │ │ │ │ ├── shared-customXmlSchemaProperties.xsd │ │ │ │ │ ├── dml-picture.xsd │ │ │ │ │ ├── shared-customXmlDataProperties.xsd │ │ │ │ │ ├── shared-additionalCharacteristics.xsd │ │ │ │ │ └── shared-relationshipReference.xsd │ │ │ │ │ ├── microsoft │ │ │ │ │ ├── wml-sdtdatahash-2020.xsd │ │ │ │ │ ├── wml-symex-2015.xsd │ │ │ │ │ ├── wml-2018.xsd │ │ │ │ │ ├── wml-cid-2016.xsd │ │ │ │ │ └── wml-cex-2018.xsd │ │ │ │ │ └── ecma │ │ │ │ │ └── fouth-edition │ │ │ │ │ ├── opc-relationships.xsd │ │ │ │ │ └── opc-contentTypes.xsd │ │ │ └── LICENSE.txt │ │ ├── document-skills │ │ │ ├── docx │ │ │ │ ├── scripts │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── templates │ │ │ │ │ │ └── people.xml │ │ │ │ ├── ooxml │ │ │ │ │ ├── scripts │ │ │ │ │ │ ├── validation │ │ │ │ │ │ │ └── __init__.py │ │ │ │ │ │ ├── unpack.py │ │ │ │ │ │ └── validate.py │ │ │ │ │ └── schemas │ │ │ │ │ │ ├── ISO-IEC29500-4_2016 │ │ │ │ │ │ ├── vml-presentationDrawing.xsd │ │ │ │ │ │ ├── dml-lockedCanvas.xsd │ │ │ │ │ │ ├── shared-customXmlSchemaProperties.xsd │ │ │ │ │ │ ├── dml-picture.xsd │ │ │ │ │ │ ├── shared-customXmlDataProperties.xsd │ │ │ │ │ │ ├── shared-additionalCharacteristics.xsd │ │ │ │ │ │ └── shared-relationshipReference.xsd │ │ │ │ │ │ ├── microsoft │ │ │ │ │ │ ├── wml-sdtdatahash-2020.xsd │ │ │ │ │ │ ├── wml-symex-2015.xsd │ │ │ │ │ │ ├── wml-2018.xsd │ │ │ │ │ │ ├── wml-cid-2016.xsd │ │ │ │ │ │ └── wml-cex-2018.xsd │ │ │ │ │ │ └── ecma │ │ │ │ │ │ └── fouth-edition │ │ │ │ │ │ ├── opc-relationships.xsd │ │ │ │ │ │ └── opc-contentTypes.xsd │ │ │ │ └── LICENSE.txt │ │ │ ├── pptx │ │ │ │ ├── ooxml │ │ │ │ │ ├── scripts │ │ │ │ │ │ ├── validation │ │ │ │ │ │ │ └── __init__.py │ │ │ │ │ │ ├── unpack.py │ │ │ │ │ │ └── validate.py │ │ │ │ │ └── schemas │ │ │ │ │ │ ├── ISO-IEC29500-4_2016 │ │ │ │ │ │ ├── vml-presentationDrawing.xsd │ │ │ │ │ │ ├── dml-lockedCanvas.xsd │ │ │ │ │ │ ├── shared-customXmlSchemaProperties.xsd │ │ │ │ │ │ ├── dml-picture.xsd │ │ │ │ │ │ ├── shared-customXmlDataProperties.xsd │ │ │ │ │ │ ├── shared-additionalCharacteristics.xsd │ │ │ │ │ │ └── shared-relationshipReference.xsd │ │ │ │ │ │ ├── microsoft │ │ │ │ │ │ ├── wml-sdtdatahash-2020.xsd │ │ │ │ │ │ ├── wml-symex-2015.xsd │ │ │ │ │ │ ├── wml-2018.xsd │ │ │ │ │ │ ├── wml-cid-2016.xsd │ │ │ │ │ │ └── wml-cex-2018.xsd │ │ │ │ │ │ └── ecma │ │ │ │ │ │ └── fouth-edition │ │ │ │ │ │ ├── opc-relationships.xsd │ │ │ │ │ │ └── opc-contentTypes.xsd │ │ │ │ └── LICENSE.txt │ │ │ ├── pdf │ │ │ │ ├── scripts │ │ │ │ │ ├── check_fillable_fields.py │ │ │ │ │ ├── convert_pdf_to_images.py │ │ │ │ │ └── create_validation_image.py │ │ │ │ └── LICENSE.txt │ │ │ └── xlsx │ │ │ │ └── LICENSE.txt │ │ ├── pptx │ │ │ ├── ooxml │ │ │ │ ├── scripts │ │ │ │ │ ├── validation │ │ │ │ │ │ └── __init__.py │ │ │ │ │ ├── unpack.py │ │ │ │ │ └── validate.py │ │ │ │ └── schemas │ │ │ │ │ ├── ISO-IEC29500-4_2016 │ │ │ │ │ ├── vml-presentationDrawing.xsd │ │ │ │ │ ├── dml-lockedCanvas.xsd │ │ │ │ │ ├── shared-customXmlSchemaProperties.xsd │ │ │ │ │ ├── dml-picture.xsd │ │ │ │ │ ├── shared-customXmlDataProperties.xsd │ │ │ │ │ ├── shared-additionalCharacteristics.xsd │ │ │ │ │ └── shared-relationshipReference.xsd │ │ │ │ │ ├── microsoft │ │ │ │ │ ├── wml-sdtdatahash-2020.xsd │ │ │ │ │ ├── wml-symex-2015.xsd │ │ │ │ │ ├── wml-2018.xsd │ │ │ │ │ ├── wml-cid-2016.xsd │ │ │ │ │ └── wml-cex-2018.xsd │ │ │ │ │ └── ecma │ │ │ │ │ └── fouth-edition │ │ │ │ │ ├── opc-relationships.xsd │ │ │ │ │ └── opc-contentTypes.xsd │ │ │ └── LICENSE.txt │ │ ├── pdf │ │ │ ├── scripts │ │ │ │ ├── check_fillable_fields.py │ │ │ │ ├── convert_pdf_to_images.py │ │ │ │ └── create_validation_image.py │ │ │ └── LICENSE.txt │ │ └── xlsx │ │ │ └── LICENSE.txt │ ├── slack-gif-creator │ │ └── requirements.txt │ ├── code-review │ │ └── code-review.zip │ ├── podcast │ │ └── podcast-generator.skill │ ├── theme-factory │ │ ├── theme-showcase.pdf │ │ └── themes │ │ │ ├── desert-rose.md │ │ │ ├── forest-canopy.md │ │ │ ├── midnight-galaxy.md │ │ │ ├── botanical-garden.md │ │ │ ├── golden-hour.md │ │ │ ├── arctic-frost.md │ │ │ ├── tech-innovation.md │ │ │ ├── modern-minimalist.md │ │ │ ├── ocean-depths.md │ │ │ └── sunset-boulevard.md │ ├── canvas-design │ │ └── canvas-fonts │ │ │ ├── Jura-Light.ttf │ │ │ ├── Lora-Bold.ttf │ │ │ ├── Jura-Medium.ttf │ │ │ ├── Lora-Italic.ttf │ │ │ ├── Lora-Regular.ttf │ │ │ ├── Outfit-Bold.ttf │ │ │ ├── CrimsonPro-Bold.ttf │ │ │ ├── DMMono-Regular.ttf │ │ │ ├── GeistMono-Bold.ttf │ │ │ ├── Gloock-Regular.ttf │ │ │ ├── Lora-BoldItalic.ttf │ │ │ ├── Outfit-Regular.ttf │ │ │ ├── RedHatMono-Bold.ttf │ │ │ ├── Tektur-Medium.ttf │ │ │ ├── Tektur-Regular.ttf │ │ │ ├── WorkSans-Bold.ttf │ │ │ ├── WorkSans-Italic.ttf │ │ │ ├── ArsenalSC-Regular.ttf │ │ │ ├── BigShoulders-Bold.ttf │ │ │ ├── Boldonse-Regular.ttf │ │ │ ├── CrimsonPro-Italic.ttf │ │ │ ├── EricaOne-Regular.ttf │ │ │ ├── GeistMono-Regular.ttf │ │ │ ├── IBMPlexMono-Bold.ttf │ │ │ ├── IBMPlexSerif-Bold.ttf │ │ │ ├── Italiana-Regular.ttf │ │ │ ├── NationalPark-Bold.ttf │ │ │ ├── PoiretOne-Regular.ttf │ │ │ ├── SmoochSans-Medium.ttf │ │ │ ├── WorkSans-Regular.ttf │ │ │ ├── BigShoulders-Regular.ttf │ │ │ ├── CrimsonPro-Regular.ttf │ │ │ ├── IBMPlexMono-Regular.ttf │ │ │ ├── IBMPlexSerif-Italic.ttf │ │ │ ├── IBMPlexSerif-Regular.ttf │ │ │ ├── InstrumentSans-Bold.ttf │ │ │ ├── JetBrainsMono-Bold.ttf │ │ │ ├── NationalPark-Regular.ttf │ │ │ ├── PixelifySans-Medium.ttf │ │ │ ├── RedHatMono-Regular.ttf │ │ │ ├── Silkscreen-Regular.ttf │ │ │ ├── WorkSans-BoldItalic.ttf │ │ │ ├── YoungSerif-Regular.ttf │ │ │ ├── InstrumentSans-Italic.ttf │ │ │ ├── InstrumentSans-Regular.ttf │ │ │ ├── InstrumentSerif-Italic.ttf │ │ │ ├── JetBrainsMono-Regular.ttf │ │ │ ├── BricolageGrotesque-Bold.ttf │ │ │ ├── IBMPlexSerif-BoldItalic.ttf │ │ │ ├── InstrumentSans-BoldItalic.ttf │ │ │ ├── InstrumentSerif-Regular.ttf │ │ │ ├── LibreBaskerville-Regular.ttf │ │ │ ├── NothingYouCouldDo-Regular.ttf │ │ │ └── BricolageGrotesque-Regular.ttf │ ├── artifacts-builder │ │ └── scripts │ │ │ ├── shadcn-components.tar.gz │ │ │ └── bundle-artifact.sh │ ├── template-skill │ │ └── SKILL.md │ ├── skill-creator │ │ └── scripts │ │ │ ├── __pycache__ │ │ │ └── quick_validate.cpython-313.pyc │ │ │ └── quick_validate.py │ ├── markitdown │ │ └── scripts │ │ │ └── convert_webpage.py │ ├── failure-test │ │ └── skill.json │ ├── error-demo │ │ └── skill.json │ ├── react-component-generator │ │ └── assets │ │ │ ├── BasicComponent.tsx │ │ │ ├── CardComponent.tsx │ │ │ ├── ListComponent.tsx │ │ │ └── StatefulComponent.tsx │ ├── internal-comms │ │ ├── examples │ │ │ ├── general-comms.md │ │ │ └── faq-answers.md │ │ └── SKILL.md │ ├── webapp-testing │ │ └── examples │ │ │ ├── static_html_automation.py │ │ │ ├── console_logging.py │ │ │ └── element_discovery.py │ ├── .claude-plugin │ │ └── marketplace.json │ ├── agent_skills_spec.md │ └── brand-guidelines │ │ └── SKILL.md ├── oai-skills │ ├── README.md │ └── spreadsheets │ │ └── examples │ │ └── features │ │ ├── change_existing_charts.py │ │ ├── cite_cells.py │ │ ├── set_merge_cells.py │ │ ├── create_tables.py │ │ ├── create_line_chart.py │ │ ├── create_area_chart.py │ │ ├── set_cell_width_height.py │ │ ├── create_pie_chart.py │ │ ├── create_doughnut_chart.py │ │ └── create_bar_chart.py └── mcp │ └── mcp.json ├── cmd └── goskills-cli │ ├── main.go │ ├── root.go │ ├── list.go │ ├── files.go │ ├── search.go │ └── detail.go ├── _website └── images │ ├── agent_web.png │ ├── agent_output.png │ ├── agent_plan.png │ ├── agent_report.png │ ├── agent_search.png │ └── agent_worflow.png ├── .github └── workflows │ └── go.yml ├── tool ├── file_tool.go ├── shell_tool.go ├── web_tool.go ├── test_all.sh ├── python_tool.go └── knowledge_tool.go ├── .gitignore ├── go.mod ├── .goreleaser.yaml ├── LICENSE ├── mcp └── config.go ├── CHANGELOG.md └── log └── golog_logger.go /testdata/skills/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | -------------------------------------------------------------------------------- /cmd/goskills-cli/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | Execute() 5 | } 6 | -------------------------------------------------------------------------------- /testdata/skills/mcp-builder/scripts/requirements.txt: -------------------------------------------------------------------------------- 1 | anthropic>=0.39.0 2 | mcp>=1.1.0 3 | -------------------------------------------------------------------------------- /testdata/skills/mcp-builder/mcp-builder/scripts/requirements.txt: -------------------------------------------------------------------------------- 1 | anthropic>=0.39.0 2 | mcp>=1.1.0 3 | -------------------------------------------------------------------------------- /_website/images/agent_web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/_website/images/agent_web.png -------------------------------------------------------------------------------- /_website/images/agent_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/_website/images/agent_output.png -------------------------------------------------------------------------------- /_website/images/agent_plan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/_website/images/agent_plan.png -------------------------------------------------------------------------------- /_website/images/agent_report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/_website/images/agent_report.png -------------------------------------------------------------------------------- /_website/images/agent_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/_website/images/agent_search.png -------------------------------------------------------------------------------- /_website/images/agent_worflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/_website/images/agent_worflow.png -------------------------------------------------------------------------------- /testdata/skills/document-skills/docx/scripts/__init__.py: -------------------------------------------------------------------------------- 1 | # Make scripts directory a package for relative imports in tests 2 | -------------------------------------------------------------------------------- /testdata/skills/slack-gif-creator/requirements.txt: -------------------------------------------------------------------------------- 1 | pillow>=10.0.0 2 | imageio>=2.31.0 3 | imageio-ffmpeg>=0.4.9 4 | numpy>=1.24.0 -------------------------------------------------------------------------------- /testdata/skills/code-review/code-review.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/code-review/code-review.zip -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/docx/scripts/__init__.py: -------------------------------------------------------------------------------- 1 | # Make scripts directory a package for relative imports in tests 2 | -------------------------------------------------------------------------------- /testdata/skills/podcast/podcast-generator.skill: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/podcast/podcast-generator.skill -------------------------------------------------------------------------------- /testdata/skills/theme-factory/theme-showcase.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/theme-factory/theme-showcase.pdf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/Jura-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/Jura-Light.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/Lora-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/Lora-Bold.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/Jura-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/Jura-Medium.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/Lora-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/Lora-Italic.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/Lora-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/Lora-Regular.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/Outfit-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/Outfit-Bold.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/DMMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/DMMono-Regular.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/GeistMono-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/GeistMono-Bold.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/Gloock-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/Gloock-Regular.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/Outfit-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/Outfit-Regular.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/RedHatMono-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/RedHatMono-Bold.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/Tektur-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/Tektur-Medium.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/Tektur-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/Tektur-Regular.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/WorkSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/WorkSans-Bold.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/WorkSans-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/WorkSans-Italic.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/BigShoulders-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/BigShoulders-Bold.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/Boldonse-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/Boldonse-Regular.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/EricaOne-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/EricaOne-Regular.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/GeistMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/GeistMono-Regular.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/Italiana-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/Italiana-Regular.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/NationalPark-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/NationalPark-Bold.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/PoiretOne-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/PoiretOne-Regular.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/SmoochSans-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/SmoochSans-Medium.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/WorkSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/WorkSans-Regular.ttf -------------------------------------------------------------------------------- /testdata/skills/artifacts-builder/scripts/shadcn-components.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/artifacts-builder/scripts/shadcn-components.tar.gz -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/BigShoulders-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/BigShoulders-Regular.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/NationalPark-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/NationalPark-Regular.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/PixelifySans-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/PixelifySans-Medium.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/RedHatMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/RedHatMono-Regular.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/Silkscreen-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/Silkscreen-Regular.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf -------------------------------------------------------------------------------- /testdata/skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf -------------------------------------------------------------------------------- /testdata/skills/template-skill/SKILL.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: template-skill 3 | description: Replace with description of the skill and when Claude should use it. 4 | --- 5 | 6 | # Insert instructions below 7 | -------------------------------------------------------------------------------- /testdata/skills/skill-creator/scripts/__pycache__/quick_validate.cpython-313.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/goskills/HEAD/testdata/skills/skill-creator/scripts/__pycache__/quick_validate.cpython-313.pyc -------------------------------------------------------------------------------- /testdata/skills/document-skills/docx/scripts/templates/people.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/docx/scripts/templates/people.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /testdata/oai-skills/README.md: -------------------------------------------------------------------------------- 1 | # oai-skills 2 | 3 | See [Simon Willison’s blog post](https://simonwillison.net/2025/Dec/12/openai-skills/) for background on this project. 4 | 5 | ## Creating a skills archive with a prompt 6 | 7 | Created by prompting [ChatGPT]([https://claude.ai](https://chatgpt.com/)): 8 | 9 | > `Create a zip file of /home/oai/skills` 10 | > 11 | -------------------------------------------------------------------------------- /testdata/skills/markitdown/scripts/convert_webpage.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from markitdown import MarkItDown 3 | 4 | if len(sys.argv) != 2: 5 | print("Usage: python convert_webpage.py ") 6 | sys.exit(1) 7 | 8 | url = sys.argv[1] 9 | 10 | try: 11 | md = MarkItDown() 12 | result = md.convert(url) 13 | print(result.text_content) 14 | except Exception as e: 15 | print(f"An error occurred: {e}") 16 | sys.exit(1) 17 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/docx/ooxml/scripts/validation/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Validation modules for Word document processing. 3 | """ 4 | 5 | from .base import BaseSchemaValidator 6 | from .docx import DOCXSchemaValidator 7 | from .pptx import PPTXSchemaValidator 8 | from .redlining import RedliningValidator 9 | 10 | __all__ = [ 11 | "BaseSchemaValidator", 12 | "DOCXSchemaValidator", 13 | "PPTXSchemaValidator", 14 | "RedliningValidator", 15 | ] 16 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/pptx/ooxml/scripts/validation/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Validation modules for Word document processing. 3 | """ 4 | 5 | from .base import BaseSchemaValidator 6 | from .docx import DOCXSchemaValidator 7 | from .pptx import PPTXSchemaValidator 8 | from .redlining import RedliningValidator 9 | 10 | __all__ = [ 11 | "BaseSchemaValidator", 12 | "DOCXSchemaValidator", 13 | "PPTXSchemaValidator", 14 | "RedliningValidator", 15 | ] 16 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/pdf/scripts/check_fillable_fields.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from pypdf import PdfReader 3 | 4 | 5 | # Script for Claude to run to determine whether a PDF has fillable form fields. See forms.md. 6 | 7 | 8 | reader = PdfReader(sys.argv[1]) 9 | if (reader.get_fields()): 10 | print("This PDF has fillable form fields") 11 | else: 12 | print("This PDF does not have fillable form fields; you will need to visually determine where to enter data") 13 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/docx/ooxml/scripts/validation/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Validation modules for Word document processing. 3 | """ 4 | 5 | from .base import BaseSchemaValidator 6 | from .docx import DOCXSchemaValidator 7 | from .pptx import PPTXSchemaValidator 8 | from .redlining import RedliningValidator 9 | 10 | __all__ = [ 11 | "BaseSchemaValidator", 12 | "DOCXSchemaValidator", 13 | "PPTXSchemaValidator", 14 | "RedliningValidator", 15 | ] 16 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/pptx/ooxml/scripts/validation/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Validation modules for Word document processing. 3 | """ 4 | 5 | from .base import BaseSchemaValidator 6 | from .docx import DOCXSchemaValidator 7 | from .pptx import PPTXSchemaValidator 8 | from .redlining import RedliningValidator 9 | 10 | __all__ = [ 11 | "BaseSchemaValidator", 12 | "DOCXSchemaValidator", 13 | "PPTXSchemaValidator", 14 | "RedliningValidator", 15 | ] 16 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/pdf/scripts/check_fillable_fields.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from pypdf import PdfReader 3 | 4 | 5 | # Script for Claude to run to determine whether a PDF has fillable form fields. See forms.md. 6 | 7 | 8 | reader = PdfReader(sys.argv[1]) 9 | if (reader.get_fields()): 10 | print("This PDF has fillable form fields") 11 | else: 12 | print("This PDF does not have fillable form fields; you will need to visually determine where to enter data") 13 | -------------------------------------------------------------------------------- /testdata/skills/failure-test/skill.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "failure-test", 3 | "description": "Test skill for failure resolution", 4 | "category": "testing", 5 | "tags": ["test", "failure"], 6 | "prompt": "You are a test skill that demonstrates failure resolution capabilities. You can call various tools that might fail to test the intelligent retry system.", 7 | "tools": [ 8 | "read_file", 9 | "run_shell_code", 10 | "tavily_search", 11 | "web_fetch" 12 | ], 13 | "resources": [] 14 | } -------------------------------------------------------------------------------- /testdata/skills/error-demo/skill.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "error-demo", 3 | "description": "Demonstrates simple error handling by letting LLM see tool errors and recover", 4 | "category": "demo", 5 | "tags": ["demo", "error"], 6 | "prompt": "You are a demonstration skill that shows how the system handles tool errors gracefully. When a tool fails, you'll receive detailed error information and can decide how to recover.", 7 | "tools": [ 8 | "read_file", 9 | "write_file", 10 | "run_shell_code" 11 | ], 12 | "resources": [] 13 | } -------------------------------------------------------------------------------- /testdata/skills/theme-factory/themes/desert-rose.md: -------------------------------------------------------------------------------- 1 | # Desert Rose 2 | 3 | A soft and sophisticated theme with dusty, muted tones perfect for elegant presentations. 4 | 5 | ## Color Palette 6 | 7 | - **Dusty Rose**: `#d4a5a5` - Soft primary color 8 | - **Clay**: `#b87d6d` - Earthy accent 9 | - **Sand**: `#e8d5c4` - Warm neutral backgrounds 10 | - **Deep Burgundy**: `#5d2e46` - Rich dark contrast 11 | 12 | ## Typography 13 | 14 | - **Headers**: FreeSans Bold 15 | - **Body Text**: FreeSans 16 | 17 | ## Best Used For 18 | 19 | Fashion presentations, beauty brands, wedding planning, interior design, boutique businesses. 20 | -------------------------------------------------------------------------------- /testdata/skills/theme-factory/themes/forest-canopy.md: -------------------------------------------------------------------------------- 1 | # Forest Canopy 2 | 3 | A natural and grounded theme featuring earth tones inspired by dense forest environments. 4 | 5 | ## Color Palette 6 | 7 | - **Forest Green**: `#2d4a2b` - Primary dark green 8 | - **Sage**: `#7d8471` - Muted green accent 9 | - **Olive**: `#a4ac86` - Light accent color 10 | - **Ivory**: `#faf9f6` - Backgrounds and text 11 | 12 | ## Typography 13 | 14 | - **Headers**: FreeSerif Bold 15 | - **Body Text**: FreeSans 16 | 17 | ## Best Used For 18 | 19 | Environmental presentations, sustainability reports, outdoor brands, wellness content, organic products. 20 | -------------------------------------------------------------------------------- /testdata/skills/theme-factory/themes/midnight-galaxy.md: -------------------------------------------------------------------------------- 1 | # Midnight Galaxy 2 | 3 | A dramatic and cosmic theme with deep purples and mystical tones for impactful presentations. 4 | 5 | ## Color Palette 6 | 7 | - **Deep Purple**: `#2b1e3e` - Rich dark base 8 | - **Cosmic Blue**: `#4a4e8f` - Mystical mid-tone 9 | - **Lavender**: `#a490c2` - Soft accent color 10 | - **Silver**: `#e6e6fa` - Light highlights and text 11 | 12 | ## Typography 13 | 14 | - **Headers**: FreeSans Bold 15 | - **Body Text**: FreeSans 16 | 17 | ## Best Used For 18 | 19 | Entertainment industry, gaming presentations, nightlife venues, luxury brands, creative agencies. 20 | -------------------------------------------------------------------------------- /testdata/skills/theme-factory/themes/botanical-garden.md: -------------------------------------------------------------------------------- 1 | # Botanical Garden 2 | 3 | A fresh and organic theme featuring vibrant garden-inspired colors for lively presentations. 4 | 5 | ## Color Palette 6 | 7 | - **Fern Green**: `#4a7c59` - Rich natural green 8 | - **Marigold**: `#f9a620` - Bright floral accent 9 | - **Terracotta**: `#b7472a` - Earthy warm tone 10 | - **Cream**: `#f5f3ed` - Soft neutral backgrounds 11 | 12 | ## Typography 13 | 14 | - **Headers**: DejaVu Serif Bold 15 | - **Body Text**: DejaVu Sans 16 | 17 | ## Best Used For 18 | 19 | Garden centers, food presentations, farm-to-table content, botanical brands, natural products. 20 | -------------------------------------------------------------------------------- /testdata/skills/theme-factory/themes/golden-hour.md: -------------------------------------------------------------------------------- 1 | # Golden Hour 2 | 3 | A rich and warm autumnal palette that creates an inviting and sophisticated atmosphere. 4 | 5 | ## Color Palette 6 | 7 | - **Mustard Yellow**: `#f4a900` - Bold primary accent 8 | - **Terracotta**: `#c1666b` - Warm secondary color 9 | - **Warm Beige**: `#d4b896` - Neutral backgrounds 10 | - **Chocolate Brown**: `#4a403a` - Dark text and anchors 11 | 12 | ## Typography 13 | 14 | - **Headers**: FreeSans Bold 15 | - **Body Text**: FreeSans 16 | 17 | ## Best Used For 18 | 19 | Restaurant presentations, hospitality brands, fall campaigns, cozy lifestyle content, artisan products. 20 | -------------------------------------------------------------------------------- /testdata/skills/react-component-generator/assets/BasicComponent.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | interface ComponentNameProps { 4 | className?: string; 5 | children?: React.ReactNode; 6 | } 7 | 8 | /** 9 | * ComponentName - Brief description of what this component does 10 | * 11 | * @param props - Component props 12 | * @returns JSX.Element 13 | */ 14 | export const ComponentName: React.FC = ({ 15 | className = '', 16 | children 17 | }) => { 18 | return ( 19 |
20 | {children} 21 |
22 | ); 23 | }; 24 | 25 | export default ComponentName; 26 | -------------------------------------------------------------------------------- /testdata/skills/theme-factory/themes/arctic-frost.md: -------------------------------------------------------------------------------- 1 | # Arctic Frost 2 | 3 | A cool and crisp winter-inspired theme that conveys clarity, precision, and professionalism. 4 | 5 | ## Color Palette 6 | 7 | - **Ice Blue**: `#d4e4f7` - Light backgrounds and highlights 8 | - **Steel Blue**: `#4a6fa5` - Primary accent color 9 | - **Silver**: `#c0c0c0` - Metallic accent elements 10 | - **Crisp White**: `#fafafa` - Clean backgrounds and text 11 | 12 | ## Typography 13 | 14 | - **Headers**: DejaVu Sans Bold 15 | - **Body Text**: DejaVu Sans 16 | 17 | ## Best Used For 18 | 19 | Healthcare presentations, technology solutions, winter sports, clean tech, pharmaceutical content. 20 | -------------------------------------------------------------------------------- /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | name: Go 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | 11 | build: 12 | name: Build 13 | runs-on: ubuntu-latest 14 | steps: 15 | 16 | - name: Set up Go 1.x 17 | uses: actions/setup-go@v2 18 | with: 19 | go-version: ^1.25 20 | 21 | - name: Check out code into the Go module directory 22 | uses: actions/checkout@v2 23 | 24 | - name: Get dependencies 25 | run: | 26 | go get -v -t -d ./... 27 | 28 | - name: Build 29 | run: go build -v ./... 30 | 31 | - name: Test 32 | run: go test -v ./... 33 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /testdata/skills/theme-factory/themes/tech-innovation.md: -------------------------------------------------------------------------------- 1 | # Tech Innovation 2 | 3 | A bold and modern theme with high-contrast colors perfect for cutting-edge technology presentations. 4 | 5 | ## Color Palette 6 | 7 | - **Electric Blue**: `#0066ff` - Vibrant primary accent 8 | - **Neon Cyan**: `#00ffff` - Bright highlight color 9 | - **Dark Gray**: `#1e1e1e` - Deep backgrounds 10 | - **White**: `#ffffff` - Clean text and contrast 11 | 12 | ## Typography 13 | 14 | - **Headers**: DejaVu Sans Bold 15 | - **Body Text**: DejaVu Sans 16 | 17 | ## Best Used For 18 | 19 | Tech startups, software launches, innovation showcases, AI/ML presentations, digital transformation content. 20 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /testdata/skills/theme-factory/themes/modern-minimalist.md: -------------------------------------------------------------------------------- 1 | # Modern Minimalist 2 | 3 | A clean and contemporary theme with a sophisticated grayscale palette for maximum versatility. 4 | 5 | ## Color Palette 6 | 7 | - **Charcoal**: `#36454f` - Primary dark color 8 | - **Slate Gray**: `#708090` - Medium gray for accents 9 | - **Light Gray**: `#d3d3d3` - Backgrounds and dividers 10 | - **White**: `#ffffff` - Text and clean backgrounds 11 | 12 | ## Typography 13 | 14 | - **Headers**: DejaVu Sans Bold 15 | - **Body Text**: DejaVu Sans 16 | 17 | ## Best Used For 18 | 19 | Tech presentations, architecture portfolios, design showcases, modern business proposals, data visualization. 20 | -------------------------------------------------------------------------------- /testdata/skills/theme-factory/themes/ocean-depths.md: -------------------------------------------------------------------------------- 1 | # Ocean Depths 2 | 3 | A professional and calming maritime theme that evokes the serenity of deep ocean waters. 4 | 5 | ## Color Palette 6 | 7 | - **Deep Navy**: `#1a2332` - Primary background color 8 | - **Teal**: `#2d8b8b` - Accent color for highlights and emphasis 9 | - **Seafoam**: `#a8dadc` - Secondary accent for lighter elements 10 | - **Cream**: `#f1faee` - Text and light backgrounds 11 | 12 | ## Typography 13 | 14 | - **Headers**: DejaVu Sans Bold 15 | - **Body Text**: DejaVu Sans 16 | 17 | ## Best Used For 18 | 19 | Corporate presentations, financial reports, professional consulting decks, trust-building content. 20 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /testdata/skills/theme-factory/themes/sunset-boulevard.md: -------------------------------------------------------------------------------- 1 | # Sunset Boulevard 2 | 3 | A warm and vibrant theme inspired by golden hour sunsets, perfect for energetic and creative presentations. 4 | 5 | ## Color Palette 6 | 7 | - **Burnt Orange**: `#e76f51` - Primary accent color 8 | - **Coral**: `#f4a261` - Secondary warm accent 9 | - **Warm Sand**: `#e9c46a` - Highlighting and backgrounds 10 | - **Deep Purple**: `#264653` - Dark contrast and text 11 | 12 | ## Typography 13 | 14 | - **Headers**: DejaVu Serif Bold 15 | - **Body Text**: DejaVu Sans 16 | 17 | ## Best Used For 18 | 19 | Creative pitches, marketing presentations, lifestyle brands, event promotions, inspirational content. 20 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /testdata/skills/internal-comms/examples/general-comms.md: -------------------------------------------------------------------------------- 1 | ## Instructions 2 | You are being asked to write internal company communication that doesn't fit into the standard formats (3P 3 | updates, newsletters, or FAQs). 4 | 5 | Before proceeding: 6 | 1. Ask the user about their target audience 7 | 2. Understand the communication's purpose 8 | 3. Clarify the desired tone (formal, casual, urgent, informational) 9 | 4. Confirm any specific formatting requirements 10 | 11 | Use these general principles: 12 | - Be clear and concise 13 | - Use active voice 14 | - Put the most important information first 15 | - Include relevant links and references 16 | - Match the company's communication style -------------------------------------------------------------------------------- /testdata/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /tool/file_tool.go: -------------------------------------------------------------------------------- 1 | package tool 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | ) 7 | 8 | // ReadFile reads the content of a file and returns it as a string. 9 | func ReadFile(filePath string) (string, error) { 10 | content, err := os.ReadFile(filePath) 11 | if err != nil { 12 | return "", fmt.Errorf("failed to read file '%s': %w", filePath, err) 13 | } 14 | return string(content), nil 15 | } 16 | 17 | // WriteFile writes the given content to a file. 18 | // If the file does not exist, it will be created. If it exists, its content will be truncated. 19 | func WriteFile(filePath string, content string) error { 20 | err := os.WriteFile(filePath, []byte(content), 0644) // 0644 is standard file permissions 21 | if err != nil { 22 | return fmt.Errorf("failed to write to file '%s': %w", filePath, err) 23 | } 24 | return nil 25 | } 26 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /testdata/oai-skills/spreadsheets/examples/features/change_existing_charts.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pathlib import Path 4 | 5 | from artifact_tool import SpreadsheetArtifact 6 | 7 | 8 | def main() -> None: 9 | file_path = Path(__file__).resolve().parent / ".." / "sample_xlsx" / "weather_sf.xlsx" 10 | spreadsheet = SpreadsheetArtifact.read(file_path=file_path) 11 | 12 | dashboard = spreadsheet.sheet("Dashboard") 13 | 14 | print(f"Charts before deletion: {len(dashboard.charts)}") 15 | for i, chart in enumerate(dashboard.charts): 16 | print(f"Chart {i}: {chart.title}") 17 | 18 | del dashboard.charts[0] 19 | 20 | print(f"Charts after deletion: {len(dashboard.charts)}") 21 | for i, chart in enumerate(dashboard.charts): 22 | print(f"Chart {i}: {chart.title}") 23 | 24 | 25 | if __name__ == "__main__": 26 | main() 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # If you prefer the allow list template instead of the deny list, see community template: 2 | # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore 3 | # 4 | # Binaries for programs and plugins 5 | *.exe 6 | *.exe~ 7 | *.dll 8 | *.so 9 | *.dylib 10 | 11 | # Test binary, built with `go test -c` 12 | *.test 13 | 14 | # Code coverage profiles and other test artifacts 15 | *.out 16 | coverage.html 17 | coverage.out 18 | *.coverprofile 19 | profile.cov 20 | 21 | # Dependency directories (remove the comment below to include it) 22 | # vendor/ 23 | 24 | # Go workspace file 25 | go.work 26 | go.work.sum 27 | 28 | # env file 29 | .env 30 | 31 | # Editor/IDE 32 | # .idea/ 33 | # .vscode/ 34 | 35 | goskills-cli 36 | !goskills-cli/ 37 | goskills 38 | !goskills/ 39 | sessions 40 | 41 | 42 | generated 43 | .claude 44 | 45 | # Added by goreleaser init: 46 | dist/ 47 | -------------------------------------------------------------------------------- /cmd/goskills-cli/root.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/smallnest/goskills/log" 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | // Version is the version of the tool, set at build time 11 | var Version = "v0.1.0" 12 | 13 | var rootCmd = &cobra.Command{ 14 | Use: "goskills-cli", 15 | Short: "A CLI tool for creating and managing Claude skills.", 16 | Long: `goskills-cli is a command-line interface to help you develop, parse, 17 | and manage Claude Skill packages.`, 18 | Version: Version, 19 | CompletionOptions: cobra.CompletionOptions{ 20 | DisableDefaultCmd: true, 21 | }, 22 | } 23 | 24 | // Execute adds all child commands to the root command and sets flags appropriately. 25 | // This is called by main.main(). It only needs to happen once to the rootCmd. 26 | func Execute() { 27 | if err := rootCmd.Execute(); err != nil { 28 | log.Error("command execution failed: %v", err) 29 | os.Exit(1) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2018.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/docx/ooxml/schemas/microsoft/wml-2018.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/smallnest/goskills 2 | 3 | go 1.25.0 4 | 5 | require ( 6 | github.com/PuerkitoBio/goquery v1.11.0 7 | github.com/modelcontextprotocol/go-sdk v1.1.0 8 | github.com/sashabaranov/go-openai v1.41.2 9 | github.com/spf13/cobra v1.10.1 10 | github.com/stretchr/testify v1.10.0 11 | gopkg.in/yaml.v3 v3.0.1 12 | ) 13 | 14 | require ( 15 | github.com/andybalholm/cascadia v1.3.3 // indirect 16 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect 17 | github.com/google/jsonschema-go v0.3.0 // indirect 18 | github.com/inconshreveable/mousetrap v1.1.0 // indirect 19 | github.com/jinzhu/inflection v1.0.0 // indirect 20 | github.com/kataras/golog v0.1.15 // indirect 21 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect 22 | github.com/spf13/pflag v1.0.9 // indirect 23 | github.com/yosida95/uritemplate/v3 v3.0.2 // indirect 24 | golang.org/x/net v0.47.0 // indirect 25 | golang.org/x/oauth2 v0.30.0 // indirect 26 | golang.org/x/sys v0.38.0 // indirect 27 | golang.org/x/tools v0.38.0 // indirect 28 | ) 29 | -------------------------------------------------------------------------------- /.goreleaser.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | builds: 4 | - id: goskills-runner 5 | binary: goskills 6 | main: ./cmd/goskills 7 | env: 8 | - CGO_ENABLED=0 9 | goos: 10 | - linux 11 | - windows 12 | - darwin 13 | goarch: 14 | - amd64 15 | - arm64 16 | 17 | archives: 18 | - format: tar.gz 19 | # Name your archive with a sensible pattern, including the project name, OS, and architecture. 20 | # The .Format directive is already used by goreleaser so no need to specify it. 21 | name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" 22 | 23 | checksum: 24 | name_template: 'checksums.txt' 25 | 26 | release: 27 | # You can customize this if you want to upload to a different repository. 28 | # repo: 29 | # owner: your_github_username 30 | # name: your_repo_name 31 | # This allows GoReleaser to create a GitHub release. 32 | # If you are not using GitHub, you might need to adjust or disable this section. 33 | disable: false # Set to true if you don't want to create a GitHub release 34 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 smallnest 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /testdata/skills/webapp-testing/examples/static_html_automation.py: -------------------------------------------------------------------------------- 1 | from playwright.sync_api import sync_playwright 2 | import os 3 | 4 | # Example: Automating interaction with static HTML files using file:// URLs 5 | 6 | html_file_path = os.path.abspath('path/to/your/file.html') 7 | file_url = f'file://{html_file_path}' 8 | 9 | with sync_playwright() as p: 10 | browser = p.chromium.launch(headless=True) 11 | page = browser.new_page(viewport={'width': 1920, 'height': 1080}) 12 | 13 | # Navigate to local HTML file 14 | page.goto(file_url) 15 | 16 | # Take screenshot 17 | page.screenshot(path='/mnt/user-data/outputs/static_page.png', full_page=True) 18 | 19 | # Interact with elements 20 | page.click('text=Click Me') 21 | page.fill('#name', 'John Doe') 22 | page.fill('#email', 'john@example.com') 23 | 24 | # Submit form 25 | page.click('button[type="submit"]') 26 | page.wait_for_timeout(500) 27 | 28 | # Take final screenshot 29 | page.screenshot(path='/mnt/user-data/outputs/after_submit.png', full_page=True) 30 | 31 | browser.close() 32 | 33 | print("Static HTML automation completed!") -------------------------------------------------------------------------------- /cmd/goskills-cli/list.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/smallnest/goskills" 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | var listCmd = &cobra.Command{ 11 | Use: "list [path]", 12 | Short: "Lists all valid skills in a given directory.", 13 | Long: `The list command scans a directory for subdirectories that are valid 14 | Claude skill packages and prints a summary of each one found.`, 15 | Args: cobra.ExactArgs(1), 16 | RunE: func(cmd *cobra.Command, args []string) error { 17 | skillsRoot := args[0] 18 | 19 | packages, err := goskills.ParseSkillPackages(skillsRoot) 20 | if err != nil { 21 | return fmt.Errorf("could not parse skills in directory '%s': %w", skillsRoot, err) 22 | } 23 | 24 | fmt.Printf("--- Skills found in %s ---\n", skillsRoot) 25 | if len(packages) == 0 { 26 | fmt.Println("No valid skills found.") 27 | return nil 28 | } 29 | 30 | for _, skillPackage := range packages { 31 | fmt.Printf("- %-20s: %s\n", skillPackage.Meta.Name, skillPackage.Meta.Description) 32 | } 33 | 34 | return nil 35 | }, 36 | } 37 | 38 | func init() { 39 | rootCmd.AddCommand(listCmd) 40 | } 41 | -------------------------------------------------------------------------------- /testdata/mcp/mcp.json: -------------------------------------------------------------------------------- 1 | { 2 | "mcpServers": { 3 | "sequential-thinking": { 4 | "type": "stdio", 5 | "command": "npx", 6 | "args": [ 7 | "-y", 8 | "@modelcontextprotocol/server-sequential-thinking" 9 | ], 10 | "env": {} 11 | }, 12 | "filesystem": { 13 | "type": "stdio", 14 | "command": "npx", 15 | "args": [ 16 | "-y", 17 | "@modelcontextprotocol/server-filesystem", 18 | "." 19 | ], 20 | "env": {} 21 | }, 22 | "puppeteer": { 23 | "type": "stdio", 24 | "command": "npx", 25 | "args": [ 26 | "-y", 27 | "@modelcontextprotocol/server-puppeteer" 28 | ], 29 | "env": {} 30 | }, 31 | "fetch": { 32 | "type": "stdio", 33 | "command": "npx", 34 | "args": [ 35 | "-y", 36 | "@kazuph/mcp-fetch" 37 | ], 38 | "env": {} 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /testdata/skills/document-skills/docx/ooxml/scripts/unpack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Unpack and format XML contents of Office files (.docx, .pptx, .xlsx)""" 3 | 4 | import random 5 | import sys 6 | import defusedxml.minidom 7 | import zipfile 8 | from pathlib import Path 9 | 10 | # Get command line arguments 11 | assert len(sys.argv) == 3, "Usage: python unpack.py " 12 | input_file, output_dir = sys.argv[1], sys.argv[2] 13 | 14 | # Extract and format 15 | output_path = Path(output_dir) 16 | output_path.mkdir(parents=True, exist_ok=True) 17 | zipfile.ZipFile(input_file).extractall(output_path) 18 | 19 | # Pretty print all XML files 20 | xml_files = list(output_path.rglob("*.xml")) + list(output_path.rglob("*.rels")) 21 | for xml_file in xml_files: 22 | content = xml_file.read_text(encoding="utf-8") 23 | dom = defusedxml.minidom.parseString(content) 24 | xml_file.write_bytes(dom.toprettyxml(indent=" ", encoding="ascii")) 25 | 26 | # For .docx files, suggest an RSID for tracked changes 27 | if input_file.endswith(".docx"): 28 | suggested_rsid = "".join(random.choices("0123456789ABCDEF", k=8)) 29 | print(f"Suggested RSID for edit session: {suggested_rsid}") 30 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/pptx/ooxml/scripts/unpack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Unpack and format XML contents of Office files (.docx, .pptx, .xlsx)""" 3 | 4 | import random 5 | import sys 6 | import defusedxml.minidom 7 | import zipfile 8 | from pathlib import Path 9 | 10 | # Get command line arguments 11 | assert len(sys.argv) == 3, "Usage: python unpack.py " 12 | input_file, output_dir = sys.argv[1], sys.argv[2] 13 | 14 | # Extract and format 15 | output_path = Path(output_dir) 16 | output_path.mkdir(parents=True, exist_ok=True) 17 | zipfile.ZipFile(input_file).extractall(output_path) 18 | 19 | # Pretty print all XML files 20 | xml_files = list(output_path.rglob("*.xml")) + list(output_path.rglob("*.rels")) 21 | for xml_file in xml_files: 22 | content = xml_file.read_text(encoding="utf-8") 23 | dom = defusedxml.minidom.parseString(content) 24 | xml_file.write_bytes(dom.toprettyxml(indent=" ", encoding="ascii")) 25 | 26 | # For .docx files, suggest an RSID for tracked changes 27 | if input_file.endswith(".docx"): 28 | suggested_rsid = "".join(random.choices("0123456789ABCDEF", k=8)) 29 | print(f"Suggested RSID for edit session: {suggested_rsid}") 30 | -------------------------------------------------------------------------------- /testdata/skills/webapp-testing/examples/console_logging.py: -------------------------------------------------------------------------------- 1 | from playwright.sync_api import sync_playwright 2 | 3 | # Example: Capturing console logs during browser automation 4 | 5 | url = 'http://localhost:5173' # Replace with your URL 6 | 7 | console_logs = [] 8 | 9 | with sync_playwright() as p: 10 | browser = p.chromium.launch(headless=True) 11 | page = browser.new_page(viewport={'width': 1920, 'height': 1080}) 12 | 13 | # Set up console log capture 14 | def handle_console_message(msg): 15 | console_logs.append(f"[{msg.type}] {msg.text}") 16 | print(f"Console: [{msg.type}] {msg.text}") 17 | 18 | page.on("console", handle_console_message) 19 | 20 | # Navigate to page 21 | page.goto(url) 22 | page.wait_for_load_state('networkidle') 23 | 24 | # Interact with the page (triggers console logs) 25 | page.click('text=Dashboard') 26 | page.wait_for_timeout(1000) 27 | 28 | browser.close() 29 | 30 | # Save console logs to file 31 | with open('/mnt/user-data/outputs/console.log', 'w') as f: 32 | f.write('\n'.join(console_logs)) 33 | 34 | print(f"\nCaptured {len(console_logs)} console messages") 35 | print(f"Logs saved to: /mnt/user-data/outputs/console.log") -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/docx/ooxml/scripts/unpack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Unpack and format XML contents of Office files (.docx, .pptx, .xlsx)""" 3 | 4 | import random 5 | import sys 6 | import defusedxml.minidom 7 | import zipfile 8 | from pathlib import Path 9 | 10 | # Get command line arguments 11 | assert len(sys.argv) == 3, "Usage: python unpack.py " 12 | input_file, output_dir = sys.argv[1], sys.argv[2] 13 | 14 | # Extract and format 15 | output_path = Path(output_dir) 16 | output_path.mkdir(parents=True, exist_ok=True) 17 | zipfile.ZipFile(input_file).extractall(output_path) 18 | 19 | # Pretty print all XML files 20 | xml_files = list(output_path.rglob("*.xml")) + list(output_path.rglob("*.rels")) 21 | for xml_file in xml_files: 22 | content = xml_file.read_text(encoding="utf-8") 23 | dom = defusedxml.minidom.parseString(content) 24 | xml_file.write_bytes(dom.toprettyxml(indent=" ", encoding="ascii")) 25 | 26 | # For .docx files, suggest an RSID for tracked changes 27 | if input_file.endswith(".docx"): 28 | suggested_rsid = "".join(random.choices("0123456789ABCDEF", k=8)) 29 | print(f"Suggested RSID for edit session: {suggested_rsid}") 30 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/pptx/ooxml/scripts/unpack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Unpack and format XML contents of Office files (.docx, .pptx, .xlsx)""" 3 | 4 | import random 5 | import sys 6 | import defusedxml.minidom 7 | import zipfile 8 | from pathlib import Path 9 | 10 | # Get command line arguments 11 | assert len(sys.argv) == 3, "Usage: python unpack.py " 12 | input_file, output_dir = sys.argv[1], sys.argv[2] 13 | 14 | # Extract and format 15 | output_path = Path(output_dir) 16 | output_path.mkdir(parents=True, exist_ok=True) 17 | zipfile.ZipFile(input_file).extractall(output_path) 18 | 19 | # Pretty print all XML files 20 | xml_files = list(output_path.rglob("*.xml")) + list(output_path.rglob("*.rels")) 21 | for xml_file in xml_files: 22 | content = xml_file.read_text(encoding="utf-8") 23 | dom = defusedxml.minidom.parseString(content) 24 | xml_file.write_bytes(dom.toprettyxml(indent=" ", encoding="ascii")) 25 | 26 | # For .docx files, suggest an RSID for tracked changes 27 | if input_file.endswith(".docx"): 28 | suggested_rsid = "".join(random.choices("0123456789ABCDEF", k=8)) 29 | print(f"Suggested RSID for edit session: {suggested_rsid}") 30 | -------------------------------------------------------------------------------- /mcp/config.go: -------------------------------------------------------------------------------- 1 | package mcp 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "os" 7 | ) 8 | 9 | // Config represents the structure of the ~/.claude.json file. 10 | type Config struct { 11 | MCPServers map[string]MCPServer `json:"mcpServers"` 12 | MaxRetries int `json:"maxRetries,omitempty"` // Default retry count for tool calls 13 | } 14 | 15 | // MCPServer represents a single MCP server configuration. 16 | type MCPServer struct { 17 | Command string `json:"command"` 18 | Args []string `json:"args"` 19 | Env map[string]string `json:"env,omitempty"` 20 | Type string `json:"type,omitempty"` // "stdio" (default) or "sse" 21 | URL string `json:"url,omitempty"` // For SSE 22 | Headers map[string]string `json:"headers,omitempty"` // For SSE 23 | } 24 | 25 | // LoadConfig loads the MCP configuration from the specified path. 26 | func LoadConfig(path string) (*Config, error) { 27 | data, err := os.ReadFile(path) 28 | if err != nil { 29 | return nil, fmt.Errorf("failed to read config file: %w", err) 30 | } 31 | 32 | var config Config 33 | if err := json.Unmarshal(data, &config); err != nil { 34 | return nil, fmt.Errorf("failed to parse config file: %w", err) 35 | } 36 | 37 | return &config, nil 38 | } 39 | -------------------------------------------------------------------------------- /testdata/skills/mcp-builder/scripts/example_evaluation.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Calculate the compound interest on $10,000 invested at 5% annual interest rate, compounded monthly for 3 years. What is the final amount in dollars (rounded to 2 decimal places)? 4 | 11614.72 5 | 6 | 7 | A projectile is launched at a 45-degree angle with an initial velocity of 50 m/s. Calculate the total distance (in meters) it has traveled from the launch point after 2 seconds, assuming g=9.8 m/s². Round to 2 decimal places. 8 | 87.25 9 | 10 | 11 | A sphere has a volume of 500 cubic meters. Calculate its surface area in square meters. Round to 2 decimal places. 12 | 304.65 13 | 14 | 15 | Calculate the population standard deviation of this dataset: [12, 15, 18, 22, 25, 30, 35]. Round to 2 decimal places. 16 | 7.61 17 | 18 | 19 | Calculate the pH of a solution with a hydrogen ion concentration of 3.5 × 10^-5 M. Round to 2 decimal places. 20 | 4.46 21 | 22 | 23 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/pdf/scripts/convert_pdf_to_images.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | from pdf2image import convert_from_path 5 | 6 | 7 | # Converts each page of a PDF to a PNG image. 8 | 9 | 10 | def convert(pdf_path, output_dir, max_dim=1000): 11 | images = convert_from_path(pdf_path, dpi=200) 12 | 13 | for i, image in enumerate(images): 14 | # Scale image if needed to keep width/height under `max_dim` 15 | width, height = image.size 16 | if width > max_dim or height > max_dim: 17 | scale_factor = min(max_dim / width, max_dim / height) 18 | new_width = int(width * scale_factor) 19 | new_height = int(height * scale_factor) 20 | image = image.resize((new_width, new_height)) 21 | 22 | image_path = os.path.join(output_dir, f"page_{i+1}.png") 23 | image.save(image_path) 24 | print(f"Saved page {i+1} as {image_path} (size: {image.size})") 25 | 26 | print(f"Converted {len(images)} pages to PNG images") 27 | 28 | 29 | if __name__ == "__main__": 30 | if len(sys.argv) != 3: 31 | print("Usage: convert_pdf_to_images.py [input pdf] [output directory]") 32 | sys.exit(1) 33 | pdf_path = sys.argv[1] 34 | output_directory = sys.argv[2] 35 | convert(pdf_path, output_directory) 36 | -------------------------------------------------------------------------------- /testdata/skills/mcp-builder/mcp-builder/scripts/example_evaluation.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Calculate the compound interest on $10,000 invested at 5% annual interest rate, compounded monthly for 3 years. What is the final amount in dollars (rounded to 2 decimal places)? 4 | 11614.72 5 | 6 | 7 | A projectile is launched at a 45-degree angle with an initial velocity of 50 m/s. Calculate the total distance (in meters) it has traveled from the launch point after 2 seconds, assuming g=9.8 m/s². Round to 2 decimal places. 8 | 87.25 9 | 10 | 11 | A sphere has a volume of 500 cubic meters. Calculate its surface area in square meters. Round to 2 decimal places. 12 | 304.65 13 | 14 | 15 | Calculate the population standard deviation of this dataset: [12, 15, 18, 22, 25, 30, 35]. Round to 2 decimal places. 16 | 7.61 17 | 18 | 19 | Calculate the pH of a solution with a hydrogen ion concentration of 3.5 × 10^-5 M. Round to 2 decimal places. 20 | 4.46 21 | 22 | 23 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/pdf/scripts/convert_pdf_to_images.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | from pdf2image import convert_from_path 5 | 6 | 7 | # Converts each page of a PDF to a PNG image. 8 | 9 | 10 | def convert(pdf_path, output_dir, max_dim=1000): 11 | images = convert_from_path(pdf_path, dpi=200) 12 | 13 | for i, image in enumerate(images): 14 | # Scale image if needed to keep width/height under `max_dim` 15 | width, height = image.size 16 | if width > max_dim or height > max_dim: 17 | scale_factor = min(max_dim / width, max_dim / height) 18 | new_width = int(width * scale_factor) 19 | new_height = int(height * scale_factor) 20 | image = image.resize((new_width, new_height)) 21 | 22 | image_path = os.path.join(output_dir, f"page_{i+1}.png") 23 | image.save(image_path) 24 | print(f"Saved page {i+1} as {image_path} (size: {image.size})") 25 | 26 | print(f"Converted {len(images)} pages to PNG images") 27 | 28 | 29 | if __name__ == "__main__": 30 | if len(sys.argv) != 3: 31 | print("Usage: convert_pdf_to_images.py [input pdf] [output directory]") 32 | sys.exit(1) 33 | pdf_path = sys.argv[1] 34 | output_directory = sys.argv[2] 35 | convert(pdf_path, output_directory) 36 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /testdata/oai-skills/spreadsheets/examples/features/cite_cells.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | 3 | from artifact_tool import SpreadsheetArtifact 4 | 5 | 6 | def main() -> None: 7 | spreadsheet = SpreadsheetArtifact("CiteDemo") 8 | first_sheet = spreadsheet.sheet("Sheet1") 9 | 10 | # Example data. 11 | first_sheet.range("A1:C3").set_values( 12 | [ 13 | ["Note", "hello", "hello"], 14 | ["a", "b", "c"], 15 | ["d", "e", "f"], 16 | ] 17 | ) 18 | # Add note on the range (anchors to top-left A1 by default). 19 | first_sheet.range("A1:C3").cite( 20 | tether_id="123456789", 21 | start_line_number=12, 22 | end_line_number=18, 23 | ) 24 | 25 | first_sheet.cell("A4").set_value("This is a note on the cell A4.") 26 | first_sheet.cell("A4").cite(tether_id="1234567890", start_line_number=23, end_line_number=46) 27 | 28 | # Inspect proto->dict verification. 29 | output_dir = Path(__file__).resolve().parent / "golden_rendered_images" / "cite_cells" 30 | output_path = spreadsheet.render(output=output_dir) 31 | print(f"Spreadsheet rendered to {output_path}") 32 | 33 | # output_path = spreadsheet.export() 34 | # print(f"Spreadsheet exported to {output_path}") 35 | 36 | # as_dict = spreadsheet.to_dict() 37 | # print(as_dict) 38 | 39 | 40 | if __name__ == "__main__": 41 | main() 42 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd: -------------------------------------------------------------------------------- 1 | 2 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd: -------------------------------------------------------------------------------- 1 | 2 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd: -------------------------------------------------------------------------------- 1 | 2 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd: -------------------------------------------------------------------------------- 1 | 2 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /cmd/goskills-cli/files.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "path/filepath" 6 | 7 | "github.com/smallnest/goskills" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | var filesCmd = &cobra.Command{ 12 | Use: "files [path]", 13 | Short: "Lists all files comprising a skill package.", 14 | Long: `The files command parses a skill package and lists all the files that make it up, 15 | including the SKILL.md file and all discovered resource files.`, 16 | Args: cobra.ExactArgs(1), 17 | RunE: func(cmd *cobra.Command, args []string) error { 18 | skillPath := args[0] 19 | skillPackage, err := goskills.ParseSkillPackage(skillPath) 20 | if err != nil { 21 | return fmt.Errorf("failed to parse skill: %w", err) 22 | } 23 | 24 | fmt.Printf("Files for skill: %s\n", skillPackage.Meta.Name) 25 | 26 | // Add the SKILL.md file itself 27 | fmt.Printf("- %s\n", filepath.Join(skillPackage.Path, "SKILL.md")) 28 | 29 | // Add all resource files 30 | resources := skillPackage.Resources 31 | for _, file := range resources.Scripts { 32 | fmt.Printf("- %s\n", filepath.Join(skillPackage.Path, file)) 33 | } 34 | for _, file := range resources.References { 35 | fmt.Printf("- %s\n", filepath.Join(skillPackage.Path, file)) 36 | } 37 | for _, file := range resources.Assets { 38 | fmt.Printf("- %s\n", filepath.Join(skillPackage.Path, file)) 39 | } 40 | 41 | return nil 42 | }, 43 | } 44 | 45 | func init() { 46 | rootCmd.AddCommand(filesCmd) 47 | } 48 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /testdata/skills/.claude-plugin/marketplace.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "anthropic-agent-skills", 3 | "owner": { 4 | "name": "Keith Lazuka", 5 | "email": "klazuka@anthropic.com" 6 | }, 7 | "metadata": { 8 | "description": "Anthropic example skills", 9 | "version": "1.0.0" 10 | }, 11 | "plugins": [ 12 | { 13 | "name": "document-skills", 14 | "description": "Collection of document processing suite including Excel, Word, PowerPoint, and PDF capabilities", 15 | "source": "./", 16 | "strict": false, 17 | "skills": [ 18 | "./document-skills/xlsx", 19 | "./document-skills/docx", 20 | "./document-skills/pptx", 21 | "./document-skills/pdf" 22 | ] 23 | }, 24 | { 25 | "name": "example-skills", 26 | "description": "Collection of example skills demonstrating various capabilities including skill creation, MCP building, visual design, algorithmic art, internal communications, web testing, artifact building, Slack GIFs, and theme styling", 27 | "source": "./", 28 | "strict": false, 29 | "skills": [ 30 | "./algorithmic-art", 31 | "./artifacts-builder", 32 | "./brand-guidelines", 33 | "./canvas-design", 34 | "./frontend-design", 35 | "./internal-comms", 36 | "./mcp-builder", 37 | "./skill-creator", 38 | "./slack-gif-creator", 39 | "./theme-factory", 40 | "./webapp-testing" 41 | ] 42 | } 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /cmd/goskills-cli/search.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/smallnest/goskills" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | var searchCmd = &cobra.Command{ 12 | Use: "search [path] [query]", 13 | Short: "Searches for skills by name or description.", 14 | Long: `The search command scans a directory for valid skill packages and returns a list 15 | of skills where the name or description contains the provided query text. 16 | The search is case-insensitive.`, 17 | Args: cobra.ExactArgs(2), 18 | RunE: func(cmd *cobra.Command, args []string) error { 19 | skillsRoot := args[0] 20 | query := strings.ToLower(args[1]) 21 | 22 | packages, err := goskills.ParseSkillPackages(skillsRoot) 23 | if err != nil { 24 | return fmt.Errorf("could not parse skills in directory '%s': %w", skillsRoot, err) 25 | } 26 | 27 | fmt.Printf("--- Searching for '%s' in %s ---\n", query, skillsRoot) 28 | foundCount := 0 29 | for _, skillPackage := range packages { 30 | // Case-insensitive search in name and description 31 | name := strings.ToLower(skillPackage.Meta.Name) 32 | description := strings.ToLower(skillPackage.Meta.Description) 33 | 34 | if strings.Contains(name, query) || strings.Contains(description, query) { 35 | fmt.Printf("- %-20s: %s\n", skillPackage.Meta.Name, skillPackage.Meta.Description) 36 | foundCount++ 37 | } 38 | } 39 | 40 | if foundCount == 0 { 41 | fmt.Println("No matching skills found.") 42 | } 43 | 44 | return nil 45 | }, 46 | } 47 | 48 | func init() { 49 | rootCmd.AddCommand(searchCmd) 50 | } 51 | -------------------------------------------------------------------------------- /testdata/oai-skills/spreadsheets/examples/features/set_merge_cells.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | 3 | from artifact_tool import FileOutputType, SpreadsheetArtifact 4 | 5 | 6 | def main() -> None: 7 | spreadsheet = SpreadsheetArtifact("Scores") 8 | sheet = spreadsheet.create_sheet("MonsterBattle") 9 | 10 | sheet.range("B2:D2").set_values([["Monster", "Level", "Info"]]) 11 | sheet.range("B3:D4").set_values( 12 | [["Lizardman", "100", "Fire type"], ["Hydra", "90", "Water type"]] 13 | ) 14 | 15 | B5_to_D5_range = sheet.range("B5:D5") 16 | B5_to_D5_range.merge() 17 | 18 | # After merging, you can edit the value of the merged cell by either 19 | # updating the range itself or setting the top-left cell 20 | B5_to_D5_range.set_value("Winner TBD") 21 | sheet.cell("B5").set_value("Winner TBD V2") 22 | 23 | # Set formatting and styling on the merged cells. 24 | B5_to_D5_range.format.fill.set_solid_color("#E8E4F7") # lavender 25 | 26 | # Render 27 | output_dir = Path(__file__).resolve().parent / "golden_rendered_images" / "set_merge_cells" 28 | output_path = spreadsheet.render(output=output_dir) 29 | print(f"Spreadsheet rendered to {output_path} up till F6") 30 | 31 | spreadsheet.save( 32 | file_type=FileOutputType.C_STAR_PROTO_JSON, 33 | filename=output_dir / "workbook__auto.json", 34 | overwrite=True, 35 | ) 36 | 37 | # Export 38 | # output_path = spreadsheet.export() 39 | # print(f"Spreadsheet exported to {output_path}") 40 | 41 | 42 | if __name__ == "__main__": 43 | main() 44 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/docx/LICENSE.txt: -------------------------------------------------------------------------------- 1 | © 2025 Anthropic, PBC. All rights reserved. 2 | 3 | LICENSE: Use of these materials (including all code, prompts, assets, files, 4 | and other components of this Skill) is governed by your agreement with 5 | Anthropic regarding use of Anthropic's services. If no separate agreement 6 | exists, use is governed by Anthropic's Consumer Terms of Service or 7 | Commercial Terms of Service, as applicable: 8 | https://www.anthropic.com/legal/consumer-terms 9 | https://www.anthropic.com/legal/commercial-terms 10 | Your applicable agreement is referred to as the "Agreement." "Services" are 11 | as defined in the Agreement. 12 | 13 | ADDITIONAL RESTRICTIONS: Notwithstanding anything in the Agreement to the 14 | contrary, users may not: 15 | 16 | - Extract these materials from the Services or retain copies of these 17 | materials outside the Services 18 | - Reproduce or copy these materials, except for temporary copies created 19 | automatically during authorized use of the Services 20 | - Create derivative works based on these materials 21 | - Distribute, sublicense, or transfer these materials to any third party 22 | - Make, offer to sell, sell, or import any inventions embodied in these 23 | materials 24 | - Reverse engineer, decompile, or disassemble these materials 25 | 26 | The receipt, viewing, or possession of these materials does not convey or 27 | imply any license or right beyond those expressly granted above. 28 | 29 | Anthropic retains all right, title, and interest in these materials, 30 | including all copyrights, patents, and other intellectual property rights. 31 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/pdf/LICENSE.txt: -------------------------------------------------------------------------------- 1 | © 2025 Anthropic, PBC. All rights reserved. 2 | 3 | LICENSE: Use of these materials (including all code, prompts, assets, files, 4 | and other components of this Skill) is governed by your agreement with 5 | Anthropic regarding use of Anthropic's services. If no separate agreement 6 | exists, use is governed by Anthropic's Consumer Terms of Service or 7 | Commercial Terms of Service, as applicable: 8 | https://www.anthropic.com/legal/consumer-terms 9 | https://www.anthropic.com/legal/commercial-terms 10 | Your applicable agreement is referred to as the "Agreement." "Services" are 11 | as defined in the Agreement. 12 | 13 | ADDITIONAL RESTRICTIONS: Notwithstanding anything in the Agreement to the 14 | contrary, users may not: 15 | 16 | - Extract these materials from the Services or retain copies of these 17 | materials outside the Services 18 | - Reproduce or copy these materials, except for temporary copies created 19 | automatically during authorized use of the Services 20 | - Create derivative works based on these materials 21 | - Distribute, sublicense, or transfer these materials to any third party 22 | - Make, offer to sell, sell, or import any inventions embodied in these 23 | materials 24 | - Reverse engineer, decompile, or disassemble these materials 25 | 26 | The receipt, viewing, or possession of these materials does not convey or 27 | imply any license or right beyond those expressly granted above. 28 | 29 | Anthropic retains all right, title, and interest in these materials, 30 | including all copyrights, patents, and other intellectual property rights. 31 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/pptx/LICENSE.txt: -------------------------------------------------------------------------------- 1 | © 2025 Anthropic, PBC. All rights reserved. 2 | 3 | LICENSE: Use of these materials (including all code, prompts, assets, files, 4 | and other components of this Skill) is governed by your agreement with 5 | Anthropic regarding use of Anthropic's services. If no separate agreement 6 | exists, use is governed by Anthropic's Consumer Terms of Service or 7 | Commercial Terms of Service, as applicable: 8 | https://www.anthropic.com/legal/consumer-terms 9 | https://www.anthropic.com/legal/commercial-terms 10 | Your applicable agreement is referred to as the "Agreement." "Services" are 11 | as defined in the Agreement. 12 | 13 | ADDITIONAL RESTRICTIONS: Notwithstanding anything in the Agreement to the 14 | contrary, users may not: 15 | 16 | - Extract these materials from the Services or retain copies of these 17 | materials outside the Services 18 | - Reproduce or copy these materials, except for temporary copies created 19 | automatically during authorized use of the Services 20 | - Create derivative works based on these materials 21 | - Distribute, sublicense, or transfer these materials to any third party 22 | - Make, offer to sell, sell, or import any inventions embodied in these 23 | materials 24 | - Reverse engineer, decompile, or disassemble these materials 25 | 26 | The receipt, viewing, or possession of these materials does not convey or 27 | imply any license or right beyond those expressly granted above. 28 | 29 | Anthropic retains all right, title, and interest in these materials, 30 | including all copyrights, patents, and other intellectual property rights. 31 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/xlsx/LICENSE.txt: -------------------------------------------------------------------------------- 1 | © 2025 Anthropic, PBC. All rights reserved. 2 | 3 | LICENSE: Use of these materials (including all code, prompts, assets, files, 4 | and other components of this Skill) is governed by your agreement with 5 | Anthropic regarding use of Anthropic's services. If no separate agreement 6 | exists, use is governed by Anthropic's Consumer Terms of Service or 7 | Commercial Terms of Service, as applicable: 8 | https://www.anthropic.com/legal/consumer-terms 9 | https://www.anthropic.com/legal/commercial-terms 10 | Your applicable agreement is referred to as the "Agreement." "Services" are 11 | as defined in the Agreement. 12 | 13 | ADDITIONAL RESTRICTIONS: Notwithstanding anything in the Agreement to the 14 | contrary, users may not: 15 | 16 | - Extract these materials from the Services or retain copies of these 17 | materials outside the Services 18 | - Reproduce or copy these materials, except for temporary copies created 19 | automatically during authorized use of the Services 20 | - Create derivative works based on these materials 21 | - Distribute, sublicense, or transfer these materials to any third party 22 | - Make, offer to sell, sell, or import any inventions embodied in these 23 | materials 24 | - Reverse engineer, decompile, or disassemble these materials 25 | 26 | The receipt, viewing, or possession of these materials does not convey or 27 | imply any license or right beyond those expressly granted above. 28 | 29 | Anthropic retains all right, title, and interest in these materials, 30 | including all copyrights, patents, and other intellectual property rights. 31 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/docx/LICENSE.txt: -------------------------------------------------------------------------------- 1 | © 2025 Anthropic, PBC. All rights reserved. 2 | 3 | LICENSE: Use of these materials (including all code, prompts, assets, files, 4 | and other components of this Skill) is governed by your agreement with 5 | Anthropic regarding use of Anthropic's services. If no separate agreement 6 | exists, use is governed by Anthropic's Consumer Terms of Service or 7 | Commercial Terms of Service, as applicable: 8 | https://www.anthropic.com/legal/consumer-terms 9 | https://www.anthropic.com/legal/commercial-terms 10 | Your applicable agreement is referred to as the "Agreement." "Services" are 11 | as defined in the Agreement. 12 | 13 | ADDITIONAL RESTRICTIONS: Notwithstanding anything in the Agreement to the 14 | contrary, users may not: 15 | 16 | - Extract these materials from the Services or retain copies of these 17 | materials outside the Services 18 | - Reproduce or copy these materials, except for temporary copies created 19 | automatically during authorized use of the Services 20 | - Create derivative works based on these materials 21 | - Distribute, sublicense, or transfer these materials to any third party 22 | - Make, offer to sell, sell, or import any inventions embodied in these 23 | materials 24 | - Reverse engineer, decompile, or disassemble these materials 25 | 26 | The receipt, viewing, or possession of these materials does not convey or 27 | imply any license or right beyond those expressly granted above. 28 | 29 | Anthropic retains all right, title, and interest in these materials, 30 | including all copyrights, patents, and other intellectual property rights. 31 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/pdf/LICENSE.txt: -------------------------------------------------------------------------------- 1 | © 2025 Anthropic, PBC. All rights reserved. 2 | 3 | LICENSE: Use of these materials (including all code, prompts, assets, files, 4 | and other components of this Skill) is governed by your agreement with 5 | Anthropic regarding use of Anthropic's services. If no separate agreement 6 | exists, use is governed by Anthropic's Consumer Terms of Service or 7 | Commercial Terms of Service, as applicable: 8 | https://www.anthropic.com/legal/consumer-terms 9 | https://www.anthropic.com/legal/commercial-terms 10 | Your applicable agreement is referred to as the "Agreement." "Services" are 11 | as defined in the Agreement. 12 | 13 | ADDITIONAL RESTRICTIONS: Notwithstanding anything in the Agreement to the 14 | contrary, users may not: 15 | 16 | - Extract these materials from the Services or retain copies of these 17 | materials outside the Services 18 | - Reproduce or copy these materials, except for temporary copies created 19 | automatically during authorized use of the Services 20 | - Create derivative works based on these materials 21 | - Distribute, sublicense, or transfer these materials to any third party 22 | - Make, offer to sell, sell, or import any inventions embodied in these 23 | materials 24 | - Reverse engineer, decompile, or disassemble these materials 25 | 26 | The receipt, viewing, or possession of these materials does not convey or 27 | imply any license or right beyond those expressly granted above. 28 | 29 | Anthropic retains all right, title, and interest in these materials, 30 | including all copyrights, patents, and other intellectual property rights. 31 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/pptx/LICENSE.txt: -------------------------------------------------------------------------------- 1 | © 2025 Anthropic, PBC. All rights reserved. 2 | 3 | LICENSE: Use of these materials (including all code, prompts, assets, files, 4 | and other components of this Skill) is governed by your agreement with 5 | Anthropic regarding use of Anthropic's services. If no separate agreement 6 | exists, use is governed by Anthropic's Consumer Terms of Service or 7 | Commercial Terms of Service, as applicable: 8 | https://www.anthropic.com/legal/consumer-terms 9 | https://www.anthropic.com/legal/commercial-terms 10 | Your applicable agreement is referred to as the "Agreement." "Services" are 11 | as defined in the Agreement. 12 | 13 | ADDITIONAL RESTRICTIONS: Notwithstanding anything in the Agreement to the 14 | contrary, users may not: 15 | 16 | - Extract these materials from the Services or retain copies of these 17 | materials outside the Services 18 | - Reproduce or copy these materials, except for temporary copies created 19 | automatically during authorized use of the Services 20 | - Create derivative works based on these materials 21 | - Distribute, sublicense, or transfer these materials to any third party 22 | - Make, offer to sell, sell, or import any inventions embodied in these 23 | materials 24 | - Reverse engineer, decompile, or disassemble these materials 25 | 26 | The receipt, viewing, or possession of these materials does not convey or 27 | imply any license or right beyond those expressly granted above. 28 | 29 | Anthropic retains all right, title, and interest in these materials, 30 | including all copyrights, patents, and other intellectual property rights. 31 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/xlsx/LICENSE.txt: -------------------------------------------------------------------------------- 1 | © 2025 Anthropic, PBC. All rights reserved. 2 | 3 | LICENSE: Use of these materials (including all code, prompts, assets, files, 4 | and other components of this Skill) is governed by your agreement with 5 | Anthropic regarding use of Anthropic's services. If no separate agreement 6 | exists, use is governed by Anthropic's Consumer Terms of Service or 7 | Commercial Terms of Service, as applicable: 8 | https://www.anthropic.com/legal/consumer-terms 9 | https://www.anthropic.com/legal/commercial-terms 10 | Your applicable agreement is referred to as the "Agreement." "Services" are 11 | as defined in the Agreement. 12 | 13 | ADDITIONAL RESTRICTIONS: Notwithstanding anything in the Agreement to the 14 | contrary, users may not: 15 | 16 | - Extract these materials from the Services or retain copies of these 17 | materials outside the Services 18 | - Reproduce or copy these materials, except for temporary copies created 19 | automatically during authorized use of the Services 20 | - Create derivative works based on these materials 21 | - Distribute, sublicense, or transfer these materials to any third party 22 | - Make, offer to sell, sell, or import any inventions embodied in these 23 | materials 24 | - Reverse engineer, decompile, or disassemble these materials 25 | 26 | The receipt, viewing, or possession of these materials does not convey or 27 | imply any license or right beyond those expressly granted above. 28 | 29 | Anthropic retains all right, title, and interest in these materials, 30 | including all copyrights, patents, and other intellectual property rights. 31 | -------------------------------------------------------------------------------- /testdata/skills/internal-comms/SKILL.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: internal-comms 3 | description: A set of resources to help me write all kinds of internal communications, using the formats that my company likes to use. Claude should use this skill whenever asked to write some sort of internal communications (status reports, leadership updates, 3P updates, company newsletters, FAQs, incident reports, project updates, etc.). 4 | license: Complete terms in LICENSE.txt 5 | --- 6 | 7 | ## When to use this skill 8 | To write internal communications, use this skill for: 9 | - 3P updates (Progress, Plans, Problems) 10 | - Company newsletters 11 | - FAQ responses 12 | - Status reports 13 | - Leadership updates 14 | - Project updates 15 | - Incident reports 16 | 17 | ## How to use this skill 18 | 19 | To write any internal communication: 20 | 21 | 1. **Identify the communication type** from the request 22 | 2. **Load the appropriate guideline file** from the `examples/` directory: 23 | - `examples/3p-updates.md` - For Progress/Plans/Problems team updates 24 | - `examples/company-newsletter.md` - For company-wide newsletters 25 | - `examples/faq-answers.md` - For answering frequently asked questions 26 | - `examples/general-comms.md` - For anything else that doesn't explicitly match one of the above 27 | 3. **Follow the specific instructions** in that file for formatting, tone, and content gathering 28 | 29 | If the communication type doesn't match any existing guideline, ask for clarification or more context about the desired format. 30 | 31 | ## Keywords 32 | 3P updates, company newsletter, company comms, weekly update, faqs, common questions, updates, internal comms 33 | -------------------------------------------------------------------------------- /testdata/skills/webapp-testing/examples/element_discovery.py: -------------------------------------------------------------------------------- 1 | from playwright.sync_api import sync_playwright 2 | 3 | # Example: Discovering buttons and other elements on a page 4 | 5 | with sync_playwright() as p: 6 | browser = p.chromium.launch(headless=True) 7 | page = browser.new_page() 8 | 9 | # Navigate to page and wait for it to fully load 10 | page.goto('http://localhost:5173') 11 | page.wait_for_load_state('networkidle') 12 | 13 | # Discover all buttons on the page 14 | buttons = page.locator('button').all() 15 | print(f"Found {len(buttons)} buttons:") 16 | for i, button in enumerate(buttons): 17 | text = button.inner_text() if button.is_visible() else "[hidden]" 18 | print(f" [{i}] {text}") 19 | 20 | # Discover links 21 | links = page.locator('a[href]').all() 22 | print(f"\nFound {len(links)} links:") 23 | for link in links[:5]: # Show first 5 24 | text = link.inner_text().strip() 25 | href = link.get_attribute('href') 26 | print(f" - {text} -> {href}") 27 | 28 | # Discover input fields 29 | inputs = page.locator('input, textarea, select').all() 30 | print(f"\nFound {len(inputs)} input fields:") 31 | for input_elem in inputs: 32 | name = input_elem.get_attribute('name') or input_elem.get_attribute('id') or "[unnamed]" 33 | input_type = input_elem.get_attribute('type') or 'text' 34 | print(f" - {name} ({input_type})") 35 | 36 | # Take screenshot for visual reference 37 | page.screenshot(path='/tmp/page_discovery.png', full_page=True) 38 | print("\nScreenshot saved to /tmp/page_discovery.png") 39 | 40 | browser.close() -------------------------------------------------------------------------------- /tool/shell_tool.go: -------------------------------------------------------------------------------- 1 | package tool 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "os" 7 | "os/exec" 8 | "text/template" 9 | ) 10 | 11 | type ShellTool struct { 12 | } 13 | 14 | func (t *ShellTool) Run(args map[string]any, code string) (string, error) { 15 | tmpl, err := template.New("shell").Parse(code) 16 | if err != nil { 17 | return "", fmt.Errorf("failed to parse shell template: %w", err) 18 | } 19 | 20 | var script bytes.Buffer 21 | err = tmpl.Execute(&script, args) 22 | if err != nil { 23 | return "", fmt.Errorf("failed to execute shell template: %w", err) 24 | } 25 | 26 | tmpfile, err := os.CreateTemp("", "shell-*.sh") 27 | if err != nil { 28 | return "", fmt.Errorf("failed to create temp file: %w", err) 29 | } 30 | defer os.Remove(tmpfile.Name()) 31 | 32 | if _, err := tmpfile.Write(script.Bytes()); err != nil { 33 | return "", fmt.Errorf("failed to write to temp file: %w", err) 34 | } 35 | if err := tmpfile.Close(); err != nil { 36 | return "", fmt.Errorf("failed to close temp file: %w", err) 37 | } 38 | 39 | return RunShellScript(tmpfile.Name(), nil) 40 | } 41 | 42 | // RunShellScript executes a shell script and returns its combined stdout and stderr. 43 | func RunShellScript(scriptPath string, args []string) (string, error) { 44 | cmd := exec.Command("bash", append([]string{scriptPath}, args...)...) 45 | 46 | var stdout, stderr bytes.Buffer 47 | cmd.Stdout = &stdout 48 | cmd.Stderr = &stderr 49 | 50 | err := cmd.Run() 51 | if err != nil { 52 | return "", fmt.Errorf("failed to run shell script '%s': %w\nStdout: %s\nStderr: %s", scriptPath, err, stdout.String(), stderr.String()) 53 | } 54 | 55 | return stdout.String() + stderr.String(), nil 56 | } 57 | -------------------------------------------------------------------------------- /testdata/skills/artifacts-builder/scripts/bundle-artifact.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | echo "📦 Bundling React app to single HTML artifact..." 5 | 6 | # Check if we're in a project directory 7 | if [ ! -f "package.json" ]; then 8 | echo "❌ Error: No package.json found. Run this script from your project root." 9 | exit 1 10 | fi 11 | 12 | # Check if index.html exists 13 | if [ ! -f "index.html" ]; then 14 | echo "❌ Error: No index.html found in project root." 15 | echo " This script requires an index.html entry point." 16 | exit 1 17 | fi 18 | 19 | # Install bundling dependencies 20 | echo "📦 Installing bundling dependencies..." 21 | pnpm add -D parcel @parcel/config-default parcel-resolver-tspaths html-inline 22 | 23 | # Create Parcel config with tspaths resolver 24 | if [ ! -f ".parcelrc" ]; then 25 | echo "🔧 Creating Parcel configuration with path alias support..." 26 | cat > .parcelrc << 'EOF' 27 | { 28 | "extends": "@parcel/config-default", 29 | "resolvers": ["parcel-resolver-tspaths", "..."] 30 | } 31 | EOF 32 | fi 33 | 34 | # Clean previous build 35 | echo "🧹 Cleaning previous build..." 36 | rm -rf dist bundle.html 37 | 38 | # Build with Parcel 39 | echo "🔨 Building with Parcel..." 40 | pnpm exec parcel build index.html --dist-dir dist --no-source-maps 41 | 42 | # Inline everything into single HTML 43 | echo "🎯 Inlining all assets into single HTML file..." 44 | pnpm exec html-inline dist/index.html > bundle.html 45 | 46 | # Get file size 47 | FILE_SIZE=$(du -h bundle.html | cut -f1) 48 | 49 | echo "" 50 | echo "✅ Bundle complete!" 51 | echo "📄 Output: bundle.html ($FILE_SIZE)" 52 | echo "" 53 | echo "You can now use this single HTML file as an artifact in Claude conversations." 54 | echo "To test locally: open bundle.html in your browser" -------------------------------------------------------------------------------- /testdata/oai-skills/spreadsheets/examples/features/create_tables.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pathlib import Path 4 | 5 | from artifact_tool import FileOutputType, SpreadsheetArtifact 6 | 7 | 8 | def main() -> None: 9 | # New spreadsheet artifact 10 | spreadsheet = SpreadsheetArtifact("Scores") 11 | first_sheet = spreadsheet.sheet("FirstGame") 12 | 13 | # Seed some data 14 | first_sheet.range("A1:C1").set_values([["Player", "Game", "Score"]]) 15 | first_sheet.range("A2:C5").set_values( 16 | [ 17 | ["Vicky", "1", 100], 18 | ["Emily", "1", 95], 19 | ["Dibyo", "2", 110], 20 | ["Bobby", "2", 105], 21 | ] 22 | ) 23 | 24 | # Create a table over the data range 25 | table = first_sheet.add_table( 26 | "A1:C5", has_headers=True, name="ScoresTable", style_name="TableStyleMedium2" 27 | ) 28 | table.set_style(show_row_stripes=True) 29 | 30 | # Expand only the last two columns and the first two rows to compare 31 | first_sheet.set_column_widths("B:C", 24) 32 | for row_idx in range(1, 3): 33 | first_sheet.set_row_height(row_idx, 28) 34 | 35 | # Inspect proto->dict verification. 36 | output_dir = Path(__file__).resolve().parent / "golden_rendered_images" / "create_tables" 37 | output_path = spreadsheet.render(output=output_dir) 38 | print(f"Spreadsheet rendered to {output_path}") 39 | 40 | # output_path = spreadsheet.export() 41 | # print(f"Spreadsheet exported to {output_path}") 42 | 43 | spreadsheet.save( 44 | file_type=FileOutputType.C_STAR_PROTO_JSON, 45 | filename=output_dir / "workbook__auto.json", 46 | overwrite=True, 47 | ) 48 | 49 | 50 | if __name__ == "__main__": 51 | main() 52 | -------------------------------------------------------------------------------- /tool/web_tool.go: -------------------------------------------------------------------------------- 1 | package tool 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "time" 7 | 8 | "github.com/PuerkitoBio/goquery" 9 | ) 10 | 11 | // WebFetch retrieves the main text content from a given URL. 12 | // It uses goquery to parse the HTML and extract text, removing script and style tags. 13 | func WebFetch(urlString string) (string, error) { 14 | client := http.Client{ 15 | Timeout: 20 * time.Second, 16 | } 17 | 18 | req, err := http.NewRequest("GET", urlString, nil) 19 | if err != nil { 20 | return "", fmt.Errorf("failed to create request for %s: %w", urlString, err) 21 | } 22 | // Set a realistic User-Agent 23 | req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36") 24 | 25 | resp, err := client.Do(req) 26 | if err != nil { 27 | return "", fmt.Errorf("failed to fetch URL %s: %w", urlString, err) 28 | } 29 | defer resp.Body.Close() 30 | 31 | if resp.StatusCode < 200 || resp.StatusCode >= 300 { 32 | return "", fmt.Errorf("request to %s failed with status code %d", urlString, resp.StatusCode) 33 | } 34 | 35 | // Parse the HTML document 36 | doc, err := goquery.NewDocumentFromReader(resp.Body) 37 | if err != nil { 38 | return "", fmt.Errorf("failed to parse HTML from %s: %w", urlString, err) 39 | } 40 | 41 | // Remove script and style elements 42 | doc.Find("script, style").Each(func(i int, s *goquery.Selection) { 43 | s.Remove() 44 | }) 45 | 46 | // Get the text from the body 47 | bodyText := doc.Find("body").Text() 48 | 49 | if bodyText == "" { 50 | return "", fmt.Errorf("no text content found in the body of %s", urlString) 51 | } 52 | 53 | // Clean up whitespace 54 | // return strings.Join(strings.Fields(bodyText), " ") 55 | return bodyText, nil 56 | } 57 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/pdf/scripts/create_validation_image.py: -------------------------------------------------------------------------------- 1 | import json 2 | import sys 3 | 4 | from PIL import Image, ImageDraw 5 | 6 | 7 | # Creates "validation" images with rectangles for the bounding box information that 8 | # Claude creates when determining where to add text annotations in PDFs. See forms.md. 9 | 10 | 11 | def create_validation_image(page_number, fields_json_path, input_path, output_path): 12 | # Input file should be in the `fields.json` format described in forms.md. 13 | with open(fields_json_path, 'r') as f: 14 | data = json.load(f) 15 | 16 | img = Image.open(input_path) 17 | draw = ImageDraw.Draw(img) 18 | num_boxes = 0 19 | 20 | for field in data["form_fields"]: 21 | if field["page_number"] == page_number: 22 | entry_box = field['entry_bounding_box'] 23 | label_box = field['label_bounding_box'] 24 | # Draw red rectangle over entry bounding box and blue rectangle over the label. 25 | draw.rectangle(entry_box, outline='red', width=2) 26 | draw.rectangle(label_box, outline='blue', width=2) 27 | num_boxes += 2 28 | 29 | img.save(output_path) 30 | print(f"Created validation image at {output_path} with {num_boxes} bounding boxes") 31 | 32 | 33 | if __name__ == "__main__": 34 | if len(sys.argv) != 5: 35 | print("Usage: create_validation_image.py [page number] [fields.json file] [input image path] [output image path]") 36 | sys.exit(1) 37 | page_number = int(sys.argv[1]) 38 | fields_json_path = sys.argv[2] 39 | input_image_path = sys.argv[3] 40 | output_image_path = sys.argv[4] 41 | create_validation_image(page_number, fields_json_path, input_image_path, output_image_path) 42 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/pdf/scripts/create_validation_image.py: -------------------------------------------------------------------------------- 1 | import json 2 | import sys 3 | 4 | from PIL import Image, ImageDraw 5 | 6 | 7 | # Creates "validation" images with rectangles for the bounding box information that 8 | # Claude creates when determining where to add text annotations in PDFs. See forms.md. 9 | 10 | 11 | def create_validation_image(page_number, fields_json_path, input_path, output_path): 12 | # Input file should be in the `fields.json` format described in forms.md. 13 | with open(fields_json_path, 'r') as f: 14 | data = json.load(f) 15 | 16 | img = Image.open(input_path) 17 | draw = ImageDraw.Draw(img) 18 | num_boxes = 0 19 | 20 | for field in data["form_fields"]: 21 | if field["page_number"] == page_number: 22 | entry_box = field['entry_bounding_box'] 23 | label_box = field['label_bounding_box'] 24 | # Draw red rectangle over entry bounding box and blue rectangle over the label. 25 | draw.rectangle(entry_box, outline='red', width=2) 26 | draw.rectangle(label_box, outline='blue', width=2) 27 | num_boxes += 2 28 | 29 | img.save(output_path) 30 | print(f"Created validation image at {output_path} with {num_boxes} bounding boxes") 31 | 32 | 33 | if __name__ == "__main__": 34 | if len(sys.argv) != 5: 35 | print("Usage: create_validation_image.py [page number] [fields.json file] [input image path] [output image path]") 36 | sys.exit(1) 37 | page_number = int(sys.argv[1]) 38 | fields_json_path = sys.argv[2] 39 | input_image_path = sys.argv[3] 40 | output_image_path = sys.argv[4] 41 | create_validation_image(page_number, fields_json_path, input_image_path, output_image_path) 42 | -------------------------------------------------------------------------------- /testdata/oai-skills/spreadsheets/examples/features/create_line_chart.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pathlib import Path 4 | 5 | from oaiproto.coworker.pptx.chart_pb2 import Chart 6 | 7 | from artifact_tool import FileOutputType, SpreadsheetArtifact 8 | 9 | 10 | def main() -> None: 11 | # New spreadsheet artifact 12 | spreadsheet = SpreadsheetArtifact("Scores") 13 | first_sheet = spreadsheet.sheet("GameX") 14 | 15 | # Seed some data 16 | first_sheet["A1:C1"].values = [["Player", "Game 1", "Game 2"]] 17 | first_sheet["A2:C5"].values = [ 18 | ["Vicky", 120, 100], 19 | ["Emily", 134, 95], 20 | ["Dibyo", 95, 110], 21 | ["Bobby", 105, 105], 22 | ] 23 | 24 | # Set up some ranges to use as labels (categories) and values for the charts 25 | labels = first_sheet.range("A2:A5") 26 | game1 = first_sheet.range("B2:B5") 27 | game2 = first_sheet.range("C2:C5") 28 | 29 | # Add a line chart to the cell range E2:I14 30 | chart1 = first_sheet.charts.add( 31 | first_sheet.range("E2:I14"), 32 | Chart.ChartType.CHART_TYPE_LINE, 33 | title="Game Scores", 34 | ) 35 | chart1.add_series("Game 1", categories_range=labels, values_range=game1) 36 | chart1.add_series("Game 2", categories_range=labels, values_range=game2) 37 | 38 | output_dir = Path(__file__).resolve().parent / "golden_rendered_images" / "create_line_chart" 39 | output_path = spreadsheet.render(output=output_dir) 40 | print(f"Spreadsheet rendered to {output_path}") 41 | 42 | spreadsheet.save( 43 | file_type=FileOutputType.C_STAR_PROTO_JSON, 44 | filename=output_dir / "workbook__auto.json", 45 | overwrite=True, 46 | ) 47 | 48 | # output_path = spreadsheet.export() 49 | # print(f"Spreadsheet exported to {output_path}") 50 | 51 | 52 | if __name__ == "__main__": 53 | main() 54 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /testdata/oai-skills/spreadsheets/examples/features/create_area_chart.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pathlib import Path 4 | 5 | from oaiproto.coworker.pptx.chart_pb2 import Chart 6 | 7 | from artifact_tool import FileOutputType, SpreadsheetArtifact 8 | 9 | 10 | def main() -> None: 11 | # New spreadsheet artifact 12 | spreadsheet = SpreadsheetArtifact("Scores") 13 | game_sheet = spreadsheet.sheet("MyFavoriteGame") 14 | 15 | # Seed some data 16 | game_sheet["A1:C1"].values = [["Player", "Game 1", "Game 2"]] 17 | game_sheet["A2:C5"].values = [ 18 | ["Vicky", 120, 100], 19 | ["Yash", 134, 95], 20 | ["Dibyo", 95, 110], 21 | ["Bobby", 105, 105], 22 | ] 23 | 24 | # Set up some ranges to use as labels (categories) and values for the charts 25 | labels = game_sheet.range("A2:A5") 26 | game1 = game_sheet.range("B2:B5") 27 | game2 = game_sheet.range("C2:C5") 28 | 29 | # Add an area chart to the cell range E2:I14 30 | chart1 = game_sheet.charts.add( 31 | game_sheet.range("E2:I14"), 32 | Chart.ChartType.CHART_TYPE_AREA, 33 | title="Game Scores", 34 | ) 35 | chart1.add_series("Game 1", categories_range=labels, values_range=game1) 36 | chart1.add_series("Game 2", categories_range=labels, values_range=game2) 37 | 38 | output_dir = Path(__file__).resolve().parent / "golden_rendered_images" / "create_area_chart" 39 | output_path = spreadsheet.render(output=output_dir) 40 | print(f"Spreadsheet rendered to {output_path}") 41 | 42 | spreadsheet.save( 43 | file_type=FileOutputType.C_STAR_PROTO_JSON, 44 | filename=output_dir / "workbook__auto.json", 45 | overwrite=True, 46 | ) 47 | 48 | # output_path = spreadsheet.export() 49 | # print(f"Spreadsheet exported to {output_path}") 50 | 51 | 52 | if __name__ == "__main__": 53 | main() 54 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /tool/test_all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Running all tests for Go Skills Tool..." 4 | echo "=====================================" 5 | 6 | # Set colors for output 7 | GREEN='\033[0;32m' 8 | RED='\033[0;31m' 9 | YELLOW='\033[1;33m' 10 | NC='\033[0m' # No Color 11 | 12 | # Function to print status 13 | print_status() { 14 | if [ $1 -eq 0 ]; then 15 | echo -e "${GREEN}✓ $2${NC}" 16 | else 17 | echo -e "${RED}✗ $2${NC}" 18 | exit 1 19 | fi 20 | } 21 | 22 | # Run tests with coverage 23 | echo -e "\n${YELLOW}Running tests with coverage...${NC}" 24 | go test -coverprofile=coverage.out ./... 25 | print_status $? "Tests completed" 26 | 27 | # Show coverage summary 28 | echo -e "\n${YELLOW}Coverage Summary:${NC}" 29 | go tool cover -func=coverage.out | tail -1 30 | 31 | # Run benchmarks 32 | echo -e "\n${YELLOW}Running benchmarks...${NC}" 33 | go test -bench=. -benchmem ./... > /dev/null 2>&1 34 | print_status $? "Benchmarks completed" 35 | 36 | # Check for race conditions 37 | echo -e "\n${YELLOW}Running race condition tests...${NC}" 38 | go test -race ./... > /dev/null 2>&1 39 | print_status $? "Race condition tests completed" 40 | 41 | # Vet code 42 | echo -e "\n${YELLOW}Running go vet...${NC}" 43 | go vet ./... 44 | print_status $? "Code vet completed" 45 | 46 | # Format check 47 | echo -e "\n${YELLOW}Checking code formatting...${NC}" 48 | UNFORMATTED=$(gofmt -l -s .) 49 | if [ -z "$UNFORMATTED" ]; then 50 | print_status 0 "Code is properly formatted" 51 | else 52 | echo -e "${RED}Unformatted files:${NC}" 53 | echo "$UNFORMATTED" 54 | print_status 1 "Code formatting check failed" 55 | fi 56 | 57 | # Build check 58 | echo -e "\n${YELLOW}Building project...${NC}" 59 | go build -o /tmp/test-tool . 60 | print_status $? "Build completed" 61 | 62 | # Clean up 63 | rm -f /tmp/test-tool coverage.out coverage.html 64 | 65 | echo -e "\n${GREEN}All tests passed successfully!${NC}" -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 更新日志 2 | 3 | 本项目的所有重要更改都将记录在此文件中。 4 | 5 | ## [Unreleased] 6 | 7 | ### 新增特性 8 | - **递归深度 (Recursive Depth)**: 实现动态规划能力,允许 Agent 在信息不足时自动请求新的搜索和分析任务,形成闭环的 Deep Research 流程。 9 | 10 | ## [v0.3.5] - 2025-11-30 11 | 12 | ### 新增特性 13 | - **国际化 (Localization)**: 全面支持中文界面和日志。 14 | - `agent-web` 用户界面汉化。 15 | - `agent` 核心包及 Subagent 的日志和提示词汉化。 16 | - **Web 界面**: 引入基于 Web 的聊天界面 (#9)。 17 | - 添加 `agent-web` 命令。 18 | - 实现实时事件流 (SSE)。 19 | - 支持直接在浏览器中查看报告、播客和 PPT。 20 | - **会话回放**: 支持查看和回放历史会话。 21 | - **UI 交互优化**: 22 | - 任务执行期间禁用输入,防止重复提交。 23 | - 修复了任务状态图标(旋转/完成/失败)在中文日志下的显示问题。 24 | - **报告图片**: 支持在生成的报告中包含图片 (#11)。 25 | 26 | ### 改进 27 | - **上下文管理**: 重构上下文处理,以便在 Subagent 之间更好地管理状态。 28 | - **CLI**: 改进 `agent-cli` 的提示和输出格式 (#9, #5)。 29 | 30 | ### 修复 31 | - 修复 Web UI 中的播客标签页渲染问题。 32 | - 修复单元测试失败。 33 | 34 | ## [v0.3.3] - 2025-11-29 35 | 36 | ### 新增特性 37 | - **PPT 生成**: 支持使用 Slidev 生成 PowerPoint 风格的演示文稿 (#7)。 38 | - 实现 `PPTSubagent` 生成 Markdown 并构建幻灯片。 39 | - 添加酷炫视觉效果:玻璃拟态、渐变、动画。 40 | - 集成 Web 界面以查看生成的 PPT。 41 | - **PPT 图片集成**: PPT Subagent 现在可以从源内容中提取图片并用于幻灯片生成。 42 | 43 | ### 改进 44 | - **PPT 美学**: 增强 PPT 视觉风格,采用暗色主题、玻璃拟态和动画 (#7)。 45 | 46 | ## [v0.3.2] - 2025-11-28 47 | 48 | ### 新增特性 49 | - 添加 Tavily 工具和更多来自 `staruhub/ClaudeSkills` 的技能。 50 | 51 | ## [v0.3.1] - 2025-11-28 52 | 53 | ### 改进 54 | - 改进 `agent-cli` 和 `agent-web` 界面。 55 | 56 | ## [v0.3.0] - 2025-11-27 57 | 58 | ### 新增特性 59 | - 添加播客 Subagent (#6)。 60 | - 更新描述并修复 GitHub Actions。 61 | 62 | ## [v0.2.0] - 2025-11-25 63 | 64 | ### 新增特性 65 | - 添加网站内容。 66 | - 支持 MCP (#3)。 67 | - 添加 Agent RunLoop (会话)。 68 | 69 | ## [v0.1.3] - 2025-11-24 70 | 71 | ### 新增特性 72 | - 更新 `goreleaser` 配置至 v2 并添加默认归档/校验和。 73 | 74 | ## [v0.1.2] - 2025-11-24 75 | 76 | ### 构建 77 | - 添加 `goreleaser` 用于发布管理。 78 | 79 | ## [v0.1.1] - 2025-11-24 80 | 81 | ### 新增特性 82 | - 添加两个新工具 (Markitdown 技能)。 83 | 84 | ## [v0.1.0] - 2025-11-24 85 | 86 | ### 初始版本 87 | - 项目初始发布。 88 | - 基本运行器和技能支持。 89 | -------------------------------------------------------------------------------- /testdata/oai-skills/spreadsheets/examples/features/set_cell_width_height.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pathlib import Path 4 | 5 | from artifact_tool import FileOutputType, SpreadsheetArtifact 6 | 7 | 8 | def main() -> None: 9 | # New spreadsheet artifact 10 | spreadsheet = SpreadsheetArtifact("Scores") 11 | first_sheet = spreadsheet.sheet("FirstGame") 12 | 13 | # Column widths. 14 | first_sheet.set_column_widths_bulk({"B": 20, "C": 10, "D": 2, "E": 2}) 15 | 16 | assert first_sheet.get_column_width("B") == 20 17 | assert first_sheet.get_column_width("C") == 10 18 | 19 | # Row heights. 20 | first_sheet.set_sheet_styles(default_row_height=15.75) 21 | first_sheet.set_row_height(2, 35.25) 22 | first_sheet.set_row_height(4, 20.0) 23 | assert first_sheet.default_row_height == 15.75 24 | 25 | # Add text in rows with custom heights so the height differences are visible 26 | first_sheet.cell("B2").set_value("Row height 35.25") 27 | first_sheet.cell("B4").set_value("Row height 20.0") 28 | 29 | first_sheet.cell("B8").set_value("Column width 20") 30 | first_sheet.cell("C8").set_value("Column width 10") 31 | first_sheet.cell("D8").set_value("Column width 2") 32 | first_sheet.cell("E8").set_value("Column width 2") 33 | 34 | # Inspect proto->dict verification. 35 | output_dir = ( 36 | Path(__file__).resolve().parent / "golden_rendered_images" / "set_cell_width_height" 37 | ) 38 | output_path = spreadsheet.render(output=output_dir) 39 | print(f"Spreadsheet rendered to {output_path}") 40 | 41 | spreadsheet.save( 42 | file_type=FileOutputType.C_STAR_PROTO_JSON, 43 | filename=output_dir / "workbook__auto.json", 44 | overwrite=True, 45 | ) 46 | 47 | # output_path = spreadsheet.export() 48 | # print(f"Spreadsheet exported to {output_path}") 49 | 50 | 51 | if __name__ == "__main__": 52 | main() 53 | -------------------------------------------------------------------------------- /testdata/skills/agent_skills_spec.md: -------------------------------------------------------------------------------- 1 | # Agent Skills Spec 2 | 3 | A skill is a folder of instructions, scripts, and resources that agents can discover and load dynamically to perform better at specific tasks. In order for the folder to be recognized as a skill, it must contain a `SKILL.md` file. 4 | 5 | # Skill Folder Layout 6 | 7 | A minimal skill folder looks like this: 8 | 9 | ``` 10 | my-skill/ 11 | - SKILL.md 12 | ``` 13 | 14 | More complex skills can add additional directories and files as needed. 15 | 16 | 17 | # The SKILL.md file 18 | 19 | The skill's "entrypoint" is the `SKILL.md` file. It is the only file required to exist. The file must start with a YAML frontmatter followed by regular Markdown. 20 | 21 | ## YAML Frontmatter 22 | 23 | The YAML frontmatter has 2 required properties: 24 | 25 | - `name` 26 | - The name of the skill in hyphen-case 27 | - Restricted to lowercase Unicode alphanumeric + hyphen 28 | - Must match the name of the directory containing the SKILL.md 29 | - `description` 30 | - Description of what the skill does and when Claude should use it 31 | 32 | There are 3 optional properties: 33 | 34 | - `license` 35 | - The license applied to the skill 36 | - We recommend keeping it short (either the name of a license or the name of a bundled license file) 37 | - `allowed-tools` 38 | - A list of tools that are pre-approved to run 39 | - Currently only supported in Claude Code 40 | - `metadata` 41 | - A map from string keys to string values 42 | - Clients can use this to store additional properties not defined by the Agent Skills Spec 43 | - We recommend making your key names reasonably unique to avoid accidental conflicts 44 | 45 | ## Markdown Body 46 | 47 | The Markdown body has no restrictions on it. 48 | 49 | # Additional Information 50 | 51 | For a minimal example, see the `template-skill` example. 52 | 53 | # Version History 54 | 55 | - 1.0 (2025-10-16) Public Launch 56 | -------------------------------------------------------------------------------- /testdata/oai-skills/spreadsheets/examples/features/create_pie_chart.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pathlib import Path 4 | 5 | from oaiproto.coworker.pptx.chart_pb2 import Chart, LegendPosition 6 | 7 | from artifact_tool import FileOutputType, SpreadsheetArtifact 8 | 9 | 10 | def main() -> None: 11 | # New spreadsheet artifact 12 | spreadsheet = SpreadsheetArtifact("Scores") 13 | first_sheet = spreadsheet.sheet("GameX") 14 | 15 | # Seed some data 16 | first_sheet["A1:C1"].values = [["Player", "Game 1", "Game 2"]] 17 | first_sheet["A2:C5"].values = [ 18 | ["Vicky", 120, 100], 19 | ["Emily", 134, 95], 20 | ["Dibyo", 95, 110], 21 | ["Bobby", 105, 105], 22 | ] 23 | 24 | # Set up some ranges to use as labels (categories) and values for the charts 25 | labels = first_sheet.range("A2:A5") 26 | game1 = first_sheet.range("B2:B5") 27 | 28 | # Add a pie chart to the cell range E2:I14 29 | chart1 = first_sheet.charts.add( 30 | first_sheet.range("E2:I14"), 31 | Chart.ChartType.CHART_TYPE_PIE, 32 | title="Game Scores", 33 | ) 34 | chart1.add_series("Game 1", categories_range=labels, values_range=game1) 35 | 36 | # Show the legend and position it to the right 37 | chart1.legend.visible = True 38 | chart1.legend.position = LegendPosition.LEGEND_POSITION_RIGHT 39 | 40 | output_dir = Path(__file__).resolve().parent / "golden_rendered_images" / "create_pie_chart" 41 | output_path = spreadsheet.render(output=output_dir) 42 | print(f"Spreadsheet rendered to {output_path}") 43 | 44 | spreadsheet.save( 45 | file_type=FileOutputType.C_STAR_PROTO_JSON, 46 | filename=output_dir / "workbook__auto.json", 47 | overwrite=True, 48 | ) 49 | 50 | # output_path = spreadsheet.export() 51 | # print(f"Spreadsheet exported to {output_path}") 52 | 53 | 54 | if __name__ == "__main__": 55 | main() 56 | -------------------------------------------------------------------------------- /testdata/skills/react-component-generator/assets/CardComponent.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | interface ComponentNameProps { 4 | title: string; 5 | description?: string; 6 | imageUrl?: string; 7 | footer?: React.ReactNode; 8 | onClick?: () => void; 9 | className?: string; 10 | children?: React.ReactNode; 11 | } 12 | 13 | /** 14 | * ComponentName - A flexible card component 15 | * 16 | * @param props - Component props 17 | * @returns JSX.Element 18 | */ 19 | export const ComponentName: React.FC = ({ 20 | title, 21 | description, 22 | imageUrl, 23 | footer, 24 | onClick, 25 | className = '', 26 | children 27 | }) => { 28 | return ( 29 |
35 | {/* Image Section */} 36 | {imageUrl && ( 37 |
38 | {title} 43 |
44 | )} 45 | 46 | {/* Content Section */} 47 |
48 |

49 | {title} 50 |

51 | 52 | {description && ( 53 |

54 | {description} 55 |

56 | )} 57 | 58 | {children && ( 59 |
60 | {children} 61 |
62 | )} 63 |
64 | 65 | {/* Footer Section */} 66 | {footer && ( 67 |
68 | {footer} 69 |
70 | )} 71 |
72 | ); 73 | }; 74 | 75 | export default ComponentName; 76 | -------------------------------------------------------------------------------- /testdata/oai-skills/spreadsheets/examples/features/create_doughnut_chart.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pathlib import Path 4 | 5 | from oaiproto.coworker.pptx.chart_pb2 import Chart, LegendPosition 6 | 7 | from artifact_tool import FileOutputType, SpreadsheetArtifact 8 | 9 | 10 | def main() -> None: 11 | # New spreadsheet artifact 12 | spreadsheet = SpreadsheetArtifact("Scores") 13 | first_game_sheet = spreadsheet.sheet("Game1") 14 | 15 | # Seed some data 16 | first_game_sheet["A1:C1"].values = [["Player", "Game 1", "Game 2"]] 17 | first_game_sheet["A2:C5"].values = [ 18 | ["Vicky", 120, 100], 19 | ["Emily", 134, 95], 20 | ["Dibyo", 95, 110], 21 | ["Bobby", 105, 105], 22 | ] 23 | 24 | # Set up some ranges to use as labels (categories) and values for the charts 25 | labels = first_game_sheet.range("A2:A5") 26 | game1 = first_game_sheet.range("B2:B5") 27 | 28 | # Add a doughnut chart to the cell range E2:I14 29 | chart1 = first_game_sheet.charts.add( 30 | first_game_sheet.range("E2:I14"), 31 | Chart.ChartType.CHART_TYPE_DOUGHNUT, 32 | title="Game Scores", 33 | ) 34 | chart1.add_series("Game 1", categories_range=labels, values_range=game1) 35 | 36 | # Show the legend and position it to the right 37 | chart1.legend.visible = True 38 | chart1.legend.position = LegendPosition.LEGEND_POSITION_RIGHT 39 | 40 | output_dir = ( 41 | Path(__file__).resolve().parent / "golden_rendered_images" / "create_doughnut_chart" 42 | ) 43 | output_path = spreadsheet.render(output=output_dir) 44 | print(f"Spreadsheet rendered to {output_path}") 45 | 46 | spreadsheet.save( 47 | file_type=FileOutputType.C_STAR_PROTO_JSON, 48 | filename=output_dir / "workbook__auto.json", 49 | overwrite=True, 50 | ) 51 | 52 | # output_path = spreadsheet.export() 53 | # print(f"Spreadsheet exported to {output_path}") 54 | 55 | 56 | if __name__ == "__main__": 57 | main() 58 | -------------------------------------------------------------------------------- /log/golog_logger.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "github.com/kataras/golog" 5 | ) 6 | 7 | // GologLogger implements Logger interface using kataras/golog 8 | type GologLogger struct { 9 | logger *golog.Logger 10 | level LogLevel 11 | } 12 | 13 | var _ Logger = (*GologLogger)(nil) 14 | 15 | // NewGologLogger creates a new logger using an existing golog.Logger 16 | func NewGologLogger(logger *golog.Logger) *GologLogger { 17 | return &GologLogger{ 18 | logger: logger, 19 | level: LogLevelInfo, // default level 20 | } 21 | } 22 | 23 | // Debug logs debug messages 24 | func (l *GologLogger) Debug(format string, v ...any) { 25 | if l.level <= LogLevelDebug { 26 | args := append([]any{format}, v...) 27 | l.logger.Debug(args...) 28 | } 29 | } 30 | 31 | // Info logs informational messages 32 | func (l *GologLogger) Info(format string, v ...any) { 33 | if l.level <= LogLevelInfo { 34 | args := append([]any{format}, v...) 35 | l.logger.Info(args...) 36 | } 37 | } 38 | 39 | // Warn logs warning messages 40 | func (l *GologLogger) Warn(format string, v ...any) { 41 | if l.level <= LogLevelWarn { 42 | args := append([]any{format}, v...) 43 | l.logger.Warn(args...) 44 | } 45 | } 46 | 47 | // Error logs error messages 48 | func (l *GologLogger) Error(format string, v ...any) { 49 | if l.level <= LogLevelError { 50 | args := append([]any{format}, v...) 51 | l.logger.Error(args...) 52 | } 53 | } 54 | 55 | // SetLevel sets the log level 56 | func (l *GologLogger) SetLevel(level LogLevel) { 57 | l.level = level 58 | 59 | // Convert to golog level string 60 | gologLevel := "info" 61 | switch level { 62 | case LogLevelDebug: 63 | gologLevel = "debug" 64 | case LogLevelInfo: 65 | gologLevel = "info" 66 | case LogLevelWarn: 67 | gologLevel = "warn" 68 | case LogLevelError: 69 | gologLevel = "error" 70 | case LogLevelNone: 71 | gologLevel = "disable" 72 | } 73 | 74 | l.logger.SetLevel(gologLevel) 75 | } 76 | 77 | // GetLevel returns the current log level 78 | func (l *GologLogger) GetLevel() LogLevel { 79 | return l.level 80 | } 81 | -------------------------------------------------------------------------------- /tool/python_tool.go: -------------------------------------------------------------------------------- 1 | package tool 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | 7 | "os" 8 | "os/exec" 9 | "text/template" 10 | ) 11 | 12 | type PythonTool struct { 13 | } 14 | 15 | func (t *PythonTool) Run(args map[string]any, code string) (string, error) { 16 | tmpl, err := template.New("python").Parse(code) 17 | if err != nil { 18 | return "", fmt.Errorf("failed to parse python template: %w", err) 19 | } 20 | 21 | var script bytes.Buffer 22 | err = tmpl.Execute(&script, args) 23 | if err != nil { 24 | return "", fmt.Errorf("failed to execute python template: %w", err) 25 | } 26 | 27 | tmpfile, err := os.CreateTemp("", "python-*.py") 28 | if err != nil { 29 | return "", fmt.Errorf("failed to create temp file: %w", err) 30 | } 31 | defer os.Remove(tmpfile.Name()) 32 | 33 | if _, err := tmpfile.Write(script.Bytes()); err != nil { 34 | return "", fmt.Errorf("failed to write to temp file: %w", err) 35 | } 36 | if err := tmpfile.Close(); err != nil { 37 | return "", fmt.Errorf("failed to close temp file: %w", err) 38 | } 39 | 40 | return RunPythonScript(tmpfile.Name(), nil) 41 | } 42 | 43 | // RunPythonScript executes a Python script and returns its combined stdout and stderr. 44 | // It tries to use 'python3' first, then falls back to 'python'. 45 | func RunPythonScript(scriptPath string, args []string) (string, error) { 46 | pythonExe, err := exec.LookPath("python3") 47 | if err != nil { 48 | pythonExe, err = exec.LookPath("python") 49 | if err != nil { 50 | return "", fmt.Errorf("failed to find python3 or python in PATH: %w", err) 51 | } 52 | } 53 | 54 | cmd := exec.Command(pythonExe, append([]string{scriptPath}, args...)...) 55 | cmd.Env = os.Environ() 56 | var stdout, stderr bytes.Buffer 57 | cmd.Stdout = &stdout 58 | cmd.Stderr = &stderr 59 | 60 | err = cmd.Run() 61 | if err != nil { 62 | return "", fmt.Errorf("failed to run python script '%s' with '%s': %w\nStdout: %s\nStderr: %s", scriptPath, pythonExe, err, stdout.String(), stderr.String()) 63 | } 64 | 65 | return stdout.String() + stderr.String(), nil 66 | } 67 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /tool/knowledge_tool.go: -------------------------------------------------------------------------------- 1 | package tool 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "io" 8 | "net/http" 9 | "net/url" 10 | "strings" 11 | "time" 12 | ) 13 | 14 | // WikipediaSearch performs a search on Wikipedia for the given query and returns a summary. 15 | // It uses the Wikipedia API. 16 | func WikipediaSearch(query string) (string, error) { 17 | baseURL := "https://en.wikipedia.org/w/api.php" 18 | params := url.Values{} 19 | params.Add("action", "query") 20 | params.Add("format", "json") 21 | params.Add("prop", "extracts") 22 | params.Add("exintro", "") // Return only content before the first section 23 | params.Add("explaintext", "") // Return plain text 24 | params.Add("redirects", "1") // Resolve redirects 25 | params.Add("titles", query) 26 | 27 | searchURL := baseURL + "?" + params.Encode() 28 | 29 | client := http.Client{ 30 | Timeout: 10 * time.Second, 31 | } 32 | 33 | req, err := http.NewRequestWithContext(context.Background(), "GET", searchURL, nil) 34 | if err != nil { 35 | return "", fmt.Errorf("failed to create request: %w", err) 36 | } 37 | 38 | resp, err := client.Do(req) 39 | if err != nil { 40 | return "", fmt.Errorf("failed to perform Wikipedia search: %w", err) 41 | } 42 | defer resp.Body.Close() 43 | 44 | if resp.StatusCode != http.StatusOK { 45 | return "", fmt.Errorf("Wikipedia API returned status %d", resp.StatusCode) 46 | } 47 | 48 | body, err := io.ReadAll(resp.Body) 49 | if err != nil { 50 | return "", fmt.Errorf("failed to read response body: %w", err) 51 | } 52 | 53 | var result struct { 54 | Query struct { 55 | Pages map[string]struct { 56 | Extract string `json:"extract"` 57 | } `json:"pages"` 58 | } `json:"query"` 59 | } 60 | 61 | if err := json.Unmarshal(body, &result); err != nil { 62 | return "", fmt.Errorf("failed to unmarshal Wikipedia response: %w", err) 63 | } 64 | 65 | for _, page := range result.Query.Pages { 66 | if page.Extract != "" { 67 | // Clean up some common Wikipedia API artifacts 68 | extract := strings.ReplaceAll(page.Extract, "(listen)", "") 69 | extract = strings.TrimSpace(extract) 70 | return extract, nil 71 | } 72 | } 73 | 74 | return "No relevant Wikipedia entry found.", nil 75 | } 76 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/docx/ooxml/scripts/validate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Command line tool to validate Office document XML files against XSD schemas and tracked changes. 4 | 5 | Usage: 6 | python validate.py --original 7 | """ 8 | 9 | import argparse 10 | import sys 11 | from pathlib import Path 12 | 13 | from validation import DOCXSchemaValidator, PPTXSchemaValidator, RedliningValidator 14 | 15 | 16 | def main(): 17 | parser = argparse.ArgumentParser(description="Validate Office document XML files") 18 | parser.add_argument( 19 | "unpacked_dir", 20 | help="Path to unpacked Office document directory", 21 | ) 22 | parser.add_argument( 23 | "--original", 24 | required=True, 25 | help="Path to original file (.docx/.pptx/.xlsx)", 26 | ) 27 | parser.add_argument( 28 | "-v", 29 | "--verbose", 30 | action="store_true", 31 | help="Enable verbose output", 32 | ) 33 | args = parser.parse_args() 34 | 35 | # Validate paths 36 | unpacked_dir = Path(args.unpacked_dir) 37 | original_file = Path(args.original) 38 | file_extension = original_file.suffix.lower() 39 | assert unpacked_dir.is_dir(), f"Error: {unpacked_dir} is not a directory" 40 | assert original_file.is_file(), f"Error: {original_file} is not a file" 41 | assert file_extension in [".docx", ".pptx", ".xlsx"], ( 42 | f"Error: {original_file} must be a .docx, .pptx, or .xlsx file" 43 | ) 44 | 45 | # Run validations 46 | match file_extension: 47 | case ".docx": 48 | validators = [DOCXSchemaValidator, RedliningValidator] 49 | case ".pptx": 50 | validators = [PPTXSchemaValidator] 51 | case _: 52 | print(f"Error: Validation not supported for file type {file_extension}") 53 | sys.exit(1) 54 | 55 | # Run validators 56 | success = True 57 | for V in validators: 58 | validator = V(unpacked_dir, original_file, verbose=args.verbose) 59 | if not validator.validate(): 60 | success = False 61 | 62 | if success: 63 | print("All validations PASSED!") 64 | 65 | sys.exit(0 if success else 1) 66 | 67 | 68 | if __name__ == "__main__": 69 | main() 70 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/pptx/ooxml/scripts/validate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Command line tool to validate Office document XML files against XSD schemas and tracked changes. 4 | 5 | Usage: 6 | python validate.py --original 7 | """ 8 | 9 | import argparse 10 | import sys 11 | from pathlib import Path 12 | 13 | from validation import DOCXSchemaValidator, PPTXSchemaValidator, RedliningValidator 14 | 15 | 16 | def main(): 17 | parser = argparse.ArgumentParser(description="Validate Office document XML files") 18 | parser.add_argument( 19 | "unpacked_dir", 20 | help="Path to unpacked Office document directory", 21 | ) 22 | parser.add_argument( 23 | "--original", 24 | required=True, 25 | help="Path to original file (.docx/.pptx/.xlsx)", 26 | ) 27 | parser.add_argument( 28 | "-v", 29 | "--verbose", 30 | action="store_true", 31 | help="Enable verbose output", 32 | ) 33 | args = parser.parse_args() 34 | 35 | # Validate paths 36 | unpacked_dir = Path(args.unpacked_dir) 37 | original_file = Path(args.original) 38 | file_extension = original_file.suffix.lower() 39 | assert unpacked_dir.is_dir(), f"Error: {unpacked_dir} is not a directory" 40 | assert original_file.is_file(), f"Error: {original_file} is not a file" 41 | assert file_extension in [".docx", ".pptx", ".xlsx"], ( 42 | f"Error: {original_file} must be a .docx, .pptx, or .xlsx file" 43 | ) 44 | 45 | # Run validations 46 | match file_extension: 47 | case ".docx": 48 | validators = [DOCXSchemaValidator, RedliningValidator] 49 | case ".pptx": 50 | validators = [PPTXSchemaValidator] 51 | case _: 52 | print(f"Error: Validation not supported for file type {file_extension}") 53 | sys.exit(1) 54 | 55 | # Run validators 56 | success = True 57 | for V in validators: 58 | validator = V(unpacked_dir, original_file, verbose=args.verbose) 59 | if not validator.validate(): 60 | success = False 61 | 62 | if success: 63 | print("All validations PASSED!") 64 | 65 | sys.exit(0 if success else 1) 66 | 67 | 68 | if __name__ == "__main__": 69 | main() 70 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/docx/ooxml/scripts/validate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Command line tool to validate Office document XML files against XSD schemas and tracked changes. 4 | 5 | Usage: 6 | python validate.py --original 7 | """ 8 | 9 | import argparse 10 | import sys 11 | from pathlib import Path 12 | 13 | from validation import DOCXSchemaValidator, PPTXSchemaValidator, RedliningValidator 14 | 15 | 16 | def main(): 17 | parser = argparse.ArgumentParser(description="Validate Office document XML files") 18 | parser.add_argument( 19 | "unpacked_dir", 20 | help="Path to unpacked Office document directory", 21 | ) 22 | parser.add_argument( 23 | "--original", 24 | required=True, 25 | help="Path to original file (.docx/.pptx/.xlsx)", 26 | ) 27 | parser.add_argument( 28 | "-v", 29 | "--verbose", 30 | action="store_true", 31 | help="Enable verbose output", 32 | ) 33 | args = parser.parse_args() 34 | 35 | # Validate paths 36 | unpacked_dir = Path(args.unpacked_dir) 37 | original_file = Path(args.original) 38 | file_extension = original_file.suffix.lower() 39 | assert unpacked_dir.is_dir(), f"Error: {unpacked_dir} is not a directory" 40 | assert original_file.is_file(), f"Error: {original_file} is not a file" 41 | assert file_extension in [".docx", ".pptx", ".xlsx"], ( 42 | f"Error: {original_file} must be a .docx, .pptx, or .xlsx file" 43 | ) 44 | 45 | # Run validations 46 | match file_extension: 47 | case ".docx": 48 | validators = [DOCXSchemaValidator, RedliningValidator] 49 | case ".pptx": 50 | validators = [PPTXSchemaValidator] 51 | case _: 52 | print(f"Error: Validation not supported for file type {file_extension}") 53 | sys.exit(1) 54 | 55 | # Run validators 56 | success = True 57 | for V in validators: 58 | validator = V(unpacked_dir, original_file, verbose=args.verbose) 59 | if not validator.validate(): 60 | success = False 61 | 62 | if success: 63 | print("All validations PASSED!") 64 | 65 | sys.exit(0 if success else 1) 66 | 67 | 68 | if __name__ == "__main__": 69 | main() 70 | -------------------------------------------------------------------------------- /testdata/skills/document-skills/document-skills/pptx/ooxml/scripts/validate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Command line tool to validate Office document XML files against XSD schemas and tracked changes. 4 | 5 | Usage: 6 | python validate.py --original 7 | """ 8 | 9 | import argparse 10 | import sys 11 | from pathlib import Path 12 | 13 | from validation import DOCXSchemaValidator, PPTXSchemaValidator, RedliningValidator 14 | 15 | 16 | def main(): 17 | parser = argparse.ArgumentParser(description="Validate Office document XML files") 18 | parser.add_argument( 19 | "unpacked_dir", 20 | help="Path to unpacked Office document directory", 21 | ) 22 | parser.add_argument( 23 | "--original", 24 | required=True, 25 | help="Path to original file (.docx/.pptx/.xlsx)", 26 | ) 27 | parser.add_argument( 28 | "-v", 29 | "--verbose", 30 | action="store_true", 31 | help="Enable verbose output", 32 | ) 33 | args = parser.parse_args() 34 | 35 | # Validate paths 36 | unpacked_dir = Path(args.unpacked_dir) 37 | original_file = Path(args.original) 38 | file_extension = original_file.suffix.lower() 39 | assert unpacked_dir.is_dir(), f"Error: {unpacked_dir} is not a directory" 40 | assert original_file.is_file(), f"Error: {original_file} is not a file" 41 | assert file_extension in [".docx", ".pptx", ".xlsx"], ( 42 | f"Error: {original_file} must be a .docx, .pptx, or .xlsx file" 43 | ) 44 | 45 | # Run validations 46 | match file_extension: 47 | case ".docx": 48 | validators = [DOCXSchemaValidator, RedliningValidator] 49 | case ".pptx": 50 | validators = [PPTXSchemaValidator] 51 | case _: 52 | print(f"Error: Validation not supported for file type {file_extension}") 53 | sys.exit(1) 54 | 55 | # Run validators 56 | success = True 57 | for V in validators: 58 | validator = V(unpacked_dir, original_file, verbose=args.verbose) 59 | if not validator.validate(): 60 | success = False 61 | 62 | if success: 63 | print("All validations PASSED!") 64 | 65 | sys.exit(0 if success else 1) 66 | 67 | 68 | if __name__ == "__main__": 69 | main() 70 | -------------------------------------------------------------------------------- /testdata/skills/react-component-generator/assets/ListComponent.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | interface ListItem { 4 | id: string | number; 5 | title: string; 6 | description?: string; 7 | } 8 | 9 | interface ComponentNameProps { 10 | items: ListItem[]; 11 | onItemClick?: (item: ListItem) => void; 12 | onItemDelete?: (id: string | number) => void; 13 | className?: string; 14 | emptyMessage?: string; 15 | } 16 | 17 | /** 18 | * ComponentName - A reusable list component 19 | * 20 | * @param props - Component props 21 | * @returns JSX.Element 22 | */ 23 | export const ComponentName: React.FC = ({ 24 | items, 25 | onItemClick, 26 | onItemDelete, 27 | className = '', 28 | emptyMessage = 'No items to display' 29 | }) => { 30 | if (items.length === 0) { 31 | return ( 32 |
33 | {emptyMessage} 34 |
35 | ); 36 | } 37 | 38 | return ( 39 |
    40 | {items.map((item) => ( 41 |
  • 45 |
    onItemClick?.(item)} 48 | > 49 |

    50 | {item.title} 51 |

    52 | {item.description && ( 53 |

    54 | {item.description} 55 |

    56 | )} 57 |
    58 | 59 | {onItemDelete && ( 60 | 70 | )} 71 |
  • 72 | ))} 73 |
74 | ); 75 | }; 76 | 77 | export default ComponentName; 78 | -------------------------------------------------------------------------------- /testdata/skills/react-component-generator/assets/StatefulComponent.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { create } from 'zustand'; 3 | 4 | // Define the store interface 5 | interface ComponentNameStore { 6 | // State 7 | count: number; 8 | isLoading: boolean; 9 | 10 | // Actions 11 | increment: () => void; 12 | decrement: () => void; 13 | setLoading: (loading: boolean) => void; 14 | reset: () => void; 15 | } 16 | 17 | // Create the Zustand store 18 | export const useComponentNameStore = create((set) => ({ 19 | // Initial state 20 | count: 0, 21 | isLoading: false, 22 | 23 | // Actions 24 | increment: () => set((state) => ({ count: state.count + 1 })), 25 | decrement: () => set((state) => ({ count: state.count - 1 })), 26 | setLoading: (loading) => set({ isLoading: loading }), 27 | reset: () => set({ count: 0, isLoading: false }), 28 | })); 29 | 30 | interface ComponentNameProps { 31 | className?: string; 32 | } 33 | 34 | /** 35 | * ComponentName - A component with Zustand state management 36 | * 37 | * @param props - Component props 38 | * @returns JSX.Element 39 | */ 40 | export const ComponentName: React.FC = ({ 41 | className = '' 42 | }) => { 43 | const { count, isLoading, increment, decrement, reset } = useComponentNameStore(); 44 | 45 | return ( 46 |
47 |

Count: {count}

48 | 49 |
50 | 57 | 58 | 65 | 66 | 73 |
74 |
75 | ); 76 | }; 77 | 78 | export default ComponentName; 79 | -------------------------------------------------------------------------------- /testdata/skills/skill-creator/scripts/quick_validate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Quick validation script for skills - minimal version 4 | """ 5 | 6 | import sys 7 | import os 8 | import re 9 | from pathlib import Path 10 | 11 | def validate_skill(skill_path): 12 | """Basic validation of a skill""" 13 | skill_path = Path(skill_path) 14 | 15 | # Check SKILL.md exists 16 | skill_md = skill_path / 'SKILL.md' 17 | if not skill_md.exists(): 18 | return False, "SKILL.md not found" 19 | 20 | # Read and validate frontmatter 21 | content = skill_md.read_text() 22 | if not content.startswith('---'): 23 | return False, "No YAML frontmatter found" 24 | 25 | # Extract frontmatter 26 | match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL) 27 | if not match: 28 | return False, "Invalid frontmatter format" 29 | 30 | frontmatter = match.group(1) 31 | 32 | # Check required fields 33 | if 'name:' not in frontmatter: 34 | return False, "Missing 'name' in frontmatter" 35 | if 'description:' not in frontmatter: 36 | return False, "Missing 'description' in frontmatter" 37 | 38 | # Extract name for validation 39 | name_match = re.search(r'name:\s*(.+)', frontmatter) 40 | if name_match: 41 | name = name_match.group(1).strip() 42 | # Check naming convention (hyphen-case: lowercase with hyphens) 43 | if not re.match(r'^[a-z0-9-]+$', name): 44 | return False, f"Name '{name}' should be hyphen-case (lowercase letters, digits, and hyphens only)" 45 | if name.startswith('-') or name.endswith('-') or '--' in name: 46 | return False, f"Name '{name}' cannot start/end with hyphen or contain consecutive hyphens" 47 | 48 | # Extract and validate description 49 | desc_match = re.search(r'description:\s*(.+)', frontmatter) 50 | if desc_match: 51 | description = desc_match.group(1).strip() 52 | # Check for angle brackets 53 | if '<' in description or '>' in description: 54 | return False, "Description cannot contain angle brackets (< or >)" 55 | 56 | return True, "Skill is valid!" 57 | 58 | if __name__ == "__main__": 59 | if len(sys.argv) != 2: 60 | print("Usage: python quick_validate.py ") 61 | sys.exit(1) 62 | 63 | valid, message = validate_skill(sys.argv[1]) 64 | print(message) 65 | sys.exit(0 if valid else 1) -------------------------------------------------------------------------------- /testdata/skills/internal-comms/examples/faq-answers.md: -------------------------------------------------------------------------------- 1 | ## Instructions 2 | You are an assistant for answering questions that are being asked across the company. Every week, there are lots of questions that get asked across the company, and your goal is to try to summarize what those questions are. We want our company to be well-informed and on the same page, so your job is to produce a set of frequently asked questions that our employees are asking and attempt to answer them. Your singular job is to do two things: 3 | 4 | - Find questions that are big sources of confusion for lots of employees at the company, generally about things that affect a large portion of the employee base 5 | - Attempt to give a nice summarized answer to that question in order to minimize confusion. 6 | 7 | Some examples of areas that may be interesting to folks: recent corporate events (fundraising, new executives, etc.), upcoming launches, hiring progress, changes to vision or focus, etc. 8 | 9 | 10 | ## Tools Available 11 | You should use the company's available tools, where communication and work happens. For most companies, it looks something like this: 12 | - Slack: questions being asked across the company - it could be questions in response to posts with lots of responses, questions being asked with lots of reactions or thumbs up to show support, or anything else to show that a large number of employees want to ask the same things 13 | - Email: emails with FAQs written directly in them can be a good source as well 14 | - Documents: docs in places like Google Drive, linked on calendar events, etc. can also be a good source of FAQs, either directly added or inferred based on the contents of the doc 15 | 16 | ## Formatting 17 | The formatting should be pretty basic: 18 | 19 | - *Question*: [insert question - 1 sentence] 20 | - *Answer*: [insert answer - 1-2 sentence] 21 | 22 | ## Guidance 23 | Make sure you're being holistic in your questions. Don't focus too much on just the user in question or the team they are a part of, but try to capture the entire company. Try to be as holistic as you can in reading all the tools available, producing responses that are relevant to all at the company. 24 | 25 | ## Answer Guidelines 26 | - Base answers on official company communications when possible 27 | - If information is uncertain, indicate that clearly 28 | - Link to authoritative sources (docs, announcements, emails) 29 | - Keep tone professional but approachable 30 | - Flag if a question requires executive input or official response -------------------------------------------------------------------------------- /testdata/oai-skills/spreadsheets/examples/features/create_bar_chart.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pathlib import Path 4 | 5 | from oaiproto.coworker.pptx.chart_pb2 import BarDirection, BarGrouping, Chart 6 | 7 | from artifact_tool import FileOutputType, SpreadsheetArtifact 8 | from artifact_tool.models.charts import BarChart 9 | 10 | 11 | def main() -> None: 12 | # New spreadsheet artifact 13 | spreadsheet = SpreadsheetArtifact("Scores") 14 | game_sheet = spreadsheet.sheet("MyFavoriteGame") 15 | 16 | # Seed some data 17 | game_sheet["A1:C1"].values = [["Player", "Game 1", "Game 2"]] 18 | game_sheet["A2:C5"].values = [ 19 | ["Vicky", 120, 100], 20 | ["Emily", 134, 95], 21 | ["Dibyo", 95, 110], 22 | ["Bobby", 105, 105], 23 | ] 24 | 25 | # Set up some ranges to use as labels (categories) and values for the charts 26 | labels = game_sheet.range("A2:A5") 27 | game1 = game_sheet.range("B2:B5") 28 | game2 = game_sheet.range("C2:C5") 29 | 30 | # Add a vertical bar chart to the cell range E2:I14 31 | chart1 = game_sheet.charts.add( 32 | game_sheet.range("E2:I14"), 33 | Chart.ChartType.CHART_TYPE_BAR, 34 | title="Game Scores", 35 | ) 36 | chart1.add_series("Game 1", categories_range=labels, values_range=game1) 37 | chart1.add_series("Game 2", categories_range=labels, values_range=game2) 38 | 39 | # Add a horizontal bar chart to the cell range E17:I29 40 | chart2 = game_sheet.charts.add( 41 | game_sheet.range("E17:I29"), 42 | Chart.ChartType.CHART_TYPE_BAR, 43 | title="Total Scores", 44 | ) 45 | assert isinstance(chart2, BarChart) 46 | chart2.bar_direction = BarDirection.BAR_DIRECTION_BAR 47 | chart2.bar_grouping = BarGrouping.BAR_GROUPING_STACKED 48 | chart2.add_series("Game 1", categories_range=labels, values_range=game1) 49 | chart2.add_series("Game 2", categories_range=labels, values_range=game2) 50 | 51 | output_dir = Path(__file__).resolve().parent / "golden_rendered_images" / "create_bar_chart" 52 | output_path = spreadsheet.render(output=output_dir) 53 | print(f"Spreadsheet rendered to {output_path}") 54 | 55 | spreadsheet.save( 56 | file_type=FileOutputType.C_STAR_PROTO_JSON, 57 | filename=output_dir / "workbook__auto.json", 58 | overwrite=True, 59 | ) 60 | 61 | # output_path = spreadsheet.export() 62 | # print(f"Spreadsheet exported to {output_path}") 63 | 64 | 65 | if __name__ == "__main__": 66 | main() 67 | -------------------------------------------------------------------------------- /cmd/goskills-cli/detail.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "path/filepath" 6 | "strings" 7 | 8 | "github.com/smallnest/goskills" 9 | "github.com/spf13/cobra" 10 | ) 11 | 12 | var detailCmd = &cobra.Command{ 13 | Use: "detail ", 14 | Short: "Displays detailed information about a skill package.", 15 | Args: cobra.ExactArgs(1), 16 | RunE: func(cmd *cobra.Command, args []string) error { 17 | skillDir := args[0] 18 | absSkillDir, err := filepath.Abs(skillDir) 19 | if err != nil { 20 | return fmt.Errorf("failed to get absolute path for %s: %w", skillDir, err) 21 | } 22 | 23 | skillPackage, err := goskills.ParseSkillPackage(absSkillDir) 24 | if err != nil { 25 | return fmt.Errorf("failed to parse skill package: %w", err) 26 | } 27 | 28 | fmt.Printf("--- Skill Details: %s ---\n", skillPackage.Meta.Name) 29 | fmt.Printf("Path: %s\n", skillPackage.Path) 30 | fmt.Printf("Description: %s\n", skillPackage.Meta.Description) 31 | fmt.Printf("Allowed Tools: %s\n", strings.Join(skillPackage.Meta.AllowedTools, ", ")) 32 | if skillPackage.Meta.Model != "" { 33 | fmt.Printf("Model: %s\n", skillPackage.Meta.Model) 34 | } 35 | if skillPackage.Meta.Author != "" { 36 | fmt.Printf("Author: %s\n", skillPackage.Meta.Author) 37 | } 38 | if skillPackage.Meta.Version != "" { 39 | fmt.Printf("Version: %s\n", skillPackage.Meta.Version) 40 | } 41 | if skillPackage.Meta.License != "" { 42 | fmt.Printf("License: %s\n", skillPackage.Meta.License) 43 | } 44 | 45 | fmt.Println("\n--- SKILL.md Body ---") 46 | fmt.Println(skillPackage.Body) // Directly print the raw markdown body 47 | 48 | fmt.Println("\n--- Resources ---") 49 | if len(skillPackage.Resources.Scripts) > 0 { 50 | fmt.Println("Scripts:") 51 | for _, s := range skillPackage.Resources.Scripts { 52 | fmt.Printf(" - %s\n", s) 53 | } 54 | } 55 | if len(skillPackage.Resources.References) > 0 { 56 | fmt.Println("References:") 57 | for _, r := range skillPackage.Resources.References { 58 | fmt.Printf(" - %s\n", r) 59 | } 60 | } 61 | if len(skillPackage.Resources.Assets) > 0 { 62 | fmt.Println("Assets:") 63 | for _, a := range skillPackage.Resources.Assets { 64 | fmt.Printf(" - %s\n", a) 65 | } 66 | } 67 | if len(skillPackage.Resources.Scripts) == 0 && len(skillPackage.Resources.References) == 0 && len(skillPackage.Resources.Assets) == 0 { 68 | fmt.Println("No resources found.") 69 | } 70 | 71 | return nil 72 | }, 73 | } 74 | 75 | func init() { 76 | rootCmd.AddCommand(detailCmd) 77 | } 78 | -------------------------------------------------------------------------------- /testdata/skills/brand-guidelines/SKILL.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: brand-guidelines 3 | description: Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply. 4 | license: Complete terms in LICENSE.txt 5 | --- 6 | 7 | # Anthropic Brand Styling 8 | 9 | ## Overview 10 | 11 | To access Anthropic's official brand identity and style resources, use this skill. 12 | 13 | **Keywords**: branding, corporate identity, visual identity, post-processing, styling, brand colors, typography, Anthropic brand, visual formatting, visual design 14 | 15 | ## Brand Guidelines 16 | 17 | ### Colors 18 | 19 | **Main Colors:** 20 | 21 | - Dark: `#141413` - Primary text and dark backgrounds 22 | - Light: `#faf9f5` - Light backgrounds and text on dark 23 | - Mid Gray: `#b0aea5` - Secondary elements 24 | - Light Gray: `#e8e6dc` - Subtle backgrounds 25 | 26 | **Accent Colors:** 27 | 28 | - Orange: `#d97757` - Primary accent 29 | - Blue: `#6a9bcc` - Secondary accent 30 | - Green: `#788c5d` - Tertiary accent 31 | 32 | ### Typography 33 | 34 | - **Headings**: Poppins (with Arial fallback) 35 | - **Body Text**: Lora (with Georgia fallback) 36 | - **Note**: Fonts should be pre-installed in your environment for best results 37 | 38 | ## Features 39 | 40 | ### Smart Font Application 41 | 42 | - Applies Poppins font to headings (24pt and larger) 43 | - Applies Lora font to body text 44 | - Automatically falls back to Arial/Georgia if custom fonts unavailable 45 | - Preserves readability across all systems 46 | 47 | ### Text Styling 48 | 49 | - Headings (24pt+): Poppins font 50 | - Body text: Lora font 51 | - Smart color selection based on background 52 | - Preserves text hierarchy and formatting 53 | 54 | ### Shape and Accent Colors 55 | 56 | - Non-text shapes use accent colors 57 | - Cycles through orange, blue, and green accents 58 | - Maintains visual interest while staying on-brand 59 | 60 | ## Technical Details 61 | 62 | ### Font Management 63 | 64 | - Uses system-installed Poppins and Lora fonts when available 65 | - Provides automatic fallback to Arial (headings) and Georgia (body) 66 | - No font installation required - works with existing system fonts 67 | - For best results, pre-install Poppins and Lora fonts in your environment 68 | 69 | ### Color Application 70 | 71 | - Uses RGB color values for precise brand matching 72 | - Applied via python-pptx's RGBColor class 73 | - Maintains color fidelity across different systems 74 | --------------------------------------------------------------------------------