cli-jaw 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.ko.md +411 -0
- package/README.md +416 -0
- package/README.zh-CN.md +411 -0
- package/dist/bin/cli-jaw.js +108 -0
- package/dist/bin/cli-jaw.js.map +1 -0
- package/dist/bin/commands/browser.js +241 -0
- package/dist/bin/commands/browser.js.map +1 -0
- package/dist/bin/commands/chat.js +878 -0
- package/dist/bin/commands/chat.js.map +1 -0
- package/dist/bin/commands/doctor.js +152 -0
- package/dist/bin/commands/doctor.js.map +1 -0
- package/dist/bin/commands/employee.js +70 -0
- package/dist/bin/commands/employee.js.map +1 -0
- package/dist/bin/commands/init.js +110 -0
- package/dist/bin/commands/init.js.map +1 -0
- package/dist/bin/commands/mcp.js +219 -0
- package/dist/bin/commands/mcp.js.map +1 -0
- package/dist/bin/commands/memory.js +105 -0
- package/dist/bin/commands/memory.js.map +1 -0
- package/dist/bin/commands/reset.js +109 -0
- package/dist/bin/commands/reset.js.map +1 -0
- package/dist/bin/commands/serve.js +75 -0
- package/dist/bin/commands/serve.js.map +1 -0
- package/dist/bin/commands/skill.js +232 -0
- package/dist/bin/commands/skill.js.map +1 -0
- package/dist/bin/commands/status.js +51 -0
- package/dist/bin/commands/status.js.map +1 -0
- package/dist/bin/postinstall.js +218 -0
- package/dist/bin/postinstall.js.map +1 -0
- package/dist/lib/mcp-sync.js +639 -0
- package/dist/lib/mcp-sync.js.map +1 -0
- package/dist/lib/quota-copilot.js +62 -0
- package/dist/lib/quota-copilot.js.map +1 -0
- package/dist/lib/upload.js +72 -0
- package/dist/lib/upload.js.map +1 -0
- package/dist/server.js +832 -0
- package/dist/server.js.map +1 -0
- package/dist/src/agent/args.js +66 -0
- package/dist/src/agent/args.js.map +1 -0
- package/dist/src/agent/events.js +328 -0
- package/dist/src/agent/events.js.map +1 -0
- package/dist/src/agent/spawn.js +646 -0
- package/dist/src/agent/spawn.js.map +1 -0
- package/dist/src/browser/actions.js +168 -0
- package/dist/src/browser/actions.js.map +1 -0
- package/dist/src/browser/connection.js +79 -0
- package/dist/src/browser/connection.js.map +1 -0
- package/dist/src/browser/index.js +4 -0
- package/dist/src/browser/index.js.map +1 -0
- package/dist/src/browser/vision.js +128 -0
- package/dist/src/browser/vision.js.map +1 -0
- package/dist/src/cli/acp-client.js +298 -0
- package/dist/src/cli/acp-client.js.map +1 -0
- package/dist/src/cli/commands.js +267 -0
- package/dist/src/cli/commands.js.map +1 -0
- package/dist/src/cli/handlers.js +405 -0
- package/dist/src/cli/handlers.js.map +1 -0
- package/dist/src/cli/registry.js +87 -0
- package/dist/src/cli/registry.js.map +1 -0
- package/dist/src/command-contract/catalog.js +36 -0
- package/dist/src/command-contract/catalog.js.map +1 -0
- package/dist/src/command-contract/help-renderer.js +39 -0
- package/dist/src/command-contract/help-renderer.js.map +1 -0
- package/dist/src/command-contract/policy.js +34 -0
- package/dist/src/command-contract/policy.js.map +1 -0
- package/dist/src/core/bus.js +17 -0
- package/dist/src/core/bus.js.map +1 -0
- package/dist/src/core/config.js +198 -0
- package/dist/src/core/config.js.map +1 -0
- package/dist/src/core/db.js +97 -0
- package/dist/src/core/db.js.map +1 -0
- package/dist/src/core/i18n.js +86 -0
- package/dist/src/core/i18n.js.map +1 -0
- package/dist/src/core/logger.js +14 -0
- package/dist/src/core/logger.js.map +1 -0
- package/dist/src/core/settings-merge.js +40 -0
- package/dist/src/core/settings-merge.js.map +1 -0
- package/dist/src/http/async-handler.js +6 -0
- package/dist/src/http/async-handler.js.map +1 -0
- package/dist/src/http/error-middleware.js +24 -0
- package/dist/src/http/error-middleware.js.map +1 -0
- package/dist/src/http/response.js +16 -0
- package/dist/src/http/response.js.map +1 -0
- package/dist/src/memory/heartbeat.js +106 -0
- package/dist/src/memory/heartbeat.js.map +1 -0
- package/dist/src/memory/memory.js +119 -0
- package/dist/src/memory/memory.js.map +1 -0
- package/dist/src/memory/worklog.js +154 -0
- package/dist/src/memory/worklog.js.map +1 -0
- package/dist/src/orchestrator/distribute.js +310 -0
- package/dist/src/orchestrator/distribute.js.map +1 -0
- package/dist/src/orchestrator/parser.js +118 -0
- package/dist/src/orchestrator/parser.js.map +1 -0
- package/dist/src/orchestrator/pipeline.js +343 -0
- package/dist/src/orchestrator/pipeline.js.map +1 -0
- package/dist/src/prompt/builder.js +531 -0
- package/dist/src/prompt/builder.js.map +1 -0
- package/dist/src/routes/browser.js +126 -0
- package/dist/src/routes/browser.js.map +1 -0
- package/dist/src/routes/quota.js +94 -0
- package/dist/src/routes/quota.js.map +1 -0
- package/dist/src/security/decode.js +23 -0
- package/dist/src/security/decode.js.map +1 -0
- package/dist/src/security/path-guards.js +62 -0
- package/dist/src/security/path-guards.js.map +1 -0
- package/dist/src/telegram/bot.js +469 -0
- package/dist/src/telegram/bot.js.map +1 -0
- package/dist/src/telegram/forwarder.js +93 -0
- package/dist/src/telegram/forwarder.js.map +1 -0
- package/package.json +80 -0
- package/public/css/chat.css +571 -0
- package/public/css/layout.css +350 -0
- package/public/css/markdown.css +270 -0
- package/public/css/modals.css +172 -0
- package/public/css/sidebar.css +225 -0
- package/public/css/variables.css +142 -0
- package/public/index.html +470 -0
- package/public/js/api.js +55 -0
- package/public/js/constants.js +119 -0
- package/public/js/features/appname.js +43 -0
- package/public/js/features/chat.js +242 -0
- package/public/js/features/employees.js +120 -0
- package/public/js/features/heartbeat.js +80 -0
- package/public/js/features/i18n.js +125 -0
- package/public/js/features/memory.js +85 -0
- package/public/js/features/settings.js +512 -0
- package/public/js/features/sidebar.js +88 -0
- package/public/js/features/skills.js +68 -0
- package/public/js/features/slash-commands.js +231 -0
- package/public/js/features/theme.js +40 -0
- package/public/js/locale.js +23 -0
- package/public/js/main.js +281 -0
- package/public/js/render.js +294 -0
- package/public/js/state.js +16 -0
- package/public/js/ui.js +172 -0
- package/public/js/ws.js +76 -0
- package/public/locales/en.json +180 -0
- package/public/locales/ko.json +180 -0
- package/public/theme-test.html +545 -0
- package/skills_ref/1password/SKILL.md +70 -0
- package/skills_ref/agents-sdk/SKILL.md +155 -0
- package/skills_ref/agents-sdk/references/callable.md +92 -0
- package/skills_ref/agents-sdk/references/codemode.md +207 -0
- package/skills_ref/agents-sdk/references/email.md +146 -0
- package/skills_ref/agents-sdk/references/mcp.md +154 -0
- package/skills_ref/agents-sdk/references/state-scheduling.md +164 -0
- package/skills_ref/agents-sdk/references/streaming-chat.md +178 -0
- package/skills_ref/agents-sdk/references/workflows.md +132 -0
- package/skills_ref/algorithmic-art/LICENSE.txt +202 -0
- package/skills_ref/algorithmic-art/SKILL.md +405 -0
- package/skills_ref/algorithmic-art/templates/generator_template.js +223 -0
- package/skills_ref/algorithmic-art/templates/viewer.html +599 -0
- package/skills_ref/apple-notes/SKILL.md +77 -0
- package/skills_ref/apple-reminders/SKILL.md +118 -0
- package/skills_ref/atlas/SKILL.md +99 -0
- package/skills_ref/brainstorming/SKILL.md +96 -0
- package/skills_ref/browser/SKILL.md +179 -0
- package/skills_ref/canvas-design/LICENSE.txt +202 -0
- package/skills_ref/canvas-design/SKILL.md +130 -0
- package/skills_ref/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +93 -0
- package/skills_ref/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/BigShoulders-OFL.txt +93 -0
- package/skills_ref/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/Boldonse-OFL.txt +93 -0
- package/skills_ref/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
- package/skills_ref/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +93 -0
- package/skills_ref/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/DMMono-OFL.txt +93 -0
- package/skills_ref/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/EricaOne-OFL.txt +94 -0
- package/skills_ref/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/GeistMono-OFL.txt +93 -0
- package/skills_ref/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/Gloock-OFL.txt +93 -0
- package/skills_ref/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +93 -0
- package/skills_ref/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +93 -0
- package/skills_ref/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/Italiana-OFL.txt +93 -0
- package/skills_ref/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
- package/skills_ref/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/Jura-OFL.txt +93 -0
- package/skills_ref/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +93 -0
- package/skills_ref/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/Lora-OFL.txt +93 -0
- package/skills_ref/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/NationalPark-OFL.txt +93 -0
- package/skills_ref/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
- package/skills_ref/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/Outfit-OFL.txt +93 -0
- package/skills_ref/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/PixelifySans-OFL.txt +93 -0
- package/skills_ref/canvas-design/canvas-fonts/PoiretOne-OFL.txt +93 -0
- package/skills_ref/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/RedHatMono-OFL.txt +93 -0
- package/skills_ref/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/Silkscreen-OFL.txt +93 -0
- package/skills_ref/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/SmoochSans-OFL.txt +93 -0
- package/skills_ref/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/Tektur-OFL.txt +93 -0
- package/skills_ref/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/WorkSans-OFL.txt +93 -0
- package/skills_ref/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
- package/skills_ref/canvas-design/canvas-fonts/YoungSerif-OFL.txt +93 -0
- package/skills_ref/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
- package/skills_ref/changelog-generator/SKILL.md +104 -0
- package/skills_ref/cloudflare-deploy/SKILL.md +207 -0
- package/skills_ref/codebase-orientation/SKILL.md +29 -0
- package/skills_ref/config-file-explainer/SKILL.md +26 -0
- package/skills_ref/context-compression/SKILL.md +265 -0
- package/skills_ref/context-compression/references/evaluation-framework.md +213 -0
- package/skills_ref/context-compression/scripts/compression_evaluator.py +658 -0
- package/skills_ref/data-structure-chooser/SKILL.md +26 -0
- package/skills_ref/debugging-checklist/SKILL.md +26 -0
- package/skills_ref/debugging-helpers/CREATION-LOG.md +119 -0
- package/skills_ref/debugging-helpers/SKILL.md +296 -0
- package/skills_ref/debugging-helpers/condition-based-waiting-example.ts +158 -0
- package/skills_ref/debugging-helpers/condition-based-waiting.md +115 -0
- package/skills_ref/debugging-helpers/defense-in-depth.md +122 -0
- package/skills_ref/debugging-helpers/find-polluter.sh +63 -0
- package/skills_ref/debugging-helpers/root-cause-tracing.md +169 -0
- package/skills_ref/debugging-helpers/test-academic.md +14 -0
- package/skills_ref/debugging-helpers/test-pressure-1.md +58 -0
- package/skills_ref/debugging-helpers/test-pressure-2.md +68 -0
- package/skills_ref/debugging-helpers/test-pressure-3.md +69 -0
- package/skills_ref/deep-research/.env.example +7 -0
- package/skills_ref/deep-research/README.md +246 -0
- package/skills_ref/deep-research/SKILL.md +106 -0
- package/skills_ref/deep-research/requirements.txt +2 -0
- package/skills_ref/deep-research/scripts/research.py +692 -0
- package/skills_ref/dependency-install-helper/SKILL.md +26 -0
- package/skills_ref/dev/SKILL.md +65 -0
- package/skills_ref/dev-backend/SKILL.md +61 -0
- package/skills_ref/dev-data/SKILL.md +76 -0
- package/skills_ref/dev-frontend/LICENSE.txt +177 -0
- package/skills_ref/dev-frontend/SKILL.md +42 -0
- package/skills_ref/dev-testing/LICENSE.txt +202 -0
- package/skills_ref/dev-testing/SKILL.md +96 -0
- package/skills_ref/dev-testing/examples/console_logging.py +35 -0
- package/skills_ref/dev-testing/examples/element_discovery.py +40 -0
- package/skills_ref/dev-testing/examples/static_html_automation.py +33 -0
- package/skills_ref/dev-testing/scripts/with_server.py +106 -0
- package/skills_ref/develop-web-game/SKILL.md +149 -0
- package/skills_ref/differential-review/.claude-plugin/plugin.json +10 -0
- package/skills_ref/differential-review/README.md +109 -0
- package/skills_ref/differential-review/commands/diff-review.md +21 -0
- package/skills_ref/differential-review/skills/differential-review/SKILL.md +220 -0
- package/skills_ref/differential-review/skills/differential-review/adversarial.md +203 -0
- package/skills_ref/differential-review/skills/differential-review/methodology.md +234 -0
- package/skills_ref/differential-review/skills/differential-review/patterns.md +300 -0
- package/skills_ref/differential-review/skills/differential-review/reporting.md +369 -0
- package/skills_ref/dispatching-parallel-agents/SKILL.md +180 -0
- package/skills_ref/doc-coauthoring/SKILL.md +375 -0
- package/skills_ref/docx/LICENSE.txt +30 -0
- package/skills_ref/docx/SKILL.md +481 -0
- package/skills_ref/docx/scripts/__init__.py +1 -0
- package/skills_ref/docx/scripts/accept_changes.py +135 -0
- package/skills_ref/docx/scripts/comment.py +318 -0
- package/skills_ref/docx/scripts/office/helpers/__init__.py +0 -0
- package/skills_ref/docx/scripts/office/helpers/merge_runs.py +199 -0
- package/skills_ref/docx/scripts/office/helpers/simplify_redlines.py +197 -0
- package/skills_ref/docx/scripts/office/pack.py +159 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/skills_ref/docx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/skills_ref/docx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/skills_ref/docx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/skills_ref/docx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/skills_ref/docx/scripts/office/schemas/mce/mc.xsd +75 -0
- package/skills_ref/docx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
- package/skills_ref/docx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
- package/skills_ref/docx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
- package/skills_ref/docx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/skills_ref/docx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/skills_ref/docx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/skills_ref/docx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/skills_ref/docx/scripts/office/soffice.py +183 -0
- package/skills_ref/docx/scripts/office/unpack.py +132 -0
- package/skills_ref/docx/scripts/office/validate.py +111 -0
- package/skills_ref/docx/scripts/office/validators/__init__.py +15 -0
- package/skills_ref/docx/scripts/office/validators/base.py +847 -0
- package/skills_ref/docx/scripts/office/validators/docx.py +446 -0
- package/skills_ref/docx/scripts/office/validators/pptx.py +275 -0
- package/skills_ref/docx/scripts/office/validators/redlining.py +247 -0
- package/skills_ref/docx/scripts/templates/comments.xml +3 -0
- package/skills_ref/docx/scripts/templates/commentsExtended.xml +3 -0
- package/skills_ref/docx/scripts/templates/commentsExtensible.xml +3 -0
- package/skills_ref/docx/scripts/templates/commentsIds.xml +3 -0
- package/skills_ref/docx/scripts/templates/people.xml +3 -0
- package/skills_ref/durable-objects/SKILL.md +186 -0
- package/skills_ref/durable-objects/references/rules.md +286 -0
- package/skills_ref/durable-objects/references/testing.md +264 -0
- package/skills_ref/durable-objects/references/workers.md +346 -0
- package/skills_ref/email-draft-polish/SKILL.md +24 -0
- package/skills_ref/error-message-explainer/SKILL.md +27 -0
- package/skills_ref/fal-image-edit/SKILL.md +249 -0
- package/skills_ref/fal-image-edit/scripts/edit-image.sh +199 -0
- package/skills_ref/figma-implement-design/SKILL.md +264 -0
- package/skills_ref/git-worktrees/SKILL.md +218 -0
- package/skills_ref/github/SKILL.md +210 -0
- package/skills_ref/gog/SKILL.md +116 -0
- package/skills_ref/goplaces/SKILL.md +52 -0
- package/skills_ref/himalaya/SKILL.md +257 -0
- package/skills_ref/hugging-face-cli/SKILL.md +186 -0
- package/skills_ref/hugging-face-cli/references/commands.md +954 -0
- package/skills_ref/hugging-face-cli/references/examples.md +374 -0
- package/skills_ref/hugging-face-evaluation/SKILL.md +651 -0
- package/skills_ref/hugging-face-evaluation/examples/.env.example +7 -0
- package/skills_ref/hugging-face-evaluation/examples/USAGE_EXAMPLES.md +382 -0
- package/skills_ref/hugging-face-evaluation/examples/artificial_analysis_to_hub.py +141 -0
- package/skills_ref/hugging-face-evaluation/examples/example_readme_tables.md +135 -0
- package/skills_ref/hugging-face-evaluation/examples/metric_mapping.json +50 -0
- package/skills_ref/hugging-face-evaluation/requirements.txt +20 -0
- package/skills_ref/hugging-face-evaluation/scripts/evaluation_manager.py +1374 -0
- package/skills_ref/hugging-face-evaluation/scripts/inspect_eval_uv.py +104 -0
- package/skills_ref/hugging-face-evaluation/scripts/inspect_vllm_uv.py +317 -0
- package/skills_ref/hugging-face-evaluation/scripts/lighteval_vllm_uv.py +303 -0
- package/skills_ref/hugging-face-evaluation/scripts/run_eval_job.py +98 -0
- package/skills_ref/hugging-face-evaluation/scripts/run_vllm_eval_job.py +331 -0
- package/skills_ref/hugging-face-evaluation/scripts/test_extraction.py +206 -0
- package/skills_ref/hugging-face-model-trainer/SKILL.md +718 -0
- package/skills_ref/hugging-face-model-trainer/references/gguf_conversion.md +296 -0
- package/skills_ref/hugging-face-model-trainer/references/hardware_guide.md +283 -0
- package/skills_ref/hugging-face-model-trainer/references/hub_saving.md +364 -0
- package/skills_ref/hugging-face-model-trainer/references/reliability_principles.md +371 -0
- package/skills_ref/hugging-face-model-trainer/references/trackio_guide.md +189 -0
- package/skills_ref/hugging-face-model-trainer/references/training_methods.md +150 -0
- package/skills_ref/hugging-face-model-trainer/references/training_patterns.md +203 -0
- package/skills_ref/hugging-face-model-trainer/references/troubleshooting.md +282 -0
- package/skills_ref/hugging-face-model-trainer/references/unsloth.md +313 -0
- package/skills_ref/hugging-face-model-trainer/scripts/convert_to_gguf.py +424 -0
- package/skills_ref/hugging-face-model-trainer/scripts/dataset_inspector.py +417 -0
- package/skills_ref/hugging-face-model-trainer/scripts/estimate_cost.py +150 -0
- package/skills_ref/hugging-face-model-trainer/scripts/train_dpo_example.py +106 -0
- package/skills_ref/hugging-face-model-trainer/scripts/train_grpo_example.py +89 -0
- package/skills_ref/hugging-face-model-trainer/scripts/train_sft_example.py +122 -0
- package/skills_ref/hugging-face-model-trainer/scripts/unsloth_sft_example.py +512 -0
- package/skills_ref/imagegen/SKILL.md +174 -0
- package/skills_ref/insecure-defaults/.claude-plugin/plugin.json +10 -0
- package/skills_ref/insecure-defaults/README.md +45 -0
- package/skills_ref/insecure-defaults/skills/insecure-defaults/SKILL.md +117 -0
- package/skills_ref/insecure-defaults/skills/insecure-defaults/references/examples.md +409 -0
- package/skills_ref/jupyter-notebook/SKILL.md +107 -0
- package/skills_ref/linear/SKILL.md +87 -0
- package/skills_ref/linter-fix-guide/SKILL.md +27 -0
- package/skills_ref/log-summarizer/SKILL.md +27 -0
- package/skills_ref/mcp-builder/LICENSE.txt +202 -0
- package/skills_ref/mcp-builder/SKILL.md +236 -0
- package/skills_ref/mcp-builder/reference/evaluation.md +602 -0
- package/skills_ref/mcp-builder/reference/mcp_best_practices.md +249 -0
- package/skills_ref/mcp-builder/reference/node_mcp_server.md +970 -0
- package/skills_ref/mcp-builder/reference/python_mcp_server.md +719 -0
- package/skills_ref/mcp-builder/scripts/connections.py +151 -0
- package/skills_ref/mcp-builder/scripts/evaluation.py +373 -0
- package/skills_ref/mcp-builder/scripts/example_evaluation.xml +22 -0
- package/skills_ref/mcp-builder/scripts/requirements.txt +2 -0
- package/skills_ref/memory/SKILL.md +129 -0
- package/skills_ref/modern-python/.claude-plugin/plugin.json +10 -0
- package/skills_ref/modern-python/README.md +66 -0
- package/skills_ref/modern-python/hooks/hooks.json +16 -0
- package/skills_ref/modern-python/hooks/setup-shims.bats +70 -0
- package/skills_ref/modern-python/hooks/setup-shims.sh +24 -0
- package/skills_ref/modern-python/hooks/shims/pip +27 -0
- package/skills_ref/modern-python/hooks/shims/pip-shim.bats +45 -0
- package/skills_ref/modern-python/hooks/shims/pip3 +27 -0
- package/skills_ref/modern-python/hooks/shims/pipx +41 -0
- package/skills_ref/modern-python/hooks/shims/pipx-shim.bats +64 -0
- package/skills_ref/modern-python/hooks/shims/python +26 -0
- package/skills_ref/modern-python/hooks/shims/python-shim.bats +53 -0
- package/skills_ref/modern-python/hooks/shims/python3 +26 -0
- package/skills_ref/modern-python/hooks/shims/uv +27 -0
- package/skills_ref/modern-python/hooks/shims/uv-shim.bats +47 -0
- package/skills_ref/modern-python/skills/modern-python/SKILL.md +333 -0
- package/skills_ref/modern-python/skills/modern-python/references/dependabot.md +43 -0
- package/skills_ref/modern-python/skills/modern-python/references/migration-checklist.md +141 -0
- package/skills_ref/modern-python/skills/modern-python/references/pep723-scripts.md +259 -0
- package/skills_ref/modern-python/skills/modern-python/references/prek.md +211 -0
- package/skills_ref/modern-python/skills/modern-python/references/pyproject.md +254 -0
- package/skills_ref/modern-python/skills/modern-python/references/ruff-config.md +240 -0
- package/skills_ref/modern-python/skills/modern-python/references/security-setup.md +255 -0
- package/skills_ref/modern-python/skills/modern-python/references/testing.md +284 -0
- package/skills_ref/modern-python/skills/modern-python/references/uv-commands.md +200 -0
- package/skills_ref/modern-python/skills/modern-python/templates/dependabot.yml +36 -0
- package/skills_ref/modern-python/skills/modern-python/templates/pre-commit-config.yaml +66 -0
- package/skills_ref/nano-banana-pro/SKILL.md +58 -0
- package/skills_ref/netlify-deploy/SKILL.md +233 -0
- package/skills_ref/notion/SKILL.md +304 -0
- package/skills_ref/notion-knowledge-capture/SKILL.md +56 -0
- package/skills_ref/notion-meeting-intelligence/SKILL.md +60 -0
- package/skills_ref/notion-research-documentation/SKILL.md +59 -0
- package/skills_ref/notion-spec-to-implementation/SKILL.md +58 -0
- package/skills_ref/obsidian/SKILL.md +81 -0
- package/skills_ref/openai-docs/SKILL.md +56 -0
- package/skills_ref/openhue/SKILL.md +112 -0
- package/skills_ref/pdf/SKILL.md +69 -0
- package/skills_ref/postgres/README.md +77 -0
- package/skills_ref/postgres/SKILL.md +129 -0
- package/skills_ref/postgres/connections.example.json +34 -0
- package/skills_ref/postgres/requirements.txt +1 -0
- package/skills_ref/postgres/scripts/query.py +262 -0
- package/skills_ref/pptx/LICENSE.txt +30 -0
- package/skills_ref/pptx/SKILL.md +232 -0
- package/skills_ref/pptx/editing.md +205 -0
- package/skills_ref/pptx/pptxgenjs.md +420 -0
- package/skills_ref/pptx/scripts/__init__.py +0 -0
- package/skills_ref/pptx/scripts/add_slide.py +195 -0
- package/skills_ref/pptx/scripts/clean.py +286 -0
- package/skills_ref/pptx/scripts/office/helpers/__init__.py +0 -0
- package/skills_ref/pptx/scripts/office/helpers/merge_runs.py +199 -0
- package/skills_ref/pptx/scripts/office/helpers/simplify_redlines.py +197 -0
- package/skills_ref/pptx/scripts/office/pack.py +159 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/skills_ref/pptx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/skills_ref/pptx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/skills_ref/pptx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/skills_ref/pptx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/skills_ref/pptx/scripts/office/schemas/mce/mc.xsd +75 -0
- package/skills_ref/pptx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
- package/skills_ref/pptx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
- package/skills_ref/pptx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
- package/skills_ref/pptx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/skills_ref/pptx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/skills_ref/pptx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/skills_ref/pptx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/skills_ref/pptx/scripts/office/soffice.py +183 -0
- package/skills_ref/pptx/scripts/office/unpack.py +132 -0
- package/skills_ref/pptx/scripts/office/validate.py +111 -0
- package/skills_ref/pptx/scripts/office/validators/__init__.py +15 -0
- package/skills_ref/pptx/scripts/office/validators/base.py +847 -0
- package/skills_ref/pptx/scripts/office/validators/docx.py +446 -0
- package/skills_ref/pptx/scripts/office/validators/pptx.py +275 -0
- package/skills_ref/pptx/scripts/office/validators/redlining.py +247 -0
- package/skills_ref/pptx/scripts/thumbnail.py +289 -0
- package/skills_ref/property-based-testing/.claude-plugin/plugin.json +9 -0
- package/skills_ref/property-based-testing/README.md +47 -0
- package/skills_ref/property-based-testing/skills/property-based-testing/README.md +88 -0
- package/skills_ref/property-based-testing/skills/property-based-testing/SKILL.md +123 -0
- package/skills_ref/property-based-testing/skills/property-based-testing/references/design.md +191 -0
- package/skills_ref/property-based-testing/skills/property-based-testing/references/generating.md +204 -0
- package/skills_ref/property-based-testing/skills/property-based-testing/references/interpreting-failures.md +239 -0
- package/skills_ref/property-based-testing/skills/property-based-testing/references/libraries.md +130 -0
- package/skills_ref/property-based-testing/skills/property-based-testing/references/refactoring.md +181 -0
- package/skills_ref/property-based-testing/skills/property-based-testing/references/reviewing.md +209 -0
- package/skills_ref/property-based-testing/skills/property-based-testing/references/strategies.md +124 -0
- package/skills_ref/react-best-practices/AGENTS.md +2934 -0
- package/skills_ref/react-best-practices/README.md +123 -0
- package/skills_ref/react-best-practices/SKILL.md +136 -0
- package/skills_ref/react-best-practices/metadata.json +15 -0
- package/skills_ref/react-best-practices/rules/_sections.md +46 -0
- package/skills_ref/react-best-practices/rules/_template.md +28 -0
- package/skills_ref/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/skills_ref/react-best-practices/rules/advanced-init-once.md +42 -0
- package/skills_ref/react-best-practices/rules/advanced-use-latest.md +39 -0
- package/skills_ref/react-best-practices/rules/async-api-routes.md +38 -0
- package/skills_ref/react-best-practices/rules/async-defer-await.md +80 -0
- package/skills_ref/react-best-practices/rules/async-dependencies.md +51 -0
- package/skills_ref/react-best-practices/rules/async-parallel.md +28 -0
- package/skills_ref/react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/skills_ref/react-best-practices/rules/bundle-barrel-imports.md +59 -0
- package/skills_ref/react-best-practices/rules/bundle-conditional.md +31 -0
- package/skills_ref/react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/skills_ref/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/skills_ref/react-best-practices/rules/bundle-preload.md +50 -0
- package/skills_ref/react-best-practices/rules/client-event-listeners.md +74 -0
- package/skills_ref/react-best-practices/rules/client-localstorage-schema.md +71 -0
- package/skills_ref/react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/skills_ref/react-best-practices/rules/client-swr-dedup.md +56 -0
- package/skills_ref/react-best-practices/rules/js-batch-dom-css.md +107 -0
- package/skills_ref/react-best-practices/rules/js-cache-function-results.md +80 -0
- package/skills_ref/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/skills_ref/react-best-practices/rules/js-cache-storage.md +70 -0
- package/skills_ref/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/skills_ref/react-best-practices/rules/js-early-exit.md +50 -0
- package/skills_ref/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/skills_ref/react-best-practices/rules/js-index-maps.md +37 -0
- package/skills_ref/react-best-practices/rules/js-length-check-first.md +49 -0
- package/skills_ref/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/skills_ref/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/skills_ref/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/skills_ref/react-best-practices/rules/rendering-activity.md +26 -0
- package/skills_ref/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/skills_ref/react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/skills_ref/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/skills_ref/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/skills_ref/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/skills_ref/react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
- package/skills_ref/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/skills_ref/react-best-practices/rules/rendering-usetransition-loading.md +75 -0
- package/skills_ref/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/skills_ref/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/skills_ref/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
- package/skills_ref/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/skills_ref/react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/skills_ref/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/skills_ref/react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
- package/skills_ref/react-best-practices/rules/rerender-memo.md +44 -0
- package/skills_ref/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
- package/skills_ref/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
- package/skills_ref/react-best-practices/rules/rerender-transitions.md +40 -0
- package/skills_ref/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
- package/skills_ref/react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/skills_ref/react-best-practices/rules/server-auth-actions.md +96 -0
- package/skills_ref/react-best-practices/rules/server-cache-lru.md +41 -0
- package/skills_ref/react-best-practices/rules/server-cache-react.md +76 -0
- package/skills_ref/react-best-practices/rules/server-dedup-props.md +65 -0
- package/skills_ref/react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/skills_ref/react-best-practices/rules/server-serialization.md +38 -0
- package/skills_ref/receiving-code-review/SKILL.md +213 -0
- package/skills_ref/registry.json +1493 -0
- package/skills_ref/render-deploy/SKILL.md +462 -0
- package/skills_ref/requesting-code-review/SKILL.md +105 -0
- package/skills_ref/requesting-code-review/code-reviewer.md +146 -0
- package/skills_ref/screen-capture/SKILL.md +162 -0
- package/skills_ref/security-best-practices/LICENSE.txt +201 -0
- package/skills_ref/security-best-practices/SKILL.md +86 -0
- package/skills_ref/security-best-practices/agents/openai.yaml +4 -0
- package/skills_ref/security-best-practices/references/golang-general-backend-security.md +826 -0
- package/skills_ref/security-best-practices/references/javascript-express-web-server-security.md +1158 -0
- package/skills_ref/security-best-practices/references/javascript-general-web-frontend-security.md +747 -0
- package/skills_ref/security-best-practices/references/javascript-jquery-web-frontend-security.md +678 -0
- package/skills_ref/security-best-practices/references/javascript-typescript-nextjs-web-server-security.md +1144 -0
- package/skills_ref/security-best-practices/references/javascript-typescript-react-web-frontend-security.md +990 -0
- package/skills_ref/security-best-practices/references/javascript-typescript-vue-web-frontend-security.md +791 -0
- package/skills_ref/security-best-practices/references/python-django-web-server-security.md +882 -0
- package/skills_ref/security-best-practices/references/python-fastapi-web-server-security.md +1036 -0
- package/skills_ref/security-best-practices/references/python-flask-web-server-security.md +705 -0
- package/skills_ref/security-ownership-map/LICENSE.txt +201 -0
- package/skills_ref/security-ownership-map/SKILL.md +206 -0
- package/skills_ref/security-ownership-map/agents/openai.yaml +4 -0
- package/skills_ref/security-ownership-map/references/neo4j-import.md +60 -0
- package/skills_ref/security-ownership-map/scripts/build_ownership_map.py +956 -0
- package/skills_ref/security-ownership-map/scripts/community_maintainers.py +544 -0
- package/skills_ref/security-ownership-map/scripts/query_ownership.py +483 -0
- package/skills_ref/security-ownership-map/scripts/run_ownership_map.py +200 -0
- package/skills_ref/security-threat-model/LICENSE.txt +201 -0
- package/skills_ref/security-threat-model/SKILL.md +81 -0
- package/skills_ref/security-threat-model/agents/openai.yaml +4 -0
- package/skills_ref/security-threat-model/references/prompt-template.md +255 -0
- package/skills_ref/security-threat-model/references/security-controls-and-assets.md +32 -0
- package/skills_ref/sentry/SKILL.md +123 -0
- package/skills_ref/skill-creator/SKILL.md +372 -0
- package/skills_ref/sora/SKILL.md +153 -0
- package/skills_ref/speech/SKILL.md +144 -0
- package/skills_ref/spotify-player/SKILL.md +64 -0
- package/skills_ref/static-analysis/.claude-plugin/plugin.json +8 -0
- package/skills_ref/static-analysis/README.md +65 -0
- package/skills_ref/static-analysis/agents/semgrep-scanner.md +71 -0
- package/skills_ref/static-analysis/agents/semgrep-triager.md +107 -0
- package/skills_ref/static-analysis/skills/codeql/SKILL.md +119 -0
- package/skills_ref/static-analysis/skills/codeql/references/diagnostic-query-templates.md +339 -0
- package/skills_ref/static-analysis/skills/codeql/references/language-details.md +207 -0
- package/skills_ref/static-analysis/skills/codeql/references/performance-tuning.md +111 -0
- package/skills_ref/static-analysis/skills/codeql/references/ruleset-catalog.md +63 -0
- package/skills_ref/static-analysis/skills/codeql/references/threat-models.md +44 -0
- package/skills_ref/static-analysis/skills/codeql/workflows/build-database.md +669 -0
- package/skills_ref/static-analysis/skills/codeql/workflows/create-data-extensions.md +536 -0
- package/skills_ref/static-analysis/skills/codeql/workflows/run-analysis.md +436 -0
- package/skills_ref/static-analysis/skills/sarif-parsing/SKILL.md +479 -0
- package/skills_ref/static-analysis/skills/sarif-parsing/resources/jq-queries.md +162 -0
- package/skills_ref/static-analysis/skills/sarif-parsing/resources/sarif_helpers.py +331 -0
- package/skills_ref/static-analysis/skills/semgrep/SKILL.md +431 -0
- package/skills_ref/static-analysis/skills/semgrep/references/rulesets.md +162 -0
- package/skills_ref/static-analysis/skills/semgrep/references/scanner-task-prompt.md +102 -0
- package/skills_ref/static-analysis/skills/semgrep/references/triage-task-prompt.md +122 -0
- package/skills_ref/static-analysis/skills/semgrep/scripts/merge_triaged_sarif.py +252 -0
- package/skills_ref/summarize/SKILL.md +87 -0
- package/skills_ref/tdd/SKILL.md +371 -0
- package/skills_ref/tdd/testing-anti-patterns.md +299 -0
- package/skills_ref/telegram-send/SKILL.md +99 -0
- package/skills_ref/terraform/README.md +105 -0
- package/skills_ref/terraform/code-generation/.claude-plugin/plugin.json +30 -0
- package/skills_ref/terraform/code-generation/skills/azure-verified-modules/SKILL.md +613 -0
- package/skills_ref/terraform/code-generation/skills/terraform-style-guide/SKILL.md +353 -0
- package/skills_ref/terraform/code-generation/skills/terraform-test/SKILL.md +1669 -0
- package/skills_ref/terraform/module-generation/.claude-plugin/plugin.json +30 -0
- package/skills_ref/terraform/module-generation/skills/refactor-module/SKILL.md +538 -0
- package/skills_ref/terraform/module-generation/skills/terraform-stacks/SKILL.md +468 -0
- package/skills_ref/terraform/module-generation/skills/terraform-stacks/references/api-monitoring.md +543 -0
- package/skills_ref/terraform/module-generation/skills/terraform-stacks/references/component-blocks.md +476 -0
- package/skills_ref/terraform/module-generation/skills/terraform-stacks/references/deployment-blocks.md +391 -0
- package/skills_ref/terraform/module-generation/skills/terraform-stacks/references/examples.md +1529 -0
- package/skills_ref/terraform/module-generation/skills/terraform-stacks/references/linked-stacks.md +187 -0
- package/skills_ref/terraform/module-generation/skills/terraform-stacks/references/troubleshooting.md +671 -0
- package/skills_ref/terraform/provider-development/.claude-plugin/plugin.json +13 -0
- package/skills_ref/terraform/provider-development/skills/new-terraform-provider/SKILL.md +25 -0
- package/skills_ref/terraform/provider-development/skills/new-terraform-provider/assets/main.go +40 -0
- package/skills_ref/terraform/provider-development/skills/provider-actions/SKILL.md +478 -0
- package/skills_ref/terraform/provider-development/skills/provider-resources/SKILL.md +599 -0
- package/skills_ref/terraform/provider-development/skills/run-acceptance-tests/SKILL.md +41 -0
- package/skills_ref/theme-factory/LICENSE.txt +202 -0
- package/skills_ref/theme-factory/SKILL.md +59 -0
- package/skills_ref/theme-factory/theme-showcase.pdf +0 -0
- package/skills_ref/theme-factory/themes/arctic-frost.md +19 -0
- package/skills_ref/theme-factory/themes/botanical-garden.md +19 -0
- package/skills_ref/theme-factory/themes/desert-rose.md +19 -0
- package/skills_ref/theme-factory/themes/forest-canopy.md +19 -0
- package/skills_ref/theme-factory/themes/golden-hour.md +19 -0
- package/skills_ref/theme-factory/themes/midnight-galaxy.md +19 -0
- package/skills_ref/theme-factory/themes/modern-minimalist.md +19 -0
- package/skills_ref/theme-factory/themes/ocean-depths.md +19 -0
- package/skills_ref/theme-factory/themes/sunset-boulevard.md +19 -0
- package/skills_ref/theme-factory/themes/tech-innovation.md +19 -0
- package/skills_ref/things-mac/SKILL.md +86 -0
- package/skills_ref/tmux/SKILL.md +153 -0
- package/skills_ref/transcribe/SKILL.md +81 -0
- package/skills_ref/trello/SKILL.md +95 -0
- package/skills_ref/tts/SKILL.md +99 -0
- package/skills_ref/vercel-deploy/SKILL.md +115 -0
- package/skills_ref/video-downloader/SKILL.md +99 -0
- package/skills_ref/video-downloader/scripts/download_video.py +145 -0
- package/skills_ref/video-frames/SKILL.md +46 -0
- package/skills_ref/vision-click/SKILL.md +128 -0
- package/skills_ref/weather/SKILL.md +112 -0
- package/skills_ref/web-artifacts-builder/LICENSE.txt +202 -0
- package/skills_ref/web-artifacts-builder/SKILL.md +74 -0
- package/skills_ref/web-artifacts-builder/scripts/bundle-artifact.sh +54 -0
- package/skills_ref/web-artifacts-builder/scripts/init-artifact.sh +322 -0
- package/skills_ref/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
- package/skills_ref/web-perf/SKILL.md +193 -0
- package/skills_ref/web-routing/SKILL.md +26 -0
- package/skills_ref/whatsapp/SKILL.md +255 -0
- package/skills_ref/whatsapp/assets/agent-app-integration-example.json +35 -0
- package/skills_ref/whatsapp/assets/databases-example.json +11 -0
- package/skills_ref/whatsapp/assets/function-decide-route-interactive-buttons.json +6 -0
- package/skills_ref/whatsapp/assets/functions-example.json +5 -0
- package/skills_ref/whatsapp/assets/workflow-agent-simple.json +31 -0
- package/skills_ref/whatsapp/assets/workflow-api-template-wait-agent.json +59 -0
- package/skills_ref/whatsapp/assets/workflow-customer-support-intake-agent.json +56 -0
- package/skills_ref/whatsapp/assets/workflow-decision.json +83 -0
- package/skills_ref/whatsapp/assets/workflow-interactive-buttons-decide-ai.json +89 -0
- package/skills_ref/whatsapp/assets/workflow-interactive-buttons-decide-function.json +88 -0
- package/skills_ref/whatsapp/assets/workflow-linear.json +53 -0
- package/skills_ref/whatsapp/package.json +10 -0
- package/skills_ref/whatsapp/references/app-integrations.md +89 -0
- package/skills_ref/whatsapp/references/databases-reference.md +21 -0
- package/skills_ref/whatsapp/references/execution-context.md +42 -0
- package/skills_ref/whatsapp/references/function-contracts.md +55 -0
- package/skills_ref/whatsapp/references/functions-payloads.md +87 -0
- package/skills_ref/whatsapp/references/functions-reference.md +133 -0
- package/skills_ref/whatsapp/references/graph-contract.md +145 -0
- package/skills_ref/whatsapp/references/node-types.md +430 -0
- package/skills_ref/whatsapp/references/triggers.md +20 -0
- package/skills_ref/whatsapp/references/workflow-overview.md +22 -0
- package/skills_ref/whatsapp/references/workflow-reference.md +123 -0
- package/skills_ref/whatsapp/scripts/configure-prop.js +113 -0
- package/skills_ref/whatsapp/scripts/create-connect-token.js +38 -0
- package/skills_ref/whatsapp/scripts/create-function.js +64 -0
- package/skills_ref/whatsapp/scripts/create-integration.js +137 -0
- package/skills_ref/whatsapp/scripts/create-row.js +47 -0
- package/skills_ref/whatsapp/scripts/create-trigger.js +88 -0
- package/skills_ref/whatsapp/scripts/create-workflow.js +85 -0
- package/skills_ref/whatsapp/scripts/delete-integration.js +44 -0
- package/skills_ref/whatsapp/scripts/delete-row.js +49 -0
- package/skills_ref/whatsapp/scripts/delete-trigger.js +44 -0
- package/skills_ref/whatsapp/scripts/deploy-function.js +47 -0
- package/skills_ref/whatsapp/scripts/edit-graph.js +289 -0
- package/skills_ref/whatsapp/scripts/get-action-schema.js +44 -0
- package/skills_ref/whatsapp/scripts/get-context-value.js +80 -0
- package/skills_ref/whatsapp/scripts/get-execution-event.js +55 -0
- package/skills_ref/whatsapp/scripts/get-execution.js +44 -0
- package/skills_ref/whatsapp/scripts/get-function.js +43 -0
- package/skills_ref/whatsapp/scripts/get-graph.js +85 -0
- package/skills_ref/whatsapp/scripts/get-table.js +45 -0
- package/skills_ref/whatsapp/scripts/get-workflow.js +44 -0
- package/skills_ref/whatsapp/scripts/invoke-function.js +60 -0
- package/skills_ref/whatsapp/scripts/lib/databases/args.js +87 -0
- package/skills_ref/whatsapp/scripts/lib/databases/filters.js +30 -0
- package/skills_ref/whatsapp/scripts/lib/databases/kapso-api.js +70 -0
- package/skills_ref/whatsapp/scripts/lib/functions/args.js +55 -0
- package/skills_ref/whatsapp/scripts/lib/functions/kapso-api.js +70 -0
- package/skills_ref/whatsapp/scripts/lib/workflows/args.js +53 -0
- package/skills_ref/whatsapp/scripts/lib/workflows/kapso-api.js +123 -0
- package/skills_ref/whatsapp/scripts/lib/workflows/result.js +16 -0
- package/skills_ref/whatsapp/scripts/list-accounts.js +62 -0
- package/skills_ref/whatsapp/scripts/list-apps.js +42 -0
- package/skills_ref/whatsapp/scripts/list-execution-events.js +61 -0
- package/skills_ref/whatsapp/scripts/list-executions.js +53 -0
- package/skills_ref/whatsapp/scripts/list-function-invocations.js +53 -0
- package/skills_ref/whatsapp/scripts/list-functions.js +41 -0
- package/skills_ref/whatsapp/scripts/list-integrations.js +41 -0
- package/skills_ref/whatsapp/scripts/list-provider-models.js +48 -0
- package/skills_ref/whatsapp/scripts/list-tables.js +41 -0
- package/skills_ref/whatsapp/scripts/list-triggers.js +44 -0
- package/skills_ref/whatsapp/scripts/list-whatsapp-phone-numbers.js +56 -0
- package/skills_ref/whatsapp/scripts/list-workflows.js +44 -0
- package/skills_ref/whatsapp/scripts/openapi-explore.mjs +1273 -0
- package/skills_ref/whatsapp/scripts/query-rows.js +71 -0
- package/skills_ref/whatsapp/scripts/reload-props.js +110 -0
- package/skills_ref/whatsapp/scripts/resume-execution.js +75 -0
- package/skills_ref/whatsapp/scripts/search-actions.js +64 -0
- package/skills_ref/whatsapp/scripts/update-execution-status.js +51 -0
- package/skills_ref/whatsapp/scripts/update-function.js +65 -0
- package/skills_ref/whatsapp/scripts/update-graph.js +154 -0
- package/skills_ref/whatsapp/scripts/update-integration.js +82 -0
- package/skills_ref/whatsapp/scripts/update-row.js +51 -0
- package/skills_ref/whatsapp/scripts/update-trigger.js +60 -0
- package/skills_ref/whatsapp/scripts/update-workflow-settings.js +67 -0
- package/skills_ref/whatsapp/scripts/upsert-row.js +64 -0
- package/skills_ref/whatsapp/scripts/validate-graph.js +293 -0
- package/skills_ref/whatsapp/scripts/variables-delete.js +37 -0
- package/skills_ref/whatsapp/scripts/variables-list.js +55 -0
- package/skills_ref/whatsapp/scripts/variables-set.js +39 -0
- package/skills_ref/writing-plans/SKILL.md +116 -0
- package/skills_ref/xlsx/LICENSE.txt +30 -0
- package/skills_ref/xlsx/SKILL.md +292 -0
- package/skills_ref/xlsx/scripts/office/helpers/__init__.py +0 -0
- package/skills_ref/xlsx/scripts/office/helpers/merge_runs.py +199 -0
- package/skills_ref/xlsx/scripts/office/helpers/simplify_redlines.py +197 -0
- package/skills_ref/xlsx/scripts/office/pack.py +159 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/skills_ref/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/skills_ref/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/skills_ref/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/skills_ref/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/skills_ref/xlsx/scripts/office/schemas/mce/mc.xsd +75 -0
- package/skills_ref/xlsx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
- package/skills_ref/xlsx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
- package/skills_ref/xlsx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
- package/skills_ref/xlsx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/skills_ref/xlsx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/skills_ref/xlsx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/skills_ref/xlsx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/skills_ref/xlsx/scripts/office/soffice.py +183 -0
- package/skills_ref/xlsx/scripts/office/unpack.py +132 -0
- package/skills_ref/xlsx/scripts/office/validate.py +111 -0
- package/skills_ref/xlsx/scripts/office/validators/__init__.py +15 -0
- package/skills_ref/xlsx/scripts/office/validators/base.py +847 -0
- package/skills_ref/xlsx/scripts/office/validators/docx.py +446 -0
- package/skills_ref/xlsx/scripts/office/validators/pptx.py +275 -0
- package/skills_ref/xlsx/scripts/office/validators/redlining.py +247 -0
- package/skills_ref/xlsx/scripts/recalc.py +184 -0
- package/skills_ref/xurl/SKILL.md +461 -0
|
@@ -0,0 +1,1374 @@
|
|
|
1
|
+
# /// script
|
|
2
|
+
# requires-python = ">=3.13"
|
|
3
|
+
# dependencies = [
|
|
4
|
+
# "huggingface-hub>=1.1.4",
|
|
5
|
+
# "markdown-it-py>=3.0.0",
|
|
6
|
+
# "python-dotenv>=1.2.1",
|
|
7
|
+
# "pyyaml>=6.0.3",
|
|
8
|
+
# "requests>=2.32.5",
|
|
9
|
+
# ]
|
|
10
|
+
# ///
|
|
11
|
+
|
|
12
|
+
"""
|
|
13
|
+
Manage evaluation results in Hugging Face model cards.
|
|
14
|
+
|
|
15
|
+
This script provides two methods:
|
|
16
|
+
1. Extract evaluation tables from model README files
|
|
17
|
+
2. Import evaluation scores from Artificial Analysis API
|
|
18
|
+
|
|
19
|
+
Both methods update the model-index metadata in model cards.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
import argparse
|
|
23
|
+
import os
|
|
24
|
+
import re
|
|
25
|
+
from textwrap import dedent
|
|
26
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def load_env() -> None:
|
|
30
|
+
"""Load .env if python-dotenv is available; keep help usable without it."""
|
|
31
|
+
try:
|
|
32
|
+
import dotenv # type: ignore
|
|
33
|
+
except ModuleNotFoundError:
|
|
34
|
+
return
|
|
35
|
+
dotenv.load_dotenv()
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def require_markdown_it():
|
|
39
|
+
try:
|
|
40
|
+
from markdown_it import MarkdownIt # type: ignore
|
|
41
|
+
except ModuleNotFoundError as exc:
|
|
42
|
+
raise ModuleNotFoundError(
|
|
43
|
+
"markdown-it-py is required for table parsing. "
|
|
44
|
+
"Install with `uv add markdown-it-py` or `pip install markdown-it-py`."
|
|
45
|
+
) from exc
|
|
46
|
+
return MarkdownIt
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def require_model_card():
|
|
50
|
+
try:
|
|
51
|
+
from huggingface_hub import ModelCard # type: ignore
|
|
52
|
+
except ModuleNotFoundError as exc:
|
|
53
|
+
raise ModuleNotFoundError(
|
|
54
|
+
"huggingface-hub is required for model card operations. "
|
|
55
|
+
"Install with `uv add huggingface_hub` or `pip install huggingface-hub`."
|
|
56
|
+
) from exc
|
|
57
|
+
return ModelCard
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def require_requests():
|
|
61
|
+
try:
|
|
62
|
+
import requests # type: ignore
|
|
63
|
+
except ModuleNotFoundError as exc:
|
|
64
|
+
raise ModuleNotFoundError(
|
|
65
|
+
"requests is required for Artificial Analysis import. "
|
|
66
|
+
"Install with `uv add requests` or `pip install requests`."
|
|
67
|
+
) from exc
|
|
68
|
+
return requests
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def require_yaml():
|
|
72
|
+
try:
|
|
73
|
+
import yaml # type: ignore
|
|
74
|
+
except ModuleNotFoundError as exc:
|
|
75
|
+
raise ModuleNotFoundError(
|
|
76
|
+
"PyYAML is required for YAML output. "
|
|
77
|
+
"Install with `uv add pyyaml` or `pip install pyyaml`."
|
|
78
|
+
) from exc
|
|
79
|
+
return yaml
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
# ============================================================================
|
|
83
|
+
# Method 1: Extract Evaluations from README
|
|
84
|
+
# ============================================================================
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def extract_tables_from_markdown(markdown_content: str) -> List[str]:
|
|
88
|
+
"""Extract all markdown tables from content."""
|
|
89
|
+
# Pattern to match markdown tables
|
|
90
|
+
table_pattern = r"(\|[^\n]+\|(?:\r?\n\|[^\n]+\|)+)"
|
|
91
|
+
tables = re.findall(table_pattern, markdown_content)
|
|
92
|
+
return tables
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def parse_markdown_table(table_str: str) -> Tuple[List[str], List[List[str]]]:
|
|
96
|
+
"""
|
|
97
|
+
Parse a markdown table string into headers and rows.
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
Tuple of (headers, data_rows)
|
|
101
|
+
"""
|
|
102
|
+
lines = [line.strip() for line in table_str.strip().split("\n")]
|
|
103
|
+
|
|
104
|
+
# Remove separator line (the one with dashes)
|
|
105
|
+
lines = [line for line in lines if not re.match(r"^\|[\s\-:]+\|$", line)]
|
|
106
|
+
|
|
107
|
+
if len(lines) < 2:
|
|
108
|
+
return [], []
|
|
109
|
+
|
|
110
|
+
# Parse header
|
|
111
|
+
header = [cell.strip() for cell in lines[0].split("|")[1:-1]]
|
|
112
|
+
|
|
113
|
+
# Parse data rows
|
|
114
|
+
data_rows = []
|
|
115
|
+
for line in lines[1:]:
|
|
116
|
+
cells = [cell.strip() for cell in line.split("|")[1:-1]]
|
|
117
|
+
if cells:
|
|
118
|
+
data_rows.append(cells)
|
|
119
|
+
|
|
120
|
+
return header, data_rows
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def is_evaluation_table(header: List[str], rows: List[List[str]]) -> bool:
|
|
124
|
+
"""Determine if a table contains evaluation results."""
|
|
125
|
+
if not header or not rows:
|
|
126
|
+
return False
|
|
127
|
+
|
|
128
|
+
# Check if first column looks like benchmark names
|
|
129
|
+
benchmark_keywords = [
|
|
130
|
+
"benchmark", "task", "dataset", "eval", "test", "metric",
|
|
131
|
+
"mmlu", "humaneval", "gsm", "hellaswag", "arc", "winogrande",
|
|
132
|
+
"truthfulqa", "boolq", "piqa", "siqa"
|
|
133
|
+
]
|
|
134
|
+
|
|
135
|
+
first_col = header[0].lower()
|
|
136
|
+
has_benchmark_header = any(keyword in first_col for keyword in benchmark_keywords)
|
|
137
|
+
|
|
138
|
+
# Check if there are numeric values in the table
|
|
139
|
+
has_numeric_values = False
|
|
140
|
+
for row in rows:
|
|
141
|
+
for cell in row:
|
|
142
|
+
try:
|
|
143
|
+
float(cell.replace("%", "").replace(",", ""))
|
|
144
|
+
has_numeric_values = True
|
|
145
|
+
break
|
|
146
|
+
except ValueError:
|
|
147
|
+
continue
|
|
148
|
+
if has_numeric_values:
|
|
149
|
+
break
|
|
150
|
+
|
|
151
|
+
return has_benchmark_header or has_numeric_values
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def normalize_model_name(name: str) -> tuple[set[str], str]:
|
|
155
|
+
"""
|
|
156
|
+
Normalize a model name for matching.
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
name: Model name to normalize
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
Tuple of (token_set, normalized_string)
|
|
163
|
+
"""
|
|
164
|
+
# Remove markdown formatting
|
|
165
|
+
cleaned = re.sub(r'\[([^\]]+)\]\([^\)]+\)', r'\1', name) # Remove markdown links
|
|
166
|
+
cleaned = re.sub(r'\*\*([^\*]+)\*\*', r'\1', cleaned) # Remove bold
|
|
167
|
+
cleaned = cleaned.strip()
|
|
168
|
+
|
|
169
|
+
# Normalize and tokenize
|
|
170
|
+
normalized = cleaned.lower().replace("-", " ").replace("_", " ")
|
|
171
|
+
tokens = set(normalized.split())
|
|
172
|
+
|
|
173
|
+
return tokens, normalized
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def find_main_model_column(header: List[str], model_name: str) -> Optional[int]:
|
|
177
|
+
"""
|
|
178
|
+
Identify the column index that corresponds to the main model.
|
|
179
|
+
|
|
180
|
+
Only returns a column if there's an exact normalized match with the model name.
|
|
181
|
+
This prevents extracting scores from training checkpoints or similar models.
|
|
182
|
+
|
|
183
|
+
Args:
|
|
184
|
+
header: Table column headers
|
|
185
|
+
model_name: Model name from repo_id (e.g., "OLMo-3-32B-Think")
|
|
186
|
+
|
|
187
|
+
Returns:
|
|
188
|
+
Column index of the main model, or None if no exact match found
|
|
189
|
+
"""
|
|
190
|
+
if not header or not model_name:
|
|
191
|
+
return None
|
|
192
|
+
|
|
193
|
+
# Normalize model name and extract tokens
|
|
194
|
+
model_tokens, _ = normalize_model_name(model_name)
|
|
195
|
+
|
|
196
|
+
# Find exact matches only
|
|
197
|
+
for i, col_name in enumerate(header):
|
|
198
|
+
if not col_name:
|
|
199
|
+
continue
|
|
200
|
+
|
|
201
|
+
# Skip first column (benchmark names)
|
|
202
|
+
if i == 0:
|
|
203
|
+
continue
|
|
204
|
+
|
|
205
|
+
col_tokens, _ = normalize_model_name(col_name)
|
|
206
|
+
|
|
207
|
+
# Check for exact token match
|
|
208
|
+
if model_tokens == col_tokens:
|
|
209
|
+
return i
|
|
210
|
+
|
|
211
|
+
# No exact match found
|
|
212
|
+
return None
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def find_main_model_row(
|
|
216
|
+
rows: List[List[str]], model_name: str
|
|
217
|
+
) -> tuple[Optional[int], List[str]]:
|
|
218
|
+
"""
|
|
219
|
+
Identify the row index that corresponds to the main model in a transposed table.
|
|
220
|
+
|
|
221
|
+
In transposed tables, each row represents a different model, with the first
|
|
222
|
+
column containing the model name.
|
|
223
|
+
|
|
224
|
+
Args:
|
|
225
|
+
rows: Table data rows
|
|
226
|
+
model_name: Model name from repo_id (e.g., "OLMo-3-32B")
|
|
227
|
+
|
|
228
|
+
Returns:
|
|
229
|
+
Tuple of (row_index, available_models)
|
|
230
|
+
- row_index: Index of the main model, or None if no exact match found
|
|
231
|
+
- available_models: List of all model names found in the table
|
|
232
|
+
"""
|
|
233
|
+
if not rows or not model_name:
|
|
234
|
+
return None, []
|
|
235
|
+
|
|
236
|
+
model_tokens, _ = normalize_model_name(model_name)
|
|
237
|
+
available_models = []
|
|
238
|
+
|
|
239
|
+
for i, row in enumerate(rows):
|
|
240
|
+
if not row or not row[0]:
|
|
241
|
+
continue
|
|
242
|
+
|
|
243
|
+
row_name = row[0].strip()
|
|
244
|
+
|
|
245
|
+
# Skip separator/header rows
|
|
246
|
+
if not row_name or row_name.startswith('---'):
|
|
247
|
+
continue
|
|
248
|
+
|
|
249
|
+
row_tokens, _ = normalize_model_name(row_name)
|
|
250
|
+
|
|
251
|
+
# Collect all non-empty model names
|
|
252
|
+
if row_tokens:
|
|
253
|
+
available_models.append(row_name)
|
|
254
|
+
|
|
255
|
+
# Check for exact token match
|
|
256
|
+
if model_tokens == row_tokens:
|
|
257
|
+
return i, available_models
|
|
258
|
+
|
|
259
|
+
return None, available_models
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def is_transposed_table(header: List[str], rows: List[List[str]]) -> bool:
|
|
263
|
+
"""
|
|
264
|
+
Determine if a table is transposed (models as rows, benchmarks as columns).
|
|
265
|
+
|
|
266
|
+
A table is considered transposed if:
|
|
267
|
+
- The first column contains model-like names (not benchmark names)
|
|
268
|
+
- Most other columns contain numeric values
|
|
269
|
+
- Header row contains benchmark-like names
|
|
270
|
+
|
|
271
|
+
Args:
|
|
272
|
+
header: Table column headers
|
|
273
|
+
rows: Table data rows
|
|
274
|
+
|
|
275
|
+
Returns:
|
|
276
|
+
True if table appears to be transposed, False otherwise
|
|
277
|
+
"""
|
|
278
|
+
if not header or not rows or len(header) < 3:
|
|
279
|
+
return False
|
|
280
|
+
|
|
281
|
+
# Check if first column header suggests model names
|
|
282
|
+
first_col = header[0].lower()
|
|
283
|
+
model_indicators = ["model", "system", "llm", "name"]
|
|
284
|
+
has_model_header = any(indicator in first_col for indicator in model_indicators)
|
|
285
|
+
|
|
286
|
+
# Check if remaining headers look like benchmarks
|
|
287
|
+
benchmark_keywords = [
|
|
288
|
+
"mmlu", "humaneval", "gsm", "hellaswag", "arc", "winogrande",
|
|
289
|
+
"eval", "score", "benchmark", "test", "math", "code", "mbpp",
|
|
290
|
+
"truthfulqa", "boolq", "piqa", "siqa", "drop", "squad"
|
|
291
|
+
]
|
|
292
|
+
|
|
293
|
+
benchmark_header_count = 0
|
|
294
|
+
for col_name in header[1:]:
|
|
295
|
+
col_lower = col_name.lower()
|
|
296
|
+
if any(keyword in col_lower for keyword in benchmark_keywords):
|
|
297
|
+
benchmark_header_count += 1
|
|
298
|
+
|
|
299
|
+
has_benchmark_headers = benchmark_header_count >= 2
|
|
300
|
+
|
|
301
|
+
# Check if data rows have numeric values in most columns (except first)
|
|
302
|
+
numeric_count = 0
|
|
303
|
+
total_cells = 0
|
|
304
|
+
|
|
305
|
+
for row in rows[:5]: # Check first 5 rows
|
|
306
|
+
for cell in row[1:]: # Skip first column
|
|
307
|
+
total_cells += 1
|
|
308
|
+
try:
|
|
309
|
+
float(cell.replace("%", "").replace(",", "").strip())
|
|
310
|
+
numeric_count += 1
|
|
311
|
+
except (ValueError, AttributeError):
|
|
312
|
+
continue
|
|
313
|
+
|
|
314
|
+
has_numeric_data = total_cells > 0 and (numeric_count / total_cells) > 0.5
|
|
315
|
+
|
|
316
|
+
return (has_model_header or has_benchmark_headers) and has_numeric_data
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
def extract_metrics_from_table(
|
|
320
|
+
header: List[str],
|
|
321
|
+
rows: List[List[str]],
|
|
322
|
+
table_format: str = "auto",
|
|
323
|
+
model_name: Optional[str] = None,
|
|
324
|
+
model_column_index: Optional[int] = None
|
|
325
|
+
) -> List[Dict[str, Any]]:
|
|
326
|
+
"""
|
|
327
|
+
Extract metrics from parsed table data.
|
|
328
|
+
|
|
329
|
+
Args:
|
|
330
|
+
header: Table column headers
|
|
331
|
+
rows: Table data rows
|
|
332
|
+
table_format: "rows" (benchmarks as rows), "columns" (benchmarks as columns),
|
|
333
|
+
"transposed" (models as rows, benchmarks as columns), or "auto"
|
|
334
|
+
model_name: Optional model name to identify the correct column/row
|
|
335
|
+
|
|
336
|
+
Returns:
|
|
337
|
+
List of metric dictionaries with name, type, and value
|
|
338
|
+
"""
|
|
339
|
+
metrics = []
|
|
340
|
+
|
|
341
|
+
if table_format == "auto":
|
|
342
|
+
# First check if it's a transposed table (models as rows)
|
|
343
|
+
if is_transposed_table(header, rows):
|
|
344
|
+
table_format = "transposed"
|
|
345
|
+
else:
|
|
346
|
+
# Check if first column header is empty/generic (indicates benchmarks in rows)
|
|
347
|
+
first_header = header[0].lower().strip() if header else ""
|
|
348
|
+
is_first_col_benchmarks = not first_header or first_header in ["", "benchmark", "task", "dataset", "metric", "eval"]
|
|
349
|
+
|
|
350
|
+
if is_first_col_benchmarks:
|
|
351
|
+
table_format = "rows"
|
|
352
|
+
else:
|
|
353
|
+
# Heuristic: if first row has mostly numeric values, benchmarks are columns
|
|
354
|
+
try:
|
|
355
|
+
numeric_count = sum(
|
|
356
|
+
1 for cell in rows[0] if cell and
|
|
357
|
+
re.match(r"^\d+\.?\d*%?$", cell.replace(",", "").strip())
|
|
358
|
+
)
|
|
359
|
+
table_format = "columns" if numeric_count > len(rows[0]) / 2 else "rows"
|
|
360
|
+
except (IndexError, ValueError):
|
|
361
|
+
table_format = "rows"
|
|
362
|
+
|
|
363
|
+
if table_format == "rows":
|
|
364
|
+
# Benchmarks are in rows, scores in columns
|
|
365
|
+
# Try to identify the main model column if model_name is provided
|
|
366
|
+
target_column = model_column_index
|
|
367
|
+
if target_column is None and model_name:
|
|
368
|
+
target_column = find_main_model_column(header, model_name)
|
|
369
|
+
|
|
370
|
+
for row in rows:
|
|
371
|
+
if not row:
|
|
372
|
+
continue
|
|
373
|
+
|
|
374
|
+
benchmark_name = row[0].strip()
|
|
375
|
+
if not benchmark_name:
|
|
376
|
+
continue
|
|
377
|
+
|
|
378
|
+
# If we identified a specific column, use it; otherwise use first numeric value
|
|
379
|
+
if target_column is not None and target_column < len(row):
|
|
380
|
+
try:
|
|
381
|
+
value_str = row[target_column].replace("%", "").replace(",", "").strip()
|
|
382
|
+
if value_str:
|
|
383
|
+
value = float(value_str)
|
|
384
|
+
metrics.append({
|
|
385
|
+
"name": benchmark_name,
|
|
386
|
+
"type": benchmark_name.lower().replace(" ", "_"),
|
|
387
|
+
"value": value
|
|
388
|
+
})
|
|
389
|
+
except (ValueError, IndexError):
|
|
390
|
+
pass
|
|
391
|
+
else:
|
|
392
|
+
# Extract numeric values from remaining columns (original behavior)
|
|
393
|
+
for i, cell in enumerate(row[1:], start=1):
|
|
394
|
+
try:
|
|
395
|
+
# Remove common suffixes and convert to float
|
|
396
|
+
value_str = cell.replace("%", "").replace(",", "").strip()
|
|
397
|
+
if not value_str:
|
|
398
|
+
continue
|
|
399
|
+
|
|
400
|
+
value = float(value_str)
|
|
401
|
+
|
|
402
|
+
# Determine metric name
|
|
403
|
+
metric_name = benchmark_name
|
|
404
|
+
if len(header) > i and header[i].lower() not in ["score", "value", "result"]:
|
|
405
|
+
metric_name = f"{benchmark_name} ({header[i]})"
|
|
406
|
+
|
|
407
|
+
metrics.append({
|
|
408
|
+
"name": metric_name,
|
|
409
|
+
"type": benchmark_name.lower().replace(" ", "_"),
|
|
410
|
+
"value": value
|
|
411
|
+
})
|
|
412
|
+
break # Only take first numeric value per row
|
|
413
|
+
except (ValueError, IndexError):
|
|
414
|
+
continue
|
|
415
|
+
|
|
416
|
+
elif table_format == "transposed":
|
|
417
|
+
# Models are in rows (first column), benchmarks are in columns (header)
|
|
418
|
+
# Find the row that matches the target model
|
|
419
|
+
if not model_name:
|
|
420
|
+
print("Warning: model_name required for transposed table format")
|
|
421
|
+
return metrics
|
|
422
|
+
|
|
423
|
+
target_row_idx, available_models = find_main_model_row(rows, model_name)
|
|
424
|
+
|
|
425
|
+
if target_row_idx is None:
|
|
426
|
+
print(f"\n⚠ Could not find model '{model_name}' in transposed table")
|
|
427
|
+
if available_models:
|
|
428
|
+
print("\nAvailable models in table:")
|
|
429
|
+
for i, model in enumerate(available_models, 1):
|
|
430
|
+
print(f" {i}. {model}")
|
|
431
|
+
print("\nPlease select the correct model name from the list above.")
|
|
432
|
+
print("You can specify it using the --model-name-override flag:")
|
|
433
|
+
print(f' --model-name-override "{available_models[0]}"')
|
|
434
|
+
return metrics
|
|
435
|
+
|
|
436
|
+
target_row = rows[target_row_idx]
|
|
437
|
+
|
|
438
|
+
# Extract metrics from each column (skip first column which is model name)
|
|
439
|
+
for i in range(1, len(header)):
|
|
440
|
+
benchmark_name = header[i].strip()
|
|
441
|
+
if not benchmark_name or i >= len(target_row):
|
|
442
|
+
continue
|
|
443
|
+
|
|
444
|
+
try:
|
|
445
|
+
value_str = target_row[i].replace("%", "").replace(",", "").strip()
|
|
446
|
+
if not value_str:
|
|
447
|
+
continue
|
|
448
|
+
|
|
449
|
+
value = float(value_str)
|
|
450
|
+
|
|
451
|
+
metrics.append({
|
|
452
|
+
"name": benchmark_name,
|
|
453
|
+
"type": benchmark_name.lower().replace(" ", "_").replace("-", "_"),
|
|
454
|
+
"value": value
|
|
455
|
+
})
|
|
456
|
+
except (ValueError, AttributeError):
|
|
457
|
+
continue
|
|
458
|
+
|
|
459
|
+
else: # table_format == "columns"
|
|
460
|
+
# Benchmarks are in columns
|
|
461
|
+
if not rows:
|
|
462
|
+
return metrics
|
|
463
|
+
|
|
464
|
+
# Use first data row for values
|
|
465
|
+
data_row = rows[0]
|
|
466
|
+
|
|
467
|
+
for i, benchmark_name in enumerate(header):
|
|
468
|
+
if not benchmark_name or i >= len(data_row):
|
|
469
|
+
continue
|
|
470
|
+
|
|
471
|
+
try:
|
|
472
|
+
value_str = data_row[i].replace("%", "").replace(",", "").strip()
|
|
473
|
+
if not value_str:
|
|
474
|
+
continue
|
|
475
|
+
|
|
476
|
+
value = float(value_str)
|
|
477
|
+
|
|
478
|
+
metrics.append({
|
|
479
|
+
"name": benchmark_name,
|
|
480
|
+
"type": benchmark_name.lower().replace(" ", "_"),
|
|
481
|
+
"value": value
|
|
482
|
+
})
|
|
483
|
+
except ValueError:
|
|
484
|
+
continue
|
|
485
|
+
|
|
486
|
+
return metrics
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
def extract_evaluations_from_readme(
|
|
490
|
+
repo_id: str,
|
|
491
|
+
task_type: str = "text-generation",
|
|
492
|
+
dataset_name: str = "Benchmarks",
|
|
493
|
+
dataset_type: str = "benchmark",
|
|
494
|
+
model_name_override: Optional[str] = None,
|
|
495
|
+
table_index: Optional[int] = None,
|
|
496
|
+
model_column_index: Optional[int] = None
|
|
497
|
+
) -> Optional[List[Dict[str, Any]]]:
|
|
498
|
+
"""
|
|
499
|
+
Extract evaluation results from a model's README.
|
|
500
|
+
|
|
501
|
+
Args:
|
|
502
|
+
repo_id: Hugging Face model repository ID
|
|
503
|
+
task_type: Task type for model-index (e.g., "text-generation")
|
|
504
|
+
dataset_name: Name for the benchmark dataset
|
|
505
|
+
dataset_type: Type identifier for the dataset
|
|
506
|
+
model_name_override: Override model name for matching (column header for comparison tables)
|
|
507
|
+
table_index: 1-indexed table number from inspect-tables output
|
|
508
|
+
|
|
509
|
+
Returns:
|
|
510
|
+
Model-index formatted results or None if no evaluations found
|
|
511
|
+
"""
|
|
512
|
+
try:
|
|
513
|
+
load_env()
|
|
514
|
+
ModelCard = require_model_card()
|
|
515
|
+
hf_token = os.getenv("HF_TOKEN")
|
|
516
|
+
card = ModelCard.load(repo_id, token=hf_token)
|
|
517
|
+
readme_content = card.content
|
|
518
|
+
|
|
519
|
+
if not readme_content:
|
|
520
|
+
print(f"No README content found for {repo_id}")
|
|
521
|
+
return None
|
|
522
|
+
|
|
523
|
+
# Extract model name from repo_id or use override
|
|
524
|
+
if model_name_override:
|
|
525
|
+
model_name = model_name_override
|
|
526
|
+
print(f"Using model name override: '{model_name}'")
|
|
527
|
+
else:
|
|
528
|
+
model_name = repo_id.split("/")[-1] if "/" in repo_id else repo_id
|
|
529
|
+
|
|
530
|
+
# Use markdown-it parser for accurate table extraction
|
|
531
|
+
all_tables = extract_tables_with_parser(readme_content)
|
|
532
|
+
|
|
533
|
+
if not all_tables:
|
|
534
|
+
print(f"No tables found in README for {repo_id}")
|
|
535
|
+
return None
|
|
536
|
+
|
|
537
|
+
# If table_index specified, use that specific table
|
|
538
|
+
if table_index is not None:
|
|
539
|
+
if table_index < 1 or table_index > len(all_tables):
|
|
540
|
+
print(f"Invalid table index {table_index}. Found {len(all_tables)} tables.")
|
|
541
|
+
print("Run inspect-tables to see available tables.")
|
|
542
|
+
return None
|
|
543
|
+
tables_to_process = [all_tables[table_index - 1]]
|
|
544
|
+
else:
|
|
545
|
+
# Filter to evaluation tables only
|
|
546
|
+
eval_tables = []
|
|
547
|
+
for table in all_tables:
|
|
548
|
+
header = table.get("headers", [])
|
|
549
|
+
rows = table.get("rows", [])
|
|
550
|
+
if is_evaluation_table(header, rows):
|
|
551
|
+
eval_tables.append(table)
|
|
552
|
+
|
|
553
|
+
if len(eval_tables) > 1:
|
|
554
|
+
print(f"\n⚠ Found {len(eval_tables)} evaluation tables.")
|
|
555
|
+
print("Run inspect-tables first, then use --table to select one:")
|
|
556
|
+
print(f' uv run scripts/evaluation_manager.py inspect-tables --repo-id "{repo_id}"')
|
|
557
|
+
return None
|
|
558
|
+
elif len(eval_tables) == 0:
|
|
559
|
+
print(f"No evaluation tables found in README for {repo_id}")
|
|
560
|
+
return None
|
|
561
|
+
|
|
562
|
+
tables_to_process = eval_tables
|
|
563
|
+
|
|
564
|
+
# Extract metrics from selected table(s)
|
|
565
|
+
all_metrics = []
|
|
566
|
+
for table in tables_to_process:
|
|
567
|
+
header = table.get("headers", [])
|
|
568
|
+
rows = table.get("rows", [])
|
|
569
|
+
metrics = extract_metrics_from_table(
|
|
570
|
+
header,
|
|
571
|
+
rows,
|
|
572
|
+
model_name=model_name,
|
|
573
|
+
model_column_index=model_column_index
|
|
574
|
+
)
|
|
575
|
+
all_metrics.extend(metrics)
|
|
576
|
+
|
|
577
|
+
if not all_metrics:
|
|
578
|
+
print(f"No metrics extracted from table")
|
|
579
|
+
return None
|
|
580
|
+
|
|
581
|
+
# Build model-index structure
|
|
582
|
+
display_name = repo_id.split("/")[-1] if "/" in repo_id else repo_id
|
|
583
|
+
|
|
584
|
+
results = [{
|
|
585
|
+
"task": {"type": task_type},
|
|
586
|
+
"dataset": {
|
|
587
|
+
"name": dataset_name,
|
|
588
|
+
"type": dataset_type
|
|
589
|
+
},
|
|
590
|
+
"metrics": all_metrics,
|
|
591
|
+
"source": {
|
|
592
|
+
"name": "Model README",
|
|
593
|
+
"url": f"https://huggingface.co/{repo_id}"
|
|
594
|
+
}
|
|
595
|
+
}]
|
|
596
|
+
|
|
597
|
+
return results
|
|
598
|
+
|
|
599
|
+
except Exception as e:
|
|
600
|
+
print(f"Error extracting evaluations from README: {e}")
|
|
601
|
+
return None
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
# ============================================================================
|
|
605
|
+
# Table Inspection (using markdown-it-py for accurate parsing)
|
|
606
|
+
# ============================================================================
|
|
607
|
+
|
|
608
|
+
|
|
609
|
+
def extract_tables_with_parser(markdown_content: str) -> List[Dict[str, Any]]:
|
|
610
|
+
"""
|
|
611
|
+
Extract tables from markdown using markdown-it-py parser.
|
|
612
|
+
Uses GFM (GitHub Flavored Markdown) which includes table support.
|
|
613
|
+
"""
|
|
614
|
+
MarkdownIt = require_markdown_it()
|
|
615
|
+
# Disable linkify to avoid optional dependency errors; not needed for table parsing.
|
|
616
|
+
md = MarkdownIt("gfm-like", {"linkify": False})
|
|
617
|
+
tokens = md.parse(markdown_content)
|
|
618
|
+
|
|
619
|
+
tables = []
|
|
620
|
+
i = 0
|
|
621
|
+
while i < len(tokens):
|
|
622
|
+
token = tokens[i]
|
|
623
|
+
|
|
624
|
+
if token.type == "table_open":
|
|
625
|
+
table_data = {"headers": [], "rows": []}
|
|
626
|
+
current_row = []
|
|
627
|
+
in_header = False
|
|
628
|
+
|
|
629
|
+
i += 1
|
|
630
|
+
while i < len(tokens) and tokens[i].type != "table_close":
|
|
631
|
+
t = tokens[i]
|
|
632
|
+
if t.type == "thead_open":
|
|
633
|
+
in_header = True
|
|
634
|
+
elif t.type == "thead_close":
|
|
635
|
+
in_header = False
|
|
636
|
+
elif t.type == "tr_open":
|
|
637
|
+
current_row = []
|
|
638
|
+
elif t.type == "tr_close":
|
|
639
|
+
if in_header:
|
|
640
|
+
table_data["headers"] = current_row
|
|
641
|
+
else:
|
|
642
|
+
table_data["rows"].append(current_row)
|
|
643
|
+
current_row = []
|
|
644
|
+
elif t.type == "inline":
|
|
645
|
+
current_row.append(t.content.strip())
|
|
646
|
+
i += 1
|
|
647
|
+
|
|
648
|
+
if table_data["headers"] or table_data["rows"]:
|
|
649
|
+
tables.append(table_data)
|
|
650
|
+
|
|
651
|
+
i += 1
|
|
652
|
+
|
|
653
|
+
return tables
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
def detect_table_format(table: Dict[str, Any], repo_id: str) -> Dict[str, Any]:
|
|
657
|
+
"""Analyze a table to detect its format and identify model columns."""
|
|
658
|
+
headers = table.get("headers", [])
|
|
659
|
+
rows = table.get("rows", [])
|
|
660
|
+
|
|
661
|
+
if not headers or not rows:
|
|
662
|
+
return {"format": "unknown", "columns": headers, "model_columns": [], "row_count": 0, "sample_rows": []}
|
|
663
|
+
|
|
664
|
+
first_header = headers[0].lower() if headers else ""
|
|
665
|
+
is_first_col_benchmarks = not first_header or first_header in ["", "benchmark", "task", "dataset", "metric", "eval"]
|
|
666
|
+
|
|
667
|
+
# Check for numeric columns
|
|
668
|
+
numeric_columns = []
|
|
669
|
+
for col_idx in range(1, len(headers)):
|
|
670
|
+
numeric_count = 0
|
|
671
|
+
for row in rows[:5]:
|
|
672
|
+
if col_idx < len(row):
|
|
673
|
+
try:
|
|
674
|
+
val = re.sub(r'\s*\([^)]*\)', '', row[col_idx])
|
|
675
|
+
float(val.replace("%", "").replace(",", "").strip())
|
|
676
|
+
numeric_count += 1
|
|
677
|
+
except (ValueError, AttributeError):
|
|
678
|
+
pass
|
|
679
|
+
if numeric_count > len(rows[:5]) / 2:
|
|
680
|
+
numeric_columns.append(col_idx)
|
|
681
|
+
|
|
682
|
+
# Determine format
|
|
683
|
+
if is_first_col_benchmarks and len(numeric_columns) > 1:
|
|
684
|
+
format_type = "comparison"
|
|
685
|
+
elif is_first_col_benchmarks and len(numeric_columns) == 1:
|
|
686
|
+
format_type = "simple"
|
|
687
|
+
elif len(numeric_columns) > len(headers) / 2:
|
|
688
|
+
format_type = "transposed"
|
|
689
|
+
else:
|
|
690
|
+
format_type = "unknown"
|
|
691
|
+
|
|
692
|
+
# Find model columns
|
|
693
|
+
model_columns = []
|
|
694
|
+
model_name = repo_id.split("/")[-1] if "/" in repo_id else repo_id
|
|
695
|
+
model_tokens, _ = normalize_model_name(model_name)
|
|
696
|
+
|
|
697
|
+
for idx, header in enumerate(headers):
|
|
698
|
+
if idx == 0 and is_first_col_benchmarks:
|
|
699
|
+
continue
|
|
700
|
+
if header:
|
|
701
|
+
header_tokens, _ = normalize_model_name(header)
|
|
702
|
+
is_match = model_tokens == header_tokens
|
|
703
|
+
is_partial = model_tokens.issubset(header_tokens) or header_tokens.issubset(model_tokens)
|
|
704
|
+
model_columns.append({
|
|
705
|
+
"index": idx,
|
|
706
|
+
"header": header,
|
|
707
|
+
"is_exact_match": is_match,
|
|
708
|
+
"is_partial_match": is_partial and not is_match
|
|
709
|
+
})
|
|
710
|
+
|
|
711
|
+
return {
|
|
712
|
+
"format": format_type,
|
|
713
|
+
"columns": headers,
|
|
714
|
+
"model_columns": model_columns,
|
|
715
|
+
"row_count": len(rows),
|
|
716
|
+
"sample_rows": [row[0] for row in rows[:5] if row]
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
|
|
720
|
+
def inspect_tables(repo_id: str) -> None:
|
|
721
|
+
"""Inspect and display all evaluation tables in a model's README."""
|
|
722
|
+
try:
|
|
723
|
+
load_env()
|
|
724
|
+
ModelCard = require_model_card()
|
|
725
|
+
hf_token = os.getenv("HF_TOKEN")
|
|
726
|
+
card = ModelCard.load(repo_id, token=hf_token)
|
|
727
|
+
readme_content = card.content
|
|
728
|
+
|
|
729
|
+
if not readme_content:
|
|
730
|
+
print(f"No README content found for {repo_id}")
|
|
731
|
+
return
|
|
732
|
+
|
|
733
|
+
tables = extract_tables_with_parser(readme_content)
|
|
734
|
+
|
|
735
|
+
if not tables:
|
|
736
|
+
print(f"No tables found in README for {repo_id}")
|
|
737
|
+
return
|
|
738
|
+
|
|
739
|
+
print(f"\n{'='*70}")
|
|
740
|
+
print(f"Tables found in README for: {repo_id}")
|
|
741
|
+
print(f"{'='*70}")
|
|
742
|
+
|
|
743
|
+
eval_table_count = 0
|
|
744
|
+
for table in tables:
|
|
745
|
+
analysis = detect_table_format(table, repo_id)
|
|
746
|
+
|
|
747
|
+
if analysis["format"] == "unknown" and not analysis.get("sample_rows"):
|
|
748
|
+
continue
|
|
749
|
+
|
|
750
|
+
eval_table_count += 1
|
|
751
|
+
print(f"\n## Table {eval_table_count}")
|
|
752
|
+
print(f" Format: {analysis['format']}")
|
|
753
|
+
print(f" Rows: {analysis['row_count']}")
|
|
754
|
+
|
|
755
|
+
print(f"\n Columns ({len(analysis['columns'])}):")
|
|
756
|
+
for col_info in analysis.get("model_columns", []):
|
|
757
|
+
idx = col_info["index"]
|
|
758
|
+
header = col_info["header"]
|
|
759
|
+
if col_info["is_exact_match"]:
|
|
760
|
+
print(f" [{idx}] {header} ✓ EXACT MATCH")
|
|
761
|
+
elif col_info["is_partial_match"]:
|
|
762
|
+
print(f" [{idx}] {header} ~ partial match")
|
|
763
|
+
else:
|
|
764
|
+
print(f" [{idx}] {header}")
|
|
765
|
+
|
|
766
|
+
if analysis.get("sample_rows"):
|
|
767
|
+
print(f"\n Sample rows (first column):")
|
|
768
|
+
for row_val in analysis["sample_rows"][:5]:
|
|
769
|
+
print(f" - {row_val}")
|
|
770
|
+
|
|
771
|
+
if eval_table_count == 0:
|
|
772
|
+
print("\nNo evaluation tables detected.")
|
|
773
|
+
else:
|
|
774
|
+
print("\nSuggested next step:")
|
|
775
|
+
print(f' uv run scripts/evaluation_manager.py extract-readme --repo-id "{repo_id}" --table <table-number> [--model-column-index <column-index>]')
|
|
776
|
+
|
|
777
|
+
print(f"\n{'='*70}\n")
|
|
778
|
+
|
|
779
|
+
except Exception as e:
|
|
780
|
+
print(f"Error inspecting tables: {e}")
|
|
781
|
+
|
|
782
|
+
|
|
783
|
+
# ============================================================================
|
|
784
|
+
# Pull Request Management
|
|
785
|
+
# ============================================================================
|
|
786
|
+
|
|
787
|
+
|
|
788
|
+
def get_open_prs(repo_id: str) -> List[Dict[str, Any]]:
|
|
789
|
+
"""
|
|
790
|
+
Fetch open pull requests for a Hugging Face model repository.
|
|
791
|
+
|
|
792
|
+
Args:
|
|
793
|
+
repo_id: Hugging Face model repository ID (e.g., "allenai/Olmo-3-32B-Think")
|
|
794
|
+
|
|
795
|
+
Returns:
|
|
796
|
+
List of open PR dictionaries with num, title, author, and createdAt
|
|
797
|
+
"""
|
|
798
|
+
requests = require_requests()
|
|
799
|
+
url = f"https://huggingface.co/api/models/{repo_id}/discussions"
|
|
800
|
+
|
|
801
|
+
try:
|
|
802
|
+
response = requests.get(url, timeout=30, allow_redirects=True)
|
|
803
|
+
response.raise_for_status()
|
|
804
|
+
|
|
805
|
+
data = response.json()
|
|
806
|
+
discussions = data.get("discussions", [])
|
|
807
|
+
|
|
808
|
+
open_prs = [
|
|
809
|
+
{
|
|
810
|
+
"num": d["num"],
|
|
811
|
+
"title": d["title"],
|
|
812
|
+
"author": d["author"]["name"],
|
|
813
|
+
"createdAt": d.get("createdAt", "unknown"),
|
|
814
|
+
}
|
|
815
|
+
for d in discussions
|
|
816
|
+
if d.get("status") == "open" and d.get("isPullRequest")
|
|
817
|
+
]
|
|
818
|
+
|
|
819
|
+
return open_prs
|
|
820
|
+
|
|
821
|
+
except requests.RequestException as e:
|
|
822
|
+
print(f"Error fetching PRs from Hugging Face: {e}")
|
|
823
|
+
return []
|
|
824
|
+
|
|
825
|
+
|
|
826
|
+
def list_open_prs(repo_id: str) -> None:
|
|
827
|
+
"""Display open pull requests for a model repository."""
|
|
828
|
+
prs = get_open_prs(repo_id)
|
|
829
|
+
|
|
830
|
+
print(f"\n{'='*70}")
|
|
831
|
+
print(f"Open Pull Requests for: {repo_id}")
|
|
832
|
+
print(f"{'='*70}")
|
|
833
|
+
|
|
834
|
+
if not prs:
|
|
835
|
+
print("\nNo open pull requests found.")
|
|
836
|
+
else:
|
|
837
|
+
print(f"\nFound {len(prs)} open PR(s):\n")
|
|
838
|
+
for pr in prs:
|
|
839
|
+
print(f" PR #{pr['num']} - {pr['title']}")
|
|
840
|
+
print(f" Author: {pr['author']}")
|
|
841
|
+
print(f" Created: {pr['createdAt']}")
|
|
842
|
+
print(f" URL: https://huggingface.co/{repo_id}/discussions/{pr['num']}")
|
|
843
|
+
print()
|
|
844
|
+
|
|
845
|
+
print(f"{'='*70}\n")
|
|
846
|
+
|
|
847
|
+
|
|
848
|
+
# ============================================================================
|
|
849
|
+
# Method 2: Import from Artificial Analysis
|
|
850
|
+
# ============================================================================
|
|
851
|
+
|
|
852
|
+
|
|
853
|
+
def get_aa_model_data(creator_slug: str, model_name: str) -> Optional[Dict[str, Any]]:
|
|
854
|
+
"""
|
|
855
|
+
Fetch model evaluation data from Artificial Analysis API.
|
|
856
|
+
|
|
857
|
+
Args:
|
|
858
|
+
creator_slug: Creator identifier (e.g., "anthropic", "openai")
|
|
859
|
+
model_name: Model slug/identifier
|
|
860
|
+
|
|
861
|
+
Returns:
|
|
862
|
+
Model data dictionary or None if not found
|
|
863
|
+
"""
|
|
864
|
+
load_env()
|
|
865
|
+
AA_API_KEY = os.getenv("AA_API_KEY")
|
|
866
|
+
if not AA_API_KEY:
|
|
867
|
+
raise ValueError("AA_API_KEY environment variable is not set")
|
|
868
|
+
|
|
869
|
+
url = "https://artificialanalysis.ai/api/v2/data/llms/models"
|
|
870
|
+
headers = {"x-api-key": AA_API_KEY}
|
|
871
|
+
|
|
872
|
+
requests = require_requests()
|
|
873
|
+
|
|
874
|
+
try:
|
|
875
|
+
response = requests.get(url, headers=headers, timeout=30)
|
|
876
|
+
response.raise_for_status()
|
|
877
|
+
|
|
878
|
+
data = response.json().get("data", [])
|
|
879
|
+
|
|
880
|
+
for model in data:
|
|
881
|
+
creator = model.get("model_creator", {})
|
|
882
|
+
if creator.get("slug") == creator_slug and model.get("slug") == model_name:
|
|
883
|
+
return model
|
|
884
|
+
|
|
885
|
+
print(f"Model {creator_slug}/{model_name} not found in Artificial Analysis")
|
|
886
|
+
return None
|
|
887
|
+
|
|
888
|
+
except requests.RequestException as e:
|
|
889
|
+
print(f"Error fetching data from Artificial Analysis: {e}")
|
|
890
|
+
return None
|
|
891
|
+
|
|
892
|
+
|
|
893
|
+
def aa_data_to_model_index(
|
|
894
|
+
model_data: Dict[str, Any],
|
|
895
|
+
dataset_name: str = "Artificial Analysis Benchmarks",
|
|
896
|
+
dataset_type: str = "artificial_analysis",
|
|
897
|
+
task_type: str = "evaluation"
|
|
898
|
+
) -> List[Dict[str, Any]]:
|
|
899
|
+
"""
|
|
900
|
+
Convert Artificial Analysis model data to model-index format.
|
|
901
|
+
|
|
902
|
+
Args:
|
|
903
|
+
model_data: Raw model data from AA API
|
|
904
|
+
dataset_name: Dataset name for model-index
|
|
905
|
+
dataset_type: Dataset type identifier
|
|
906
|
+
task_type: Task type for model-index
|
|
907
|
+
|
|
908
|
+
Returns:
|
|
909
|
+
Model-index formatted results
|
|
910
|
+
"""
|
|
911
|
+
model_name = model_data.get("name", model_data.get("slug", "unknown-model"))
|
|
912
|
+
evaluations = model_data.get("evaluations", {})
|
|
913
|
+
|
|
914
|
+
if not evaluations:
|
|
915
|
+
print(f"No evaluations found for model {model_name}")
|
|
916
|
+
return []
|
|
917
|
+
|
|
918
|
+
metrics = []
|
|
919
|
+
for key, value in evaluations.items():
|
|
920
|
+
if value is not None:
|
|
921
|
+
metrics.append({
|
|
922
|
+
"name": key.replace("_", " ").title(),
|
|
923
|
+
"type": key,
|
|
924
|
+
"value": value
|
|
925
|
+
})
|
|
926
|
+
|
|
927
|
+
results = [{
|
|
928
|
+
"task": {"type": task_type},
|
|
929
|
+
"dataset": {
|
|
930
|
+
"name": dataset_name,
|
|
931
|
+
"type": dataset_type
|
|
932
|
+
},
|
|
933
|
+
"metrics": metrics,
|
|
934
|
+
"source": {
|
|
935
|
+
"name": "Artificial Analysis API",
|
|
936
|
+
"url": "https://artificialanalysis.ai"
|
|
937
|
+
}
|
|
938
|
+
}]
|
|
939
|
+
|
|
940
|
+
return results
|
|
941
|
+
|
|
942
|
+
|
|
943
|
+
def import_aa_evaluations(
|
|
944
|
+
creator_slug: str,
|
|
945
|
+
model_name: str,
|
|
946
|
+
repo_id: str
|
|
947
|
+
) -> Optional[List[Dict[str, Any]]]:
|
|
948
|
+
"""
|
|
949
|
+
Import evaluation results from Artificial Analysis for a model.
|
|
950
|
+
|
|
951
|
+
Args:
|
|
952
|
+
creator_slug: Creator identifier in AA
|
|
953
|
+
model_name: Model identifier in AA
|
|
954
|
+
repo_id: Hugging Face repository ID to update
|
|
955
|
+
|
|
956
|
+
Returns:
|
|
957
|
+
Model-index formatted results or None if import fails
|
|
958
|
+
"""
|
|
959
|
+
model_data = get_aa_model_data(creator_slug, model_name)
|
|
960
|
+
|
|
961
|
+
if not model_data:
|
|
962
|
+
return None
|
|
963
|
+
|
|
964
|
+
results = aa_data_to_model_index(model_data)
|
|
965
|
+
return results
|
|
966
|
+
|
|
967
|
+
|
|
968
|
+
# ============================================================================
|
|
969
|
+
# Model Card Update Functions
|
|
970
|
+
# ============================================================================
|
|
971
|
+
|
|
972
|
+
|
|
973
|
+
def update_model_card_with_evaluations(
|
|
974
|
+
repo_id: str,
|
|
975
|
+
results: List[Dict[str, Any]],
|
|
976
|
+
create_pr: bool = False,
|
|
977
|
+
commit_message: Optional[str] = None
|
|
978
|
+
) -> bool:
|
|
979
|
+
"""
|
|
980
|
+
Update a model card with evaluation results.
|
|
981
|
+
|
|
982
|
+
Args:
|
|
983
|
+
repo_id: Hugging Face repository ID
|
|
984
|
+
results: Model-index formatted results
|
|
985
|
+
create_pr: Whether to create a PR instead of direct push
|
|
986
|
+
commit_message: Custom commit message
|
|
987
|
+
|
|
988
|
+
Returns:
|
|
989
|
+
True if successful, False otherwise
|
|
990
|
+
"""
|
|
991
|
+
try:
|
|
992
|
+
load_env()
|
|
993
|
+
ModelCard = require_model_card()
|
|
994
|
+
hf_token = os.getenv("HF_TOKEN")
|
|
995
|
+
if not hf_token:
|
|
996
|
+
raise ValueError("HF_TOKEN environment variable is not set")
|
|
997
|
+
|
|
998
|
+
# Load existing card
|
|
999
|
+
card = ModelCard.load(repo_id, token=hf_token)
|
|
1000
|
+
|
|
1001
|
+
# Get model name
|
|
1002
|
+
model_name = repo_id.split("/")[-1] if "/" in repo_id else repo_id
|
|
1003
|
+
|
|
1004
|
+
# Create or update model-index
|
|
1005
|
+
model_index = [{
|
|
1006
|
+
"name": model_name,
|
|
1007
|
+
"results": results
|
|
1008
|
+
}]
|
|
1009
|
+
|
|
1010
|
+
# Merge with existing model-index if present
|
|
1011
|
+
if "model-index" in card.data:
|
|
1012
|
+
existing = card.data["model-index"]
|
|
1013
|
+
if isinstance(existing, list) and existing:
|
|
1014
|
+
# Keep existing name if present
|
|
1015
|
+
if "name" in existing[0]:
|
|
1016
|
+
model_index[0]["name"] = existing[0]["name"]
|
|
1017
|
+
|
|
1018
|
+
# Merge results
|
|
1019
|
+
existing_results = existing[0].get("results", [])
|
|
1020
|
+
model_index[0]["results"].extend(existing_results)
|
|
1021
|
+
|
|
1022
|
+
card.data["model-index"] = model_index
|
|
1023
|
+
|
|
1024
|
+
# Prepare commit message
|
|
1025
|
+
if not commit_message:
|
|
1026
|
+
commit_message = f"Add evaluation results to {model_name}"
|
|
1027
|
+
|
|
1028
|
+
commit_description = (
|
|
1029
|
+
"This commit adds structured evaluation results to the model card. "
|
|
1030
|
+
"The results are formatted using the model-index specification and "
|
|
1031
|
+
"will be displayed in the model card's evaluation widget."
|
|
1032
|
+
)
|
|
1033
|
+
|
|
1034
|
+
# Push update
|
|
1035
|
+
card.push_to_hub(
|
|
1036
|
+
repo_id,
|
|
1037
|
+
token=hf_token,
|
|
1038
|
+
commit_message=commit_message,
|
|
1039
|
+
commit_description=commit_description,
|
|
1040
|
+
create_pr=create_pr
|
|
1041
|
+
)
|
|
1042
|
+
|
|
1043
|
+
action = "Pull request created" if create_pr else "Model card updated"
|
|
1044
|
+
print(f"✓ {action} successfully for {repo_id}")
|
|
1045
|
+
return True
|
|
1046
|
+
|
|
1047
|
+
except Exception as e:
|
|
1048
|
+
print(f"Error updating model card: {e}")
|
|
1049
|
+
return False
|
|
1050
|
+
|
|
1051
|
+
|
|
1052
|
+
def show_evaluations(repo_id: str) -> None:
|
|
1053
|
+
"""Display current evaluations in a model card."""
|
|
1054
|
+
try:
|
|
1055
|
+
load_env()
|
|
1056
|
+
ModelCard = require_model_card()
|
|
1057
|
+
hf_token = os.getenv("HF_TOKEN")
|
|
1058
|
+
card = ModelCard.load(repo_id, token=hf_token)
|
|
1059
|
+
|
|
1060
|
+
if "model-index" not in card.data:
|
|
1061
|
+
print(f"No model-index found in {repo_id}")
|
|
1062
|
+
return
|
|
1063
|
+
|
|
1064
|
+
model_index = card.data["model-index"]
|
|
1065
|
+
|
|
1066
|
+
print(f"\nEvaluations for {repo_id}:")
|
|
1067
|
+
print("=" * 60)
|
|
1068
|
+
|
|
1069
|
+
for model_entry in model_index:
|
|
1070
|
+
model_name = model_entry.get("name", "Unknown")
|
|
1071
|
+
print(f"\nModel: {model_name}")
|
|
1072
|
+
|
|
1073
|
+
results = model_entry.get("results", [])
|
|
1074
|
+
for i, result in enumerate(results, 1):
|
|
1075
|
+
print(f"\n Result Set {i}:")
|
|
1076
|
+
|
|
1077
|
+
task = result.get("task", {})
|
|
1078
|
+
print(f" Task: {task.get('type', 'unknown')}")
|
|
1079
|
+
|
|
1080
|
+
dataset = result.get("dataset", {})
|
|
1081
|
+
print(f" Dataset: {dataset.get('name', 'unknown')}")
|
|
1082
|
+
|
|
1083
|
+
metrics = result.get("metrics", [])
|
|
1084
|
+
print(f" Metrics ({len(metrics)}):")
|
|
1085
|
+
for metric in metrics:
|
|
1086
|
+
name = metric.get("name", "Unknown")
|
|
1087
|
+
value = metric.get("value", "N/A")
|
|
1088
|
+
print(f" - {name}: {value}")
|
|
1089
|
+
|
|
1090
|
+
source = result.get("source", {})
|
|
1091
|
+
if source:
|
|
1092
|
+
print(f" Source: {source.get('name', 'Unknown')}")
|
|
1093
|
+
|
|
1094
|
+
print("\n" + "=" * 60)
|
|
1095
|
+
|
|
1096
|
+
except Exception as e:
|
|
1097
|
+
print(f"Error showing evaluations: {e}")
|
|
1098
|
+
|
|
1099
|
+
|
|
1100
|
+
def validate_model_index(repo_id: str) -> bool:
|
|
1101
|
+
"""Validate model-index format in a model card."""
|
|
1102
|
+
try:
|
|
1103
|
+
load_env()
|
|
1104
|
+
ModelCard = require_model_card()
|
|
1105
|
+
hf_token = os.getenv("HF_TOKEN")
|
|
1106
|
+
card = ModelCard.load(repo_id, token=hf_token)
|
|
1107
|
+
|
|
1108
|
+
if "model-index" not in card.data:
|
|
1109
|
+
print(f"✗ No model-index found in {repo_id}")
|
|
1110
|
+
return False
|
|
1111
|
+
|
|
1112
|
+
model_index = card.data["model-index"]
|
|
1113
|
+
|
|
1114
|
+
if not isinstance(model_index, list):
|
|
1115
|
+
print("✗ model-index must be a list")
|
|
1116
|
+
return False
|
|
1117
|
+
|
|
1118
|
+
for i, entry in enumerate(model_index):
|
|
1119
|
+
if "name" not in entry:
|
|
1120
|
+
print(f"✗ Entry {i} missing 'name' field")
|
|
1121
|
+
return False
|
|
1122
|
+
|
|
1123
|
+
if "results" not in entry:
|
|
1124
|
+
print(f"✗ Entry {i} missing 'results' field")
|
|
1125
|
+
return False
|
|
1126
|
+
|
|
1127
|
+
for j, result in enumerate(entry["results"]):
|
|
1128
|
+
if "task" not in result:
|
|
1129
|
+
print(f"✗ Result {j} in entry {i} missing 'task' field")
|
|
1130
|
+
return False
|
|
1131
|
+
|
|
1132
|
+
if "dataset" not in result:
|
|
1133
|
+
print(f"✗ Result {j} in entry {i} missing 'dataset' field")
|
|
1134
|
+
return False
|
|
1135
|
+
|
|
1136
|
+
if "metrics" not in result:
|
|
1137
|
+
print(f"✗ Result {j} in entry {i} missing 'metrics' field")
|
|
1138
|
+
return False
|
|
1139
|
+
|
|
1140
|
+
print(f"✓ Model-index format is valid for {repo_id}")
|
|
1141
|
+
return True
|
|
1142
|
+
|
|
1143
|
+
except Exception as e:
|
|
1144
|
+
print(f"Error validating model-index: {e}")
|
|
1145
|
+
return False
|
|
1146
|
+
|
|
1147
|
+
|
|
1148
|
+
# ============================================================================
|
|
1149
|
+
# CLI Interface
|
|
1150
|
+
# ============================================================================
|
|
1151
|
+
|
|
1152
|
+
|
|
1153
|
+
def main():
|
|
1154
|
+
parser = argparse.ArgumentParser(
|
|
1155
|
+
description=(
|
|
1156
|
+
"Manage evaluation results in Hugging Face model cards.\n\n"
|
|
1157
|
+
"Use standard Python or `uv run scripts/evaluation_manager.py ...` "
|
|
1158
|
+
"to auto-resolve dependencies from the PEP 723 header."
|
|
1159
|
+
),
|
|
1160
|
+
formatter_class=argparse.RawTextHelpFormatter,
|
|
1161
|
+
epilog=dedent(
|
|
1162
|
+
"""\
|
|
1163
|
+
Typical workflows:
|
|
1164
|
+
- Inspect tables first:
|
|
1165
|
+
uv run scripts/evaluation_manager.py inspect-tables --repo-id <model>
|
|
1166
|
+
- Extract from README (prints YAML by default):
|
|
1167
|
+
uv run scripts/evaluation_manager.py extract-readme --repo-id <model> --table N
|
|
1168
|
+
- Apply changes:
|
|
1169
|
+
uv run scripts/evaluation_manager.py extract-readme --repo-id <model> --table N --apply
|
|
1170
|
+
- Import from Artificial Analysis:
|
|
1171
|
+
AA_API_KEY=... uv run scripts/evaluation_manager.py import-aa --creator-slug org --model-name slug --repo-id <model>
|
|
1172
|
+
|
|
1173
|
+
Tips:
|
|
1174
|
+
- YAML is printed by default; use --apply or --create-pr to write changes.
|
|
1175
|
+
- Set HF_TOKEN (and AA_API_KEY for import-aa); .env is loaded automatically if python-dotenv is installed.
|
|
1176
|
+
- When multiple tables exist, run inspect-tables then select with --table N.
|
|
1177
|
+
- To apply changes (push or PR), rerun extract-readme with --apply or --create-pr.
|
|
1178
|
+
"""
|
|
1179
|
+
),
|
|
1180
|
+
)
|
|
1181
|
+
parser.add_argument("--version", action="version", version="evaluation_manager 1.2.0")
|
|
1182
|
+
|
|
1183
|
+
subparsers = parser.add_subparsers(dest="command", help="Command to execute")
|
|
1184
|
+
|
|
1185
|
+
# Extract from README command
|
|
1186
|
+
extract_parser = subparsers.add_parser(
|
|
1187
|
+
"extract-readme",
|
|
1188
|
+
help="Extract evaluation tables from model README",
|
|
1189
|
+
formatter_class=argparse.RawTextHelpFormatter,
|
|
1190
|
+
description="Parse README tables into model-index YAML. Default behavior prints YAML; use --apply/--create-pr to write changes.",
|
|
1191
|
+
epilog=dedent(
|
|
1192
|
+
"""\
|
|
1193
|
+
Examples:
|
|
1194
|
+
uv run scripts/evaluation_manager.py extract-readme --repo-id username/model
|
|
1195
|
+
uv run scripts/evaluation_manager.py extract-readme --repo-id username/model --table 2 --model-column-index 3
|
|
1196
|
+
uv run scripts/evaluation_manager.py extract-readme --repo-id username/model --table 2 --model-name-override \"**Model 7B**\" # exact header text
|
|
1197
|
+
uv run scripts/evaluation_manager.py extract-readme --repo-id username/model --table 2 --create-pr
|
|
1198
|
+
|
|
1199
|
+
Apply changes:
|
|
1200
|
+
- Default: prints YAML to stdout (no writes).
|
|
1201
|
+
- Add --apply to push directly, or --create-pr to open a PR.
|
|
1202
|
+
Model selection:
|
|
1203
|
+
- Preferred: --model-column-index <header index shown by inspect-tables>
|
|
1204
|
+
- If using --model-name-override, copy the column header text exactly.
|
|
1205
|
+
"""
|
|
1206
|
+
),
|
|
1207
|
+
)
|
|
1208
|
+
extract_parser.add_argument("--repo-id", type=str, required=True, help="HF repository ID")
|
|
1209
|
+
extract_parser.add_argument("--table", type=int, help="Table number (1-indexed, from inspect-tables output)")
|
|
1210
|
+
extract_parser.add_argument("--model-column-index", type=int, help="Preferred: column index from inspect-tables output (exact selection)")
|
|
1211
|
+
extract_parser.add_argument("--model-name-override", type=str, help="Exact column header/model name for comparison/transpose tables (when index is not used)")
|
|
1212
|
+
extract_parser.add_argument("--task-type", type=str, default="text-generation", help="Sets model-index task.type (e.g., text-generation, summarization)")
|
|
1213
|
+
extract_parser.add_argument("--dataset-name", type=str, default="Benchmarks", help="Dataset name")
|
|
1214
|
+
extract_parser.add_argument("--dataset-type", type=str, default="benchmark", help="Dataset type")
|
|
1215
|
+
extract_parser.add_argument("--create-pr", action="store_true", help="Create PR instead of direct push")
|
|
1216
|
+
extract_parser.add_argument("--apply", action="store_true", help="Apply changes (default is to print YAML only)")
|
|
1217
|
+
extract_parser.add_argument("--dry-run", action="store_true", help="Preview YAML without updating (default)")
|
|
1218
|
+
|
|
1219
|
+
# Import from AA command
|
|
1220
|
+
aa_parser = subparsers.add_parser(
|
|
1221
|
+
"import-aa",
|
|
1222
|
+
help="Import evaluation scores from Artificial Analysis",
|
|
1223
|
+
formatter_class=argparse.RawTextHelpFormatter,
|
|
1224
|
+
description="Fetch scores from Artificial Analysis API and write them into model-index.",
|
|
1225
|
+
epilog=dedent(
|
|
1226
|
+
"""\
|
|
1227
|
+
Examples:
|
|
1228
|
+
AA_API_KEY=... uv run scripts/evaluation_manager.py import-aa --creator-slug anthropic --model-name claude-sonnet-4 --repo-id username/model
|
|
1229
|
+
uv run scripts/evaluation_manager.py import-aa --creator-slug openai --model-name gpt-4o --repo-id username/model --create-pr
|
|
1230
|
+
|
|
1231
|
+
Requires: AA_API_KEY in env (or .env if python-dotenv installed).
|
|
1232
|
+
"""
|
|
1233
|
+
),
|
|
1234
|
+
)
|
|
1235
|
+
aa_parser.add_argument("--creator-slug", type=str, required=True, help="AA creator slug")
|
|
1236
|
+
aa_parser.add_argument("--model-name", type=str, required=True, help="AA model name")
|
|
1237
|
+
aa_parser.add_argument("--repo-id", type=str, required=True, help="HF repository ID")
|
|
1238
|
+
aa_parser.add_argument("--create-pr", action="store_true", help="Create PR instead of direct push")
|
|
1239
|
+
|
|
1240
|
+
# Show evaluations command
|
|
1241
|
+
show_parser = subparsers.add_parser(
|
|
1242
|
+
"show",
|
|
1243
|
+
help="Display current evaluations in model card",
|
|
1244
|
+
formatter_class=argparse.RawTextHelpFormatter,
|
|
1245
|
+
description="Print model-index content from the model card (requires HF_TOKEN for private repos).",
|
|
1246
|
+
)
|
|
1247
|
+
show_parser.add_argument("--repo-id", type=str, required=True, help="HF repository ID")
|
|
1248
|
+
|
|
1249
|
+
# Validate command
|
|
1250
|
+
validate_parser = subparsers.add_parser(
|
|
1251
|
+
"validate",
|
|
1252
|
+
help="Validate model-index format",
|
|
1253
|
+
formatter_class=argparse.RawTextHelpFormatter,
|
|
1254
|
+
description="Schema sanity check for model-index section of the card.",
|
|
1255
|
+
)
|
|
1256
|
+
validate_parser.add_argument("--repo-id", type=str, required=True, help="HF repository ID")
|
|
1257
|
+
|
|
1258
|
+
# Inspect tables command
|
|
1259
|
+
inspect_parser = subparsers.add_parser(
|
|
1260
|
+
"inspect-tables",
|
|
1261
|
+
help="Inspect tables in README → outputs suggested extract-readme command",
|
|
1262
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
1263
|
+
epilog="""
|
|
1264
|
+
Workflow:
|
|
1265
|
+
1. inspect-tables → see table structure, columns, and table numbers
|
|
1266
|
+
2. extract-readme → run with --table N (from step 1); YAML prints by default
|
|
1267
|
+
3. apply changes → rerun extract-readme with --apply or --create-pr
|
|
1268
|
+
|
|
1269
|
+
Reminder:
|
|
1270
|
+
- Preferred: use --model-column-index <index>. If needed, use --model-name-override with the exact column header text.
|
|
1271
|
+
"""
|
|
1272
|
+
)
|
|
1273
|
+
inspect_parser.add_argument("--repo-id", type=str, required=True, help="HF repository ID")
|
|
1274
|
+
|
|
1275
|
+
# Get PRs command
|
|
1276
|
+
prs_parser = subparsers.add_parser(
|
|
1277
|
+
"get-prs",
|
|
1278
|
+
help="List open pull requests for a model repository",
|
|
1279
|
+
formatter_class=argparse.RawTextHelpFormatter,
|
|
1280
|
+
description="Check for existing open PRs before creating new ones to avoid duplicates.",
|
|
1281
|
+
epilog=dedent(
|
|
1282
|
+
"""\
|
|
1283
|
+
Examples:
|
|
1284
|
+
uv run scripts/evaluation_manager.py get-prs --repo-id "allenai/Olmo-3-32B-Think"
|
|
1285
|
+
|
|
1286
|
+
IMPORTANT: Always run this before using --create-pr to avoid duplicate PRs.
|
|
1287
|
+
"""
|
|
1288
|
+
),
|
|
1289
|
+
)
|
|
1290
|
+
prs_parser.add_argument("--repo-id", type=str, required=True, help="HF repository ID")
|
|
1291
|
+
|
|
1292
|
+
args = parser.parse_args()
|
|
1293
|
+
|
|
1294
|
+
if not args.command:
|
|
1295
|
+
parser.print_help()
|
|
1296
|
+
return
|
|
1297
|
+
|
|
1298
|
+
try:
|
|
1299
|
+
# Execute command
|
|
1300
|
+
if args.command == "extract-readme":
|
|
1301
|
+
results = extract_evaluations_from_readme(
|
|
1302
|
+
repo_id=args.repo_id,
|
|
1303
|
+
task_type=args.task_type,
|
|
1304
|
+
dataset_name=args.dataset_name,
|
|
1305
|
+
dataset_type=args.dataset_type,
|
|
1306
|
+
model_name_override=args.model_name_override,
|
|
1307
|
+
table_index=args.table,
|
|
1308
|
+
model_column_index=args.model_column_index
|
|
1309
|
+
)
|
|
1310
|
+
|
|
1311
|
+
if not results:
|
|
1312
|
+
print("No evaluations extracted")
|
|
1313
|
+
return
|
|
1314
|
+
|
|
1315
|
+
apply_changes = args.apply or args.create_pr
|
|
1316
|
+
|
|
1317
|
+
# Default behavior: print YAML (dry-run)
|
|
1318
|
+
yaml = require_yaml()
|
|
1319
|
+
print("\nExtracted evaluations (YAML):")
|
|
1320
|
+
print(
|
|
1321
|
+
yaml.dump(
|
|
1322
|
+
{"model-index": [{"name": args.repo_id.split('/')[-1], "results": results}]},
|
|
1323
|
+
sort_keys=False
|
|
1324
|
+
)
|
|
1325
|
+
)
|
|
1326
|
+
|
|
1327
|
+
if apply_changes:
|
|
1328
|
+
if args.model_name_override and args.model_column_index is not None:
|
|
1329
|
+
print("Note: --model-column-index takes precedence over --model-name-override.")
|
|
1330
|
+
update_model_card_with_evaluations(
|
|
1331
|
+
repo_id=args.repo_id,
|
|
1332
|
+
results=results,
|
|
1333
|
+
create_pr=args.create_pr,
|
|
1334
|
+
commit_message="Extract evaluation results from README"
|
|
1335
|
+
)
|
|
1336
|
+
|
|
1337
|
+
elif args.command == "import-aa":
|
|
1338
|
+
results = import_aa_evaluations(
|
|
1339
|
+
creator_slug=args.creator_slug,
|
|
1340
|
+
model_name=args.model_name,
|
|
1341
|
+
repo_id=args.repo_id
|
|
1342
|
+
)
|
|
1343
|
+
|
|
1344
|
+
if not results:
|
|
1345
|
+
print("No evaluations imported")
|
|
1346
|
+
return
|
|
1347
|
+
|
|
1348
|
+
update_model_card_with_evaluations(
|
|
1349
|
+
repo_id=args.repo_id,
|
|
1350
|
+
results=results,
|
|
1351
|
+
create_pr=args.create_pr,
|
|
1352
|
+
commit_message=f"Add Artificial Analysis evaluations for {args.model_name}"
|
|
1353
|
+
)
|
|
1354
|
+
|
|
1355
|
+
elif args.command == "show":
|
|
1356
|
+
show_evaluations(args.repo_id)
|
|
1357
|
+
|
|
1358
|
+
elif args.command == "validate":
|
|
1359
|
+
validate_model_index(args.repo_id)
|
|
1360
|
+
|
|
1361
|
+
elif args.command == "inspect-tables":
|
|
1362
|
+
inspect_tables(args.repo_id)
|
|
1363
|
+
|
|
1364
|
+
elif args.command == "get-prs":
|
|
1365
|
+
list_open_prs(args.repo_id)
|
|
1366
|
+
except ModuleNotFoundError as exc:
|
|
1367
|
+
# Surface dependency hints cleanly when user only needs help output
|
|
1368
|
+
print(exc)
|
|
1369
|
+
except Exception as exc:
|
|
1370
|
+
print(f"Error: {exc}")
|
|
1371
|
+
|
|
1372
|
+
|
|
1373
|
+
if __name__ == "__main__":
|
|
1374
|
+
main()
|