@prismer/runtime 2.2.55 → 2.2.63
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/CHANGELOG.md +574 -0
- package/apc/skills/releasing-test/SKILL.md +9 -0
- package/built-in-skills/agent-coordination/SKILL.md +21 -4
- package/built-in-skills/agent-meta/SKILL.md +11 -0
- package/built-in-skills/assets/SKILL.md +1 -1
- package/built-in-skills/canvas-design/SKILL.md +3 -3
- package/built-in-skills/canvas-design/canvas-fonts/IBMPlexSerif-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/InstrumentSerif-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/LICENSE-SOURCES.md +16 -0
- package/built-in-skills/claim-agent-ownership/SKILL.md +7 -3
- package/built-in-skills/claude-api/SKILL.md +1 -1
- package/built-in-skills/claude-api/python/claude-api/README.md +2 -2
- package/built-in-skills/claude-api/python/claude-api/tool-use.md +9 -5
- package/built-in-skills/claude-api/python/managed-agents/README.md +11 -1
- package/built-in-skills/claude-api/shared/error-codes.md +4 -4
- package/built-in-skills/claude-api/shared/managed-agents-client-patterns.md +4 -2
- package/built-in-skills/claude-api/shared/managed-agents-core.md +1 -2
- package/built-in-skills/claude-api/shared/managed-agents-events.md +41 -22
- package/built-in-skills/claude-api/shared/managed-agents-multiagent.md +5 -3
- package/built-in-skills/claude-api/shared/managed-agents-self-hosted-sandboxes.md +1 -1
- package/built-in-skills/claude-api/shared/managed-agents-tools.md +2 -3
- package/built-in-skills/claude-api/shared/model-migration.md +3 -3
- package/built-in-skills/claude-api/shared/models.md +1 -1
- package/built-in-skills/claude-api/typescript/claude-api/batches.md +1 -1
- package/built-in-skills/claude-api/typescript/claude-api/files-api.md +3 -1
- package/built-in-skills/claude-api/typescript/claude-api/tool-use.md +8 -2
- package/built-in-skills/claude-api/typescript/managed-agents/README.md +8 -2
- package/built-in-skills/codebase-design/SKILL.md +15 -1
- package/built-in-skills/codebase-design/references/requesting-code-review/GUIDE.md +291 -0
- package/built-in-skills/codebase-design/references/requesting-code-review/LICENSE +21 -0
- package/built-in-skills/codebase-design/references/requesting-code-review/LICENSE.superpowers +21 -0
- package/built-in-skills/codebase-design/references/requesting-code-review/NOTICE.md +37 -0
- package/built-in-skills/codebase-design/references/sdlc-review/GUIDE.md +130 -0
- package/built-in-skills/codebase-design/references/sdlc-review/LICENSE +21 -0
- package/built-in-skills/codebase-design/references/sdlc-review/NOTICE.md +17 -0
- package/built-in-skills/codebase-design/references/simplify-code/GUIDE.md +269 -0
- package/built-in-skills/codebase-design/references/simplify-code/LICENSE +21 -0
- package/built-in-skills/codebase-design/references/simplify-code/NOTICE.md +37 -0
- package/built-in-skills/competitor-intelligence/LICENSE +21 -0
- package/built-in-skills/competitor-intelligence/NOTICE.md +6 -0
- package/built-in-skills/competitor-intelligence/SKILL.md +125 -0
- package/built-in-skills/competitor-intelligence/scripts/watch_state.py +160 -0
- package/built-in-skills/conversation-compaction/SKILL.md +3 -0
- package/built-in-skills/council-creator/SKILL.md +4 -3
- package/built-in-skills/diagnosing-bugs/SKILL.md +12 -0
- package/built-in-skills/diagnosing-bugs/references/desktop-dom/GUIDE.md +64 -0
- package/built-in-skills/diagnosing-bugs/references/desktop-dom/LICENSE +21 -0
- package/built-in-skills/diagnosing-bugs/references/desktop-dom/NOTICE.md +17 -0
- package/built-in-skills/diagnosing-bugs/references/systematic-debugging/GUIDE.md +410 -0
- package/built-in-skills/diagnosing-bugs/references/systematic-debugging/LICENSE +21 -0
- package/built-in-skills/diagnosing-bugs/references/systematic-debugging/LICENSE.superpowers +21 -0
- package/built-in-skills/diagnosing-bugs/references/systematic-debugging/NOTICE.md +37 -0
- package/built-in-skills/doc-coauthoring/SKILL.md +6 -0
- package/built-in-skills/doc-coauthoring/references/humanizer/GUIDE.md +647 -0
- package/built-in-skills/doc-coauthoring/references/humanizer/LICENSE +21 -0
- package/built-in-skills/doc-coauthoring/references/humanizer/LICENSE.hermes +21 -0
- package/built-in-skills/doc-coauthoring/references/humanizer/PROVENANCE.md +7 -0
- package/built-in-skills/document-actions/LICENSE +21 -0
- package/built-in-skills/document-actions/NOTICE.md +21 -0
- package/built-in-skills/document-actions/SKILL.md +46 -0
- package/built-in-skills/evidence-citations/LICENSE +21 -0
- package/built-in-skills/evidence-citations/NOTICE.md +21 -0
- package/built-in-skills/evidence-citations/SKILL.md +46 -0
- package/built-in-skills/evidence-citations/references/citation-formats.md +68 -0
- package/built-in-skills/evidence-citations/references/grounding-rationale.md +64 -0
- package/built-in-skills/evidence-citations/scripts/sources.py +720 -0
- package/built-in-skills/frontend-design/SKILL.md +6 -0
- package/built-in-skills/frontend-design/references/claude-design/GUIDE.md +650 -0
- package/built-in-skills/frontend-design/references/claude-design/LICENSE +21 -0
- package/built-in-skills/frontend-design/references/claude-design/LICENSE.hermes +21 -0
- package/built-in-skills/frontend-design/references/claude-design/PROVENANCE.md +7 -0
- package/built-in-skills/image-generate/SKILL.md +5 -0
- package/built-in-skills/image-generate/scripts/generate-and-deliver.mjs +24 -3
- package/built-in-skills/mcp-builder/reference/evaluation.md +11 -2
- package/built-in-skills/mcp-builder/reference/node_mcp_server.md +34 -5
- package/built-in-skills/mcp-builder/reference/python_mcp_server.md +6 -2
- package/built-in-skills/mcp-builder/scripts/connections.py +1 -1
- package/built-in-skills/mcp-builder/scripts/evaluation.py +52 -34
- package/built-in-skills/mcp-builder/scripts/requirements.txt +2 -2
- package/built-in-skills/meeting-actions/LICENSE +21 -0
- package/built-in-skills/meeting-actions/NOTICE.md +21 -0
- package/built-in-skills/meeting-actions/SKILL.md +48 -0
- package/built-in-skills/memory/SKILL.md +27 -3
- package/built-in-skills/memory/references/llm-wiki/GUIDE.md +468 -0
- package/built-in-skills/memory/references/llm-wiki/LICENSE +21 -0
- package/built-in-skills/memory/references/llm-wiki/NOTICE.md +4 -0
- package/built-in-skills/memory/references/llm-wiki/scripts/lint_wiki.py +84 -0
- package/built-in-skills/memory/references/llm-wiki/scripts/requirements.txt +1 -0
- package/built-in-skills/memory/references/llm-wiki/templates/SCHEMA.md +19 -0
- package/built-in-skills/memory/references/llm-wiki/templates/index.md +9 -0
- package/built-in-skills/memory/references/llm-wiki/templates/log.md +4 -0
- package/built-in-skills/memory-dream/SKILL.md +8 -15
- package/built-in-skills/memory-import/SKILL.md +51 -0
- package/built-in-skills/office-artifacts/NOTICE.md +15 -0
- package/built-in-skills/office-artifacts/SKILL.md +20 -0
- package/built-in-skills/office-artifacts/references/RESOURCE-LIMITS.md +44 -0
- package/built-in-skills/office-artifacts/references/docx/GUIDE.md +196 -0
- package/built-in-skills/office-artifacts/references/docx/LICENSE +21 -0
- package/built-in-skills/office-artifacts/references/docx/NOTICE.md +21 -0
- package/built-in-skills/office-artifacts/references/docx/references/revisions-and-comments.md +88 -0
- package/built-in-skills/office-artifacts/references/docx/scripts/docx_comments.py +292 -0
- package/built-in-skills/office-artifacts/references/docx/scripts/docx_common.py +93 -0
- package/built-in-skills/office-artifacts/references/docx/scripts/docx_create.py +177 -0
- package/built-in-skills/office-artifacts/references/docx/scripts/docx_edit.py +250 -0
- package/built-in-skills/office-artifacts/references/docx/scripts/docx_read.py +169 -0
- package/built-in-skills/office-artifacts/references/docx/scripts/docx_revisions.py +149 -0
- package/built-in-skills/office-artifacts/references/docx/scripts/docx_template.py +70 -0
- package/built-in-skills/office-artifacts/references/docx/scripts/docx_validate.py +155 -0
- package/built-in-skills/office-artifacts/references/docx/tests/test_docx_skill.py +525 -0
- package/built-in-skills/office-artifacts/references/pdf/GUIDE.md +125 -0
- package/built-in-skills/office-artifacts/references/pdf/LICENSE +21 -0
- package/built-in-skills/office-artifacts/references/pdf/NOTICE.md +21 -0
- package/built-in-skills/office-artifacts/references/pdf/references/forms.md +99 -0
- package/built-in-skills/office-artifacts/references/pdf/references/nano-pdf-editing.md +40 -0
- package/built-in-skills/office-artifacts/references/pdf/references/ocr-extraction.md +165 -0
- package/built-in-skills/office-artifacts/references/pdf/scripts/_raster.py +87 -0
- package/built-in-skills/office-artifacts/references/pdf/scripts/extract_marker.py +95 -0
- package/built-in-skills/office-artifacts/references/pdf/scripts/extract_pymupdf.py +107 -0
- package/built-in-skills/office-artifacts/references/pdf/scripts/pdf_create.py +153 -0
- package/built-in-skills/office-artifacts/references/pdf/scripts/pdf_fill_form.py +97 -0
- package/built-in-skills/office-artifacts/references/pdf/scripts/pdf_form_layout.py +168 -0
- package/built-in-skills/office-artifacts/references/pdf/scripts/pdf_make_form.py +145 -0
- package/built-in-skills/office-artifacts/references/pdf/scripts/pdf_merge.py +50 -0
- package/built-in-skills/office-artifacts/references/pdf/scripts/pdf_meta.py +123 -0
- package/built-in-skills/office-artifacts/references/pdf/scripts/pdf_page_image.py +101 -0
- package/built-in-skills/office-artifacts/references/pdf/scripts/pdf_read.py +153 -0
- package/built-in-skills/office-artifacts/references/pdf/scripts/pdf_secure.py +71 -0
- package/built-in-skills/office-artifacts/references/pdf/scripts/pdf_split.py +86 -0
- package/built-in-skills/office-artifacts/references/pdf/scripts/pdf_stamp.py +145 -0
- package/built-in-skills/office-artifacts/references/pdf/scripts/pdf_watermark.py +51 -0
- package/built-in-skills/office-artifacts/references/pdf/tests/test_pdf_skill.py +414 -0
- package/built-in-skills/office-artifacts/references/powerpoint/GUIDE.md +220 -0
- package/built-in-skills/office-artifacts/references/powerpoint/LICENSE +21 -0
- package/built-in-skills/office-artifacts/references/powerpoint/NOTICE.md +21 -0
- package/built-in-skills/office-artifacts/references/powerpoint/scripts/pptx_create.py +214 -0
- package/built-in-skills/office-artifacts/references/powerpoint/scripts/pptx_edit.py +442 -0
- package/built-in-skills/office-artifacts/references/powerpoint/scripts/pptx_from_template.py +88 -0
- package/built-in-skills/office-artifacts/references/powerpoint/scripts/pptx_read.py +131 -0
- package/built-in-skills/office-artifacts/references/powerpoint/scripts/pptx_render.py +104 -0
- package/built-in-skills/office-artifacts/references/powerpoint/tests/test_powerpoint_skill.py +478 -0
- package/built-in-skills/office-artifacts/references/xlsx/GUIDE.md +196 -0
- package/built-in-skills/office-artifacts/references/xlsx/LICENSE +21 -0
- package/built-in-skills/office-artifacts/references/xlsx/NOTICE.md +21 -0
- package/built-in-skills/office-artifacts/references/xlsx/references/restructuring.md +74 -0
- package/built-in-skills/office-artifacts/references/xlsx/scripts/csv_to_xlsx.py +108 -0
- package/built-in-skills/office-artifacts/references/xlsx/scripts/xlsx_create.py +259 -0
- package/built-in-skills/office-artifacts/references/xlsx/scripts/xlsx_edit.py +269 -0
- package/built-in-skills/office-artifacts/references/xlsx/scripts/xlsx_read.py +160 -0
- package/built-in-skills/office-artifacts/references/xlsx/scripts/xlsx_recalc.py +111 -0
- package/built-in-skills/office-artifacts/references/xlsx/scripts/xlsx_restructure.py +418 -0
- package/built-in-skills/office-artifacts/references/xlsx/scripts/xlsx_to_csv.py +69 -0
- package/built-in-skills/office-artifacts/references/xlsx/tests/test_xlsx_skill.py +542 -0
- package/built-in-skills/office-artifacts/tests/test_resource_regressions.py +272 -0
- package/built-in-skills/persona-generator/SKILL.md +9 -9
- package/built-in-skills/pkf-svg/SKILL.md +5 -0
- package/built-in-skills/pkf-svg/references/architecture-diagram/GUIDE.md +148 -0
- package/built-in-skills/pkf-svg/references/architecture-diagram/LICENSE +21 -0
- package/built-in-skills/pkf-svg/references/architecture-diagram/LICENSE.hermes +21 -0
- package/built-in-skills/pkf-svg/references/architecture-diagram/PROVENANCE.md +7 -0
- package/built-in-skills/pkf-svg/references/architecture-diagram/templates/template.html +345 -0
- package/built-in-skills/pkf-writing/SKILL.md +36 -14
- package/built-in-skills/prismer-airtable/LICENSE +21 -0
- package/built-in-skills/prismer-airtable/NOTICE.md +11 -0
- package/built-in-skills/prismer-airtable/SKILL.md +248 -0
- package/built-in-skills/prismer-airtable/scripts/airtable_client.py +76 -0
- package/built-in-skills/prismer-apple-notes/LICENSE +21 -0
- package/built-in-skills/prismer-apple-notes/NOTICE.md +17 -0
- package/built-in-skills/prismer-apple-notes/SKILL.md +118 -0
- package/built-in-skills/prismer-apple-notes/scripts/readiness.py +47 -0
- package/built-in-skills/prismer-apple-reminders/LICENSE +21 -0
- package/built-in-skills/prismer-apple-reminders/NOTICE.md +17 -0
- package/built-in-skills/prismer-apple-reminders/SKILL.md +155 -0
- package/built-in-skills/prismer-apple-reminders/scripts/readiness.py +47 -0
- package/built-in-skills/prismer-ascii-video/LICENSE +21 -0
- package/built-in-skills/prismer-ascii-video/LICENSE.hermes +21 -0
- package/built-in-skills/prismer-ascii-video/PROVENANCE.md +7 -0
- package/built-in-skills/prismer-ascii-video/README.md +290 -0
- package/built-in-skills/prismer-ascii-video/SKILL.md +252 -0
- package/built-in-skills/prismer-ascii-video/provenance/category-DESCRIPTION.md +3 -0
- package/built-in-skills/prismer-ascii-video/references/architecture.md +807 -0
- package/built-in-skills/prismer-ascii-video/references/composition.md +900 -0
- package/built-in-skills/prismer-ascii-video/references/effects.md +1877 -0
- package/built-in-skills/prismer-ascii-video/references/inputs.md +693 -0
- package/built-in-skills/prismer-ascii-video/references/optimization.md +688 -0
- package/built-in-skills/prismer-ascii-video/references/scenes.md +1018 -0
- package/built-in-skills/prismer-ascii-video/references/shaders.md +1408 -0
- package/built-in-skills/prismer-ascii-video/references/troubleshooting.md +360 -0
- package/built-in-skills/prismer-baoyu-infographic/LICENSE +21 -0
- package/built-in-skills/prismer-baoyu-infographic/LICENSE.hermes +21 -0
- package/built-in-skills/prismer-baoyu-infographic/LICENSE.origin +21 -0
- package/built-in-skills/prismer-baoyu-infographic/PORT_NOTES.md +37 -0
- package/built-in-skills/prismer-baoyu-infographic/PROVENANCE.md +7 -0
- package/built-in-skills/prismer-baoyu-infographic/SKILL.md +240 -0
- package/built-in-skills/prismer-baoyu-infographic/references/analysis-framework.md +182 -0
- package/built-in-skills/prismer-baoyu-infographic/references/base-prompt.md +43 -0
- package/built-in-skills/prismer-baoyu-infographic/references/layouts/bento-grid.md +41 -0
- package/built-in-skills/prismer-baoyu-infographic/references/layouts/binary-comparison.md +48 -0
- package/built-in-skills/prismer-baoyu-infographic/references/layouts/bridge.md +41 -0
- package/built-in-skills/prismer-baoyu-infographic/references/layouts/circular-flow.md +41 -0
- package/built-in-skills/prismer-baoyu-infographic/references/layouts/comic-strip.md +41 -0
- package/built-in-skills/prismer-baoyu-infographic/references/layouts/comparison-matrix.md +41 -0
- package/built-in-skills/prismer-baoyu-infographic/references/layouts/dashboard.md +41 -0
- package/built-in-skills/prismer-baoyu-infographic/references/layouts/dense-modules.md +72 -0
- package/built-in-skills/prismer-baoyu-infographic/references/layouts/funnel.md +41 -0
- package/built-in-skills/prismer-baoyu-infographic/references/layouts/hierarchical-layers.md +48 -0
- package/built-in-skills/prismer-baoyu-infographic/references/layouts/hub-spoke.md +41 -0
- package/built-in-skills/prismer-baoyu-infographic/references/layouts/iceberg.md +41 -0
- package/built-in-skills/prismer-baoyu-infographic/references/layouts/isometric-map.md +41 -0
- package/built-in-skills/prismer-baoyu-infographic/references/layouts/jigsaw.md +41 -0
- package/built-in-skills/prismer-baoyu-infographic/references/layouts/linear-progression.md +48 -0
- package/built-in-skills/prismer-baoyu-infographic/references/layouts/periodic-table.md +41 -0
- package/built-in-skills/prismer-baoyu-infographic/references/layouts/story-mountain.md +41 -0
- package/built-in-skills/prismer-baoyu-infographic/references/layouts/structural-breakdown.md +48 -0
- package/built-in-skills/prismer-baoyu-infographic/references/layouts/tree-branching.md +41 -0
- package/built-in-skills/prismer-baoyu-infographic/references/layouts/venn-diagram.md +41 -0
- package/built-in-skills/prismer-baoyu-infographic/references/layouts/winding-roadmap.md +41 -0
- package/built-in-skills/prismer-baoyu-infographic/references/structured-content-template.md +244 -0
- package/built-in-skills/prismer-baoyu-infographic/references/styles/aged-academia.md +36 -0
- package/built-in-skills/prismer-baoyu-infographic/references/styles/bold-graphic.md +36 -0
- package/built-in-skills/prismer-baoyu-infographic/references/styles/chalkboard.md +61 -0
- package/built-in-skills/prismer-baoyu-infographic/references/styles/claymation.md +29 -0
- package/built-in-skills/prismer-baoyu-infographic/references/styles/corporate-memphis.md +29 -0
- package/built-in-skills/prismer-baoyu-infographic/references/styles/craft-handmade.md +44 -0
- package/built-in-skills/prismer-baoyu-infographic/references/styles/cyberpunk-neon.md +29 -0
- package/built-in-skills/prismer-baoyu-infographic/references/styles/hand-drawn-edu.md +63 -0
- package/built-in-skills/prismer-baoyu-infographic/references/styles/ikea-manual.md +29 -0
- package/built-in-skills/prismer-baoyu-infographic/references/styles/kawaii.md +29 -0
- package/built-in-skills/prismer-baoyu-infographic/references/styles/knolling.md +29 -0
- package/built-in-skills/prismer-baoyu-infographic/references/styles/lego-brick.md +29 -0
- package/built-in-skills/prismer-baoyu-infographic/references/styles/morandi-journal.md +60 -0
- package/built-in-skills/prismer-baoyu-infographic/references/styles/origami.md +29 -0
- package/built-in-skills/prismer-baoyu-infographic/references/styles/pixel-art.md +29 -0
- package/built-in-skills/prismer-baoyu-infographic/references/styles/pop-laboratory.md +48 -0
- package/built-in-skills/prismer-baoyu-infographic/references/styles/retro-pop-grid.md +47 -0
- package/built-in-skills/prismer-baoyu-infographic/references/styles/storybook-watercolor.md +29 -0
- package/built-in-skills/prismer-baoyu-infographic/references/styles/subway-map.md +29 -0
- package/built-in-skills/prismer-baoyu-infographic/references/styles/technical-schematic.md +36 -0
- package/built-in-skills/prismer-baoyu-infographic/references/styles/ui-wireframe.md +29 -0
- package/built-in-skills/prismer-blocked-page-recovery/LICENSE +21 -0
- package/built-in-skills/prismer-blocked-page-recovery/NOTICE.md +17 -0
- package/built-in-skills/prismer-blocked-page-recovery/SKILL.md +158 -0
- package/built-in-skills/prismer-blocked-page-recovery/scripts/recover_page.py +311 -0
- package/built-in-skills/prismer-box/LICENSE +21 -0
- package/built-in-skills/prismer-box/NOTICE.md +11 -0
- package/built-in-skills/prismer-box/SKILL.md +147 -0
- package/built-in-skills/prismer-box/references/bulk-operations.md +43 -0
- package/built-in-skills/prismer-box/references/cli-guide.md +133 -0
- package/built-in-skills/prismer-box/references/content-workflows.md +86 -0
- package/built-in-skills/prismer-box/references/hubs.md +77 -0
- package/built-in-skills/prismer-box/references/oauth-setup.md +92 -0
- package/built-in-skills/prismer-box/references/rest-api.md +37 -0
- package/built-in-skills/prismer-box/references/sdk-development.md +85 -0
- package/built-in-skills/prismer-box/references/search-and-ai.md +147 -0
- package/built-in-skills/prismer-box/references/troubleshooting.md +33 -0
- package/built-in-skills/prismer-box/references/webhooks-and-events.md +43 -0
- package/built-in-skills/prismer-codebase-inspection/LICENSE +21 -0
- package/built-in-skills/prismer-codebase-inspection/NOTICE.md +17 -0
- package/built-in-skills/prismer-codebase-inspection/SKILL.md +141 -0
- package/built-in-skills/prismer-computer-use/LICENSE +21 -0
- package/built-in-skills/prismer-computer-use/NOTICE.md +17 -0
- package/built-in-skills/prismer-computer-use/SKILL.md +372 -0
- package/built-in-skills/prismer-design-md/LICENSE +21 -0
- package/built-in-skills/prismer-design-md/LICENSE.hermes +21 -0
- package/built-in-skills/prismer-design-md/PROVENANCE.md +7 -0
- package/built-in-skills/prismer-design-md/SKILL.md +227 -0
- package/built-in-skills/prismer-design-md/templates/starter.md +99 -0
- package/built-in-skills/prismer-email-inbox-triage/LICENSE +21 -0
- package/built-in-skills/prismer-email-inbox-triage/NOTICE.md +11 -0
- package/built-in-skills/prismer-email-inbox-triage/SKILL.md +116 -0
- package/built-in-skills/prismer-findmy/LICENSE +21 -0
- package/built-in-skills/prismer-findmy/NOTICE.md +17 -0
- package/built-in-skills/prismer-findmy/SKILL.md +150 -0
- package/built-in-skills/prismer-findmy/scripts/readiness.py +47 -0
- package/built-in-skills/prismer-gif-search/LICENSE +21 -0
- package/built-in-skills/prismer-gif-search/LICENSE.hermes +21 -0
- package/built-in-skills/prismer-gif-search/PROVENANCE.md +7 -0
- package/built-in-skills/prismer-gif-search/SKILL.md +97 -0
- package/built-in-skills/prismer-gif-search/scripts/tenor.py +81 -0
- package/built-in-skills/prismer-github/LICENSE +21 -0
- package/built-in-skills/prismer-github/NOTICE.md +17 -0
- package/built-in-skills/prismer-github/SKILL.md +74 -0
- package/built-in-skills/prismer-github/references/auth.md +91 -0
- package/built-in-skills/prismer-github/references/ci-troubleshooting.md +193 -0
- package/built-in-skills/prismer-github/references/code-review.md +465 -0
- package/built-in-skills/prismer-github/references/conventional-commits.md +81 -0
- package/built-in-skills/prismer-github/references/github-api-cheatsheet.md +177 -0
- package/built-in-skills/prismer-github/references/issue-to-pr.md +74 -0
- package/built-in-skills/prismer-github/references/issues.md +336 -0
- package/built-in-skills/prismer-github/references/pr-workflow.md +346 -0
- package/built-in-skills/prismer-github/references/repo-management.md +484 -0
- package/built-in-skills/prismer-github/references/review-output-template.md +84 -0
- package/built-in-skills/prismer-github/scripts/ensure-gh.py +132 -0
- package/built-in-skills/prismer-github/scripts/gh-env.sh +25 -0
- package/built-in-skills/prismer-github/scripts/git-credential-token.py +68 -0
- package/built-in-skills/prismer-github/scripts/github-api.py +71 -0
- package/built-in-skills/prismer-github/scripts/github-context.py +28 -0
- package/built-in-skills/prismer-github/templates/bug-report.md +35 -0
- package/built-in-skills/prismer-github/templates/feature-request.md +31 -0
- package/built-in-skills/prismer-github/templates/pr-body-bugfix.md +35 -0
- package/built-in-skills/prismer-github/templates/pr-body-feature.md +33 -0
- package/built-in-skills/prismer-google-workspace/LICENSE +21 -0
- package/built-in-skills/prismer-google-workspace/NOTICE.md +11 -0
- package/built-in-skills/prismer-google-workspace/SKILL.md +369 -0
- package/built-in-skills/prismer-google-workspace/references/daily-brief.md +65 -0
- package/built-in-skills/prismer-google-workspace/references/gmail-search-syntax.md +63 -0
- package/built-in-skills/prismer-google-workspace/scripts/_hermes_home.py +17 -0
- package/built-in-skills/prismer-google-workspace/scripts/_private_state.py +39 -0
- package/built-in-skills/prismer-google-workspace/scripts/google_api.py +1339 -0
- package/built-in-skills/prismer-google-workspace/scripts/gws_bridge.py +121 -0
- package/built-in-skills/prismer-google-workspace/scripts/setup.py +563 -0
- package/built-in-skills/prismer-google-workspace/tests/test_productivity_regressions.py +214 -0
- package/built-in-skills/prismer-hermes-agent/LICENSE +21 -0
- package/built-in-skills/prismer-hermes-agent/NOTICE.md +17 -0
- package/built-in-skills/prismer-hermes-agent/SKILL.md +247 -0
- package/built-in-skills/prismer-hermes-agent/references/background-systems.md +108 -0
- package/built-in-skills/prismer-hermes-agent/references/cli-reference.md +158 -0
- package/built-in-skills/prismer-hermes-agent/references/configuration.md +96 -0
- package/built-in-skills/prismer-hermes-agent/references/contributor-guide.md +151 -0
- package/built-in-skills/prismer-hermes-agent/references/delegate-task-concurrency-diagnosis.md +47 -0
- package/built-in-skills/prismer-hermes-agent/references/desktop-plugins.md +215 -0
- package/built-in-skills/prismer-hermes-agent/references/native-mcp.md +351 -0
- package/built-in-skills/prismer-hermes-agent/references/petdex.md +82 -0
- package/built-in-skills/prismer-hermes-agent/references/portal-auth-for-third-party-apps.md +135 -0
- package/built-in-skills/prismer-hermes-agent/references/project-context-files.md +55 -0
- package/built-in-skills/prismer-hermes-agent/references/providers-and-models.md +81 -0
- package/built-in-skills/prismer-hermes-agent/references/security-privacy.md +73 -0
- package/built-in-skills/prismer-hermes-agent/references/slash-commands.md +119 -0
- package/built-in-skills/prismer-hermes-agent/references/themes.md +134 -0
- package/built-in-skills/prismer-hermes-agent/references/troubleshooting.md +87 -0
- package/built-in-skills/prismer-hermes-agent/references/tui-widgets.md +144 -0
- package/built-in-skills/prismer-hermes-agent/references/webhooks.md +219 -0
- package/built-in-skills/prismer-hermes-agent/references/windows-quirks.md +64 -0
- package/built-in-skills/prismer-hermes-agent/templates/clock.mjs +51 -0
- package/built-in-skills/prismer-hermes-agent/templates/plugin.js +97 -0
- package/built-in-skills/prismer-hermes-agent/templates/skin.yaml +49 -0
- package/built-in-skills/prismer-himalaya/LICENSE +21 -0
- package/built-in-skills/prismer-himalaya/NOTICE.md +11 -0
- package/built-in-skills/prismer-himalaya/SKILL.md +340 -0
- package/built-in-skills/prismer-himalaya/references/configuration.md +227 -0
- package/built-in-skills/prismer-himalaya/references/message-composition.md +206 -0
- package/built-in-skills/prismer-himalaya/scripts/compose_draft.py +48 -0
- package/built-in-skills/prismer-im-collab/SKILL.md +1 -1
- package/built-in-skills/prismer-imessage/LICENSE +21 -0
- package/built-in-skills/prismer-imessage/NOTICE.md +17 -0
- package/built-in-skills/prismer-imessage/SKILL.md +128 -0
- package/built-in-skills/prismer-imessage/scripts/readiness.py +47 -0
- package/built-in-skills/prismer-manim-video/LICENSE +21 -0
- package/built-in-skills/prismer-manim-video/LICENSE.hermes +21 -0
- package/built-in-skills/prismer-manim-video/PROVENANCE.md +7 -0
- package/built-in-skills/prismer-manim-video/README.md +23 -0
- package/built-in-skills/prismer-manim-video/SKILL.md +279 -0
- package/built-in-skills/prismer-manim-video/references/animation-design-thinking.md +161 -0
- package/built-in-skills/prismer-manim-video/references/animations.md +282 -0
- package/built-in-skills/prismer-manim-video/references/camera-and-3d.md +135 -0
- package/built-in-skills/prismer-manim-video/references/decorations.md +202 -0
- package/built-in-skills/prismer-manim-video/references/equations.md +216 -0
- package/built-in-skills/prismer-manim-video/references/graphs-and-data.md +163 -0
- package/built-in-skills/prismer-manim-video/references/mobjects.md +333 -0
- package/built-in-skills/prismer-manim-video/references/paper-explainer.md +255 -0
- package/built-in-skills/prismer-manim-video/references/production-quality.md +190 -0
- package/built-in-skills/prismer-manim-video/references/rendering.md +187 -0
- package/built-in-skills/prismer-manim-video/references/scene-planning.md +118 -0
- package/built-in-skills/prismer-manim-video/references/troubleshooting.md +135 -0
- package/built-in-skills/prismer-manim-video/references/updaters-and-trackers.md +260 -0
- package/built-in-skills/prismer-manim-video/references/visual-design.md +124 -0
- package/built-in-skills/prismer-manim-video/scripts/setup.sh +15 -0
- package/built-in-skills/prismer-maps/LICENSE +21 -0
- package/built-in-skills/prismer-maps/NOTICE.md +11 -0
- package/built-in-skills/prismer-maps/SKILL.md +240 -0
- package/built-in-skills/prismer-maps/scripts/maps_client.py +1324 -0
- package/built-in-skills/prismer-node-inspect-debugger/LICENSE +21 -0
- package/built-in-skills/prismer-node-inspect-debugger/NOTICE.md +17 -0
- package/built-in-skills/prismer-node-inspect-debugger/SKILL.md +347 -0
- package/built-in-skills/prismer-notion/LICENSE +21 -0
- package/built-in-skills/prismer-notion/NOTICE.md +11 -0
- package/built-in-skills/prismer-notion/SKILL.md +495 -0
- package/built-in-skills/prismer-notion/references/block-types.md +112 -0
- package/built-in-skills/prismer-obsidian/LICENSE +21 -0
- package/built-in-skills/prismer-obsidian/LICENSE.hermes +21 -0
- package/built-in-skills/prismer-obsidian/PROVENANCE.md +7 -0
- package/built-in-skills/prismer-obsidian/SKILL.md +80 -0
- package/built-in-skills/prismer-obsidian/provenance/category-DESCRIPTION.md +3 -0
- package/built-in-skills/prismer-obsidian/scripts/write_note.py +84 -0
- package/built-in-skills/prismer-p5js/LICENSE +21 -0
- package/built-in-skills/prismer-p5js/LICENSE.hermes +21 -0
- package/built-in-skills/prismer-p5js/PROVENANCE.md +7 -0
- package/built-in-skills/prismer-p5js/README.md +64 -0
- package/built-in-skills/prismer-p5js/SKILL.md +574 -0
- package/built-in-skills/prismer-p5js/references/animation.md +439 -0
- package/built-in-skills/prismer-p5js/references/color-systems.md +355 -0
- package/built-in-skills/prismer-p5js/references/core-api.md +410 -0
- package/built-in-skills/prismer-p5js/references/export-pipeline.md +534 -0
- package/built-in-skills/prismer-p5js/references/interaction.md +398 -0
- package/built-in-skills/prismer-p5js/references/shapes-and-geometry.md +300 -0
- package/built-in-skills/prismer-p5js/references/troubleshooting.md +532 -0
- package/built-in-skills/prismer-p5js/references/typography.md +302 -0
- package/built-in-skills/prismer-p5js/references/visual-effects.md +905 -0
- package/built-in-skills/prismer-p5js/references/webgl-and-3d.md +423 -0
- package/built-in-skills/prismer-p5js/scripts/export-frames.js +91 -0
- package/built-in-skills/prismer-p5js/scripts/render.sh +113 -0
- package/built-in-skills/prismer-p5js/scripts/serve.sh +25 -0
- package/built-in-skills/prismer-p5js/scripts/setup.sh +87 -0
- package/built-in-skills/prismer-p5js/templates/viewer.html +401 -0
- package/built-in-skills/prismer-popular-web-designs/LICENSE +21 -0
- package/built-in-skills/prismer-popular-web-designs/LICENSE.hermes +21 -0
- package/built-in-skills/prismer-popular-web-designs/LICENSE.origin +21 -0
- package/built-in-skills/prismer-popular-web-designs/PROVENANCE.md +7 -0
- package/built-in-skills/prismer-popular-web-designs/SKILL.md +218 -0
- package/built-in-skills/prismer-popular-web-designs/templates/airbnb.md +259 -0
- package/built-in-skills/prismer-popular-web-designs/templates/airtable.md +102 -0
- package/built-in-skills/prismer-popular-web-designs/templates/apple.md +326 -0
- package/built-in-skills/prismer-popular-web-designs/templates/bmw.md +193 -0
- package/built-in-skills/prismer-popular-web-designs/templates/cal.md +272 -0
- package/built-in-skills/prismer-popular-web-designs/templates/claude.md +325 -0
- package/built-in-skills/prismer-popular-web-designs/templates/clay.md +317 -0
- package/built-in-skills/prismer-popular-web-designs/templates/clickhouse.md +294 -0
- package/built-in-skills/prismer-popular-web-designs/templates/cohere.md +279 -0
- package/built-in-skills/prismer-popular-web-designs/templates/coinbase.md +142 -0
- package/built-in-skills/prismer-popular-web-designs/templates/composio.md +320 -0
- package/built-in-skills/prismer-popular-web-designs/templates/cursor.md +322 -0
- package/built-in-skills/prismer-popular-web-designs/templates/elevenlabs.md +278 -0
- package/built-in-skills/prismer-popular-web-designs/templates/expo.md +294 -0
- package/built-in-skills/prismer-popular-web-designs/templates/figma.md +233 -0
- package/built-in-skills/prismer-popular-web-designs/templates/framer.md +259 -0
- package/built-in-skills/prismer-popular-web-designs/templates/hashicorp.md +291 -0
- package/built-in-skills/prismer-popular-web-designs/templates/ibm.md +345 -0
- package/built-in-skills/prismer-popular-web-designs/templates/intercom.md +159 -0
- package/built-in-skills/prismer-popular-web-designs/templates/kraken.md +138 -0
- package/built-in-skills/prismer-popular-web-designs/templates/linear.app.md +380 -0
- package/built-in-skills/prismer-popular-web-designs/templates/lovable.md +311 -0
- package/built-in-skills/prismer-popular-web-designs/templates/minimax.md +270 -0
- package/built-in-skills/prismer-popular-web-designs/templates/mintlify.md +339 -0
- package/built-in-skills/prismer-popular-web-designs/templates/miro.md +121 -0
- package/built-in-skills/prismer-popular-web-designs/templates/mistral.ai.md +274 -0
- package/built-in-skills/prismer-popular-web-designs/templates/mongodb.md +279 -0
- package/built-in-skills/prismer-popular-web-designs/templates/notion.md +322 -0
- package/built-in-skills/prismer-popular-web-designs/templates/nvidia.md +306 -0
- package/built-in-skills/prismer-popular-web-designs/templates/ollama.md +280 -0
- package/built-in-skills/prismer-popular-web-designs/templates/opencode.ai.md +294 -0
- package/built-in-skills/prismer-popular-web-designs/templates/pinterest.md +243 -0
- package/built-in-skills/prismer-popular-web-designs/templates/posthog.md +269 -0
- package/built-in-skills/prismer-popular-web-designs/templates/raycast.md +281 -0
- package/built-in-skills/prismer-popular-web-designs/templates/replicate.md +274 -0
- package/built-in-skills/prismer-popular-web-designs/templates/resend.md +316 -0
- package/built-in-skills/prismer-popular-web-designs/templates/revolut.md +198 -0
- package/built-in-skills/prismer-popular-web-designs/templates/runwayml.md +257 -0
- package/built-in-skills/prismer-popular-web-designs/templates/sanity.md +370 -0
- package/built-in-skills/prismer-popular-web-designs/templates/sentry.md +275 -0
- package/built-in-skills/prismer-popular-web-designs/templates/spacex.md +207 -0
- package/built-in-skills/prismer-popular-web-designs/templates/spotify.md +259 -0
- package/built-in-skills/prismer-popular-web-designs/templates/stripe.md +335 -0
- package/built-in-skills/prismer-popular-web-designs/templates/supabase.md +268 -0
- package/built-in-skills/prismer-popular-web-designs/templates/superhuman.md +265 -0
- package/built-in-skills/prismer-popular-web-designs/templates/together.ai.md +276 -0
- package/built-in-skills/prismer-popular-web-designs/templates/uber.md +308 -0
- package/built-in-skills/prismer-popular-web-designs/templates/vercel.md +323 -0
- package/built-in-skills/prismer-popular-web-designs/templates/voltagent.md +336 -0
- package/built-in-skills/prismer-popular-web-designs/templates/warp.md +266 -0
- package/built-in-skills/prismer-popular-web-designs/templates/webflow.md +105 -0
- package/built-in-skills/prismer-popular-web-designs/templates/wise.md +186 -0
- package/built-in-skills/prismer-popular-web-designs/templates/x.ai.md +270 -0
- package/built-in-skills/prismer-popular-web-designs/templates/zapier.md +341 -0
- package/built-in-skills/prismer-product-price-monitor/LICENSE +21 -0
- package/built-in-skills/prismer-product-price-monitor/NOTICE.md +11 -0
- package/built-in-skills/prismer-product-price-monitor/SKILL.md +97 -0
- package/built-in-skills/prismer-product-price-monitor/scripts/watch_state.py +116 -0
- package/built-in-skills/prismer-python-debugpy/LICENSE +21 -0
- package/built-in-skills/prismer-python-debugpy/NOTICE.md +17 -0
- package/built-in-skills/prismer-python-debugpy/SKILL.md +377 -0
- package/built-in-skills/prismer-python-debugpy/scripts/dap_client.py +68 -0
- package/built-in-skills/prismer-songsee/LICENSE +21 -0
- package/built-in-skills/prismer-songsee/LICENSE.hermes +21 -0
- package/built-in-skills/prismer-songsee/PROVENANCE.md +7 -0
- package/built-in-skills/prismer-songsee/SKILL.md +91 -0
- package/built-in-skills/prismer-songwriting-and-ai-music/LICENSE +21 -0
- package/built-in-skills/prismer-songwriting-and-ai-music/LICENSE.hermes +21 -0
- package/built-in-skills/prismer-songwriting-and-ai-music/PROVENANCE.md +7 -0
- package/built-in-skills/prismer-songwriting-and-ai-music/SKILL.md +317 -0
- package/built-in-skills/prismer-spike/LICENSE +21 -0
- package/built-in-skills/prismer-spike/LICENSE.gsd +21 -0
- package/built-in-skills/prismer-spike/NOTICE.md +17 -0
- package/built-in-skills/prismer-spike/SKILL.md +212 -0
- package/built-in-skills/prismer-teams-meeting-pipeline/LICENSE +21 -0
- package/built-in-skills/prismer-teams-meeting-pipeline/NOTICE.md +11 -0
- package/built-in-skills/prismer-teams-meeting-pipeline/SKILL.md +156 -0
- package/built-in-skills/prismer-xurl/LICENSE +21 -0
- package/built-in-skills/prismer-xurl/LICENSE.hermes +21 -0
- package/built-in-skills/prismer-xurl/PROVENANCE.md +7 -0
- package/built-in-skills/prismer-xurl/SKILL.md +444 -0
- package/built-in-skills/prismer-xurl/provenance/category-DESCRIPTION.md +3 -0
- package/built-in-skills/prismer-youtube-content/LICENSE +21 -0
- package/built-in-skills/prismer-youtube-content/LICENSE.hermes +21 -0
- package/built-in-skills/prismer-youtube-content/PROVENANCE.md +7 -0
- package/built-in-skills/prismer-youtube-content/SKILL.md +86 -0
- package/built-in-skills/prismer-youtube-content/provenance/category-DESCRIPTION.md +3 -0
- package/built-in-skills/prismer-youtube-content/references/output-formats.md +56 -0
- package/built-in-skills/prismer-youtube-content/scripts/fetch_transcript.py +146 -0
- package/built-in-skills/research-arxiv/LICENSE +21 -0
- package/built-in-skills/research-arxiv/NOTICE.md +4 -0
- package/built-in-skills/research-arxiv/SKILL.md +263 -0
- package/built-in-skills/research-arxiv/scripts/search_arxiv.py +111 -0
- package/built-in-skills/role-builder/SKILL.md +7 -1
- package/built-in-skills/role-builder/scripts/author-role.mjs +23 -7
- package/built-in-skills/role-builder/scripts/ingest-role.mjs +15 -117
- package/built-in-skills/role-builder/scripts/instantiate-and-run.mjs +15 -1
- package/built-in-skills/role-builder/scripts/operation-harness.mjs +6 -4
- package/built-in-skills/skill-creator/LICENSE.prismer +21 -0
- package/built-in-skills/skill-creator/NOTICE.md +18 -0
- package/built-in-skills/skill-creator/SKILL.md +20 -1
- package/built-in-skills/skill-creator/eval-viewer/generate_review.py +20 -31
- package/built-in-skills/skill-creator/eval-viewer/viewer.html +35 -23
- package/built-in-skills/skill-creator/references/hermes-agent-skill-authoring/GUIDE.md +220 -0
- package/built-in-skills/skill-creator/references/hermes-agent-skill-authoring/LICENSE +21 -0
- package/built-in-skills/{skill-authoring/SKILL.md → skill-creator/references/skill-authoring/GUIDE.md} +1 -1
- package/built-in-skills/{skill-builder/SKILL.md → skill-creator/references/skill-builder/GUIDE.md} +8 -12
- package/built-in-skills/skill-creator/references/skill-builder/scripts/ingest.mjs +93 -0
- package/built-in-skills/skill-creator/scripts/aggregate_benchmark.py +3 -2
- package/built-in-skills/skill-creator/scripts/import-library.mjs +30 -7
- package/built-in-skills/skill-creator/scripts/improve_description.py +14 -16
- package/built-in-skills/skill-creator/scripts/package_skill.py +16 -9
- package/built-in-skills/skill-creator/scripts/quick_validate.py +22 -5
- package/built-in-skills/skill-creator/scripts/run_eval.py +63 -144
- package/built-in-skills/skill-creator/scripts/run_loop.py +24 -16
- package/built-in-skills/slack-gif-creator/core/gif_builder.py +13 -2
- package/built-in-skills/slack-gif-creator/core/validators.py +17 -7
- package/built-in-skills/tasks/SKILL.md +2 -2
- package/built-in-skills/tdd/SKILL.md +7 -0
- package/built-in-skills/tdd/references/test-driven-development/GUIDE.md +356 -0
- package/built-in-skills/tdd/references/test-driven-development/LICENSE +21 -0
- package/built-in-skills/tdd/references/test-driven-development/LICENSE.superpowers +21 -0
- package/built-in-skills/tdd/references/test-driven-development/NOTICE.md +37 -0
- package/built-in-skills/team/SKILL.md +1 -1
- package/built-in-skills/web-artifacts-builder/SKILL.md +3 -3
- package/built-in-skills/web-artifacts-builder/scripts/bundle-artifact.sh +9 -7
- package/built-in-skills/web-artifacts-builder/scripts/init-artifact.sh +28 -55
- package/built-in-skills/webapp-qa/LICENSE +21 -0
- package/built-in-skills/webapp-qa/NOTICE.md +37 -0
- package/built-in-skills/webapp-qa/SKILL.md +41 -0
- package/built-in-skills/webapp-qa/references/dogfood/GUIDE.md +161 -0
- package/built-in-skills/webapp-qa/references/issue-taxonomy.md +109 -0
- package/built-in-skills/webapp-qa/templates/dogfood-report-template.md +86 -0
- package/built-in-skills/webapp-testing/SKILL.md +9 -2
- package/built-in-skills/webapp-testing/examples/console_logging.py +10 -4
- package/built-in-skills/webapp-testing/examples/element_discovery.py +11 -4
- package/built-in-skills/webapp-testing/examples/static_html_automation.py +14 -9
- package/built-in-skills/webapp-testing/scripts/with_server.py +34 -10
- package/built-in-skills/weekly-review/LICENSE +21 -0
- package/built-in-skills/weekly-review/NOTICE.md +21 -0
- package/built-in-skills/weekly-review/SKILL.md +49 -0
- package/components/eaas-pi-components.manifest.json +37 -0
- package/dist/cli.cjs +7017 -3340
- package/dist/cli.js +6631 -2936
- package/dist/index.cjs +7863 -3830
- package/dist/index.d.cts +459 -5
- package/dist/index.d.ts +459 -5
- package/dist/index.js +7106 -3064
- package/package.json +7 -2
- package/plugins/memory/prismer/__init__.py +4 -0
- package/plugins/memory/prismer/tool-schemas.generated.json +8 -0
- package/built-in-skills/skill-builder/scripts/ingest.mjs +0 -265
- package/built-in-skills/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
- /package/built-in-skills/{document-generation/SKILL.md → office-artifacts/references/document-generation/GUIDE.md} +0 -0
- /package/built-in-skills/{skill-authoring/skill.json → skill-creator/references/skill-authoring/draft-contract.json} +0 -0
|
@@ -12,9 +12,13 @@ import os
|
|
|
12
12
|
import re
|
|
13
13
|
import subprocess
|
|
14
14
|
import sys
|
|
15
|
+
import tempfile
|
|
15
16
|
from pathlib import Path
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
if __package__:
|
|
19
|
+
from .utils import parse_skill_md
|
|
20
|
+
else:
|
|
21
|
+
from utils import parse_skill_md
|
|
18
22
|
|
|
19
23
|
|
|
20
24
|
def _call_claude(prompt: str, model: str | None, timeout: int = 300) -> str:
|
|
@@ -23,26 +27,20 @@ def _call_claude(prompt: str, model: str | None, timeout: int = 300) -> str:
|
|
|
23
27
|
Prompt goes over stdin (not argv) because it embeds the full SKILL.md
|
|
24
28
|
body and can easily exceed comfortable argv length.
|
|
25
29
|
"""
|
|
26
|
-
|
|
30
|
+
if os.environ.get('PRISMER_ALLOW_PAID_EVAL') != '1':
|
|
31
|
+
raise PermissionError('Set PRISMER_ALLOW_PAID_EVAL=1 after approving evaluation cost')
|
|
32
|
+
cmd = ['claude', '-p', '--output-format', 'text', '--bare', '--tools', '',
|
|
33
|
+
'--strict-mcp-config', '--mcp-config', '{"mcpServers":{}}',
|
|
34
|
+
'--setting-sources', '', '--no-session-persistence', '--max-budget-usd', '0.25']
|
|
27
35
|
if model:
|
|
28
36
|
cmd.extend(["--model", model])
|
|
29
37
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
env = {k: v for k, v in os.environ.items() if k != "CLAUDECODE"}
|
|
34
|
-
|
|
35
|
-
result = subprocess.run(
|
|
36
|
-
cmd,
|
|
37
|
-
input=prompt,
|
|
38
|
-
capture_output=True,
|
|
39
|
-
text=True,
|
|
40
|
-
env=env,
|
|
41
|
-
timeout=timeout,
|
|
42
|
-
)
|
|
38
|
+
with tempfile.TemporaryDirectory(prefix='skill-description-') as directory:
|
|
39
|
+
result = subprocess.run(cmd, input=prompt, capture_output=True, text=True,
|
|
40
|
+
env=dict(os.environ), cwd=directory, timeout=timeout)
|
|
43
41
|
if result.returncode != 0:
|
|
44
42
|
raise RuntimeError(
|
|
45
|
-
f"claude -p exited {result.returncode}
|
|
43
|
+
f"claude -p exited {result.returncode}; evaluation incomplete"
|
|
46
44
|
)
|
|
47
45
|
return result.stdout
|
|
48
46
|
|
|
@@ -3,23 +3,26 @@
|
|
|
3
3
|
Skill Packager - Creates a distributable .skill file of a skill folder
|
|
4
4
|
|
|
5
5
|
Usage:
|
|
6
|
-
python
|
|
6
|
+
python scripts/package_skill.py <path/to/skill-folder> [output-directory]
|
|
7
7
|
|
|
8
8
|
Example:
|
|
9
|
-
python
|
|
10
|
-
python
|
|
9
|
+
python scripts/package_skill.py skills/public/my-skill
|
|
10
|
+
python scripts/package_skill.py skills/public/my-skill ./dist
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
13
|
import fnmatch
|
|
14
14
|
import sys
|
|
15
15
|
import zipfile
|
|
16
16
|
from pathlib import Path
|
|
17
|
-
|
|
17
|
+
if __package__:
|
|
18
|
+
from .quick_validate import validate_skill
|
|
19
|
+
else:
|
|
20
|
+
from quick_validate import validate_skill
|
|
18
21
|
|
|
19
22
|
# Patterns to exclude when packaging skills.
|
|
20
|
-
EXCLUDE_DIRS = {"__pycache__", "node_modules"}
|
|
23
|
+
EXCLUDE_DIRS = {"__pycache__", "node_modules", ".git", ".prismer"}
|
|
21
24
|
EXCLUDE_GLOBS = {"*.pyc"}
|
|
22
|
-
EXCLUDE_FILES = {".DS_Store"}
|
|
25
|
+
EXCLUDE_FILES = {".DS_Store", ".env"}
|
|
23
26
|
# Directories excluded only at the skill root (not when nested deeper).
|
|
24
27
|
ROOT_EXCLUDE_DIRS = {"evals"}
|
|
25
28
|
|
|
@@ -91,6 +94,10 @@ def package_skill(skill_path, output_dir=None):
|
|
|
91
94
|
with zipfile.ZipFile(skill_filename, 'w', zipfile.ZIP_DEFLATED) as zipf:
|
|
92
95
|
# Walk through the skill directory, excluding build artifacts
|
|
93
96
|
for file_path in skill_path.rglob('*'):
|
|
97
|
+
if file_path.is_symlink():
|
|
98
|
+
raise ValueError(f'Symlink is not a portable bundle resource: {file_path}')
|
|
99
|
+
if file_path.resolve() == skill_filename.resolve():
|
|
100
|
+
continue
|
|
94
101
|
if not file_path.is_file():
|
|
95
102
|
continue
|
|
96
103
|
arcname = file_path.relative_to(skill_path.parent)
|
|
@@ -110,10 +117,10 @@ def package_skill(skill_path, output_dir=None):
|
|
|
110
117
|
|
|
111
118
|
def main():
|
|
112
119
|
if len(sys.argv) < 2:
|
|
113
|
-
print("Usage: python
|
|
120
|
+
print("Usage: python scripts/package_skill.py <path/to/skill-folder> [output-directory]")
|
|
114
121
|
print("\nExample:")
|
|
115
|
-
print(" python
|
|
116
|
-
print(" python
|
|
122
|
+
print(" python scripts/package_skill.py skills/public/my-skill")
|
|
123
|
+
print(" python scripts/package_skill.py skills/public/my-skill ./dist")
|
|
117
124
|
sys.exit(1)
|
|
118
125
|
|
|
119
126
|
skill_path = sys.argv[1]
|
|
@@ -19,12 +19,12 @@ def validate_skill(skill_path):
|
|
|
19
19
|
return False, "SKILL.md not found"
|
|
20
20
|
|
|
21
21
|
# Read and validate frontmatter
|
|
22
|
-
content = skill_md.read_text()
|
|
22
|
+
content = skill_md.read_text(encoding='utf-8')
|
|
23
23
|
if not content.startswith('---'):
|
|
24
24
|
return False, "No YAML frontmatter found"
|
|
25
25
|
|
|
26
26
|
# Extract frontmatter
|
|
27
|
-
match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
|
|
27
|
+
match = re.match(r'^---\n(.*?)\n---(?:\n|$)', content, re.DOTALL)
|
|
28
28
|
if not match:
|
|
29
29
|
return False, "Invalid frontmatter format"
|
|
30
30
|
|
|
@@ -39,7 +39,11 @@ def validate_skill(skill_path):
|
|
|
39
39
|
return False, f"Invalid YAML in frontmatter: {e}"
|
|
40
40
|
|
|
41
41
|
# Define allowed properties
|
|
42
|
-
ALLOWED_PROPERTIES = {'name', 'description', 'license', 'allowed-tools', 'metadata',
|
|
42
|
+
ALLOWED_PROPERTIES = {'name', 'description', 'license', 'allowed-tools', 'metadata',
|
|
43
|
+
'compatibility', 'scope', 'category', 'config', 'version',
|
|
44
|
+
'author', 'platforms', 'prerequisites', 'source', 'applies_to',
|
|
45
|
+
'tags', 'triggers', 'phaseModel', 'requires', 'aliases',
|
|
46
|
+
'role_scope', 'required_credential_files'}
|
|
43
47
|
|
|
44
48
|
# Check for unexpected properties (excluding nested keys under metadata)
|
|
45
49
|
unexpected_keys = set(frontmatter.keys()) - ALLOWED_PROPERTIES
|
|
@@ -60,6 +64,8 @@ def validate_skill(skill_path):
|
|
|
60
64
|
if not isinstance(name, str):
|
|
61
65
|
return False, f"Name must be a string, got {type(name).__name__}"
|
|
62
66
|
name = name.strip()
|
|
67
|
+
if not name:
|
|
68
|
+
return False, "Name must not be empty"
|
|
63
69
|
if name:
|
|
64
70
|
# Check naming convention (kebab-case: lowercase with hyphens)
|
|
65
71
|
if not re.match(r'^[a-z0-9-]+$', name):
|
|
@@ -75,6 +81,8 @@ def validate_skill(skill_path):
|
|
|
75
81
|
if not isinstance(description, str):
|
|
76
82
|
return False, f"Description must be a string, got {type(description).__name__}"
|
|
77
83
|
description = description.strip()
|
|
84
|
+
if not description:
|
|
85
|
+
return False, "Description must not be empty"
|
|
78
86
|
if description:
|
|
79
87
|
# Check for angle brackets
|
|
80
88
|
if '<' in description or '>' in description:
|
|
@@ -86,11 +94,20 @@ def validate_skill(skill_path):
|
|
|
86
94
|
# Validate compatibility field if present (optional)
|
|
87
95
|
compatibility = frontmatter.get('compatibility', '')
|
|
88
96
|
if compatibility:
|
|
97
|
+
if isinstance(compatibility, list):
|
|
98
|
+
if not all(isinstance(item, str) and item.strip() for item in compatibility):
|
|
99
|
+
return False, "Compatibility list must contain non-empty strings"
|
|
100
|
+
compatibility = ', '.join(compatibility)
|
|
89
101
|
if not isinstance(compatibility, str):
|
|
90
|
-
return False,
|
|
102
|
+
return False, "Compatibility must be a string or list of strings"
|
|
91
103
|
if len(compatibility) > 500:
|
|
92
104
|
return False, f"Compatibility is too long ({len(compatibility)} characters). Maximum is 500 characters."
|
|
93
105
|
|
|
106
|
+
for key in ('metadata', 'config'):
|
|
107
|
+
if key in frontmatter and not isinstance(frontmatter[key], dict):
|
|
108
|
+
return False, f"{key} must be a mapping"
|
|
109
|
+
if not content[match.end():].strip():
|
|
110
|
+
return False, "Skill body must not be empty"
|
|
94
111
|
return True, "Skill is valid!"
|
|
95
112
|
|
|
96
113
|
if __name__ == "__main__":
|
|
@@ -100,4 +117,4 @@ if __name__ == "__main__":
|
|
|
100
117
|
|
|
101
118
|
valid, message = validate_skill(sys.argv[1])
|
|
102
119
|
print(message)
|
|
103
|
-
sys.exit(0 if valid else 1)
|
|
120
|
+
sys.exit(0 if valid else 1)
|
|
@@ -8,6 +8,8 @@ for a set of queries. Outputs results as JSON.
|
|
|
8
8
|
import argparse
|
|
9
9
|
import json
|
|
10
10
|
import os
|
|
11
|
+
import re
|
|
12
|
+
import tempfile
|
|
11
13
|
import select
|
|
12
14
|
import subprocess
|
|
13
15
|
import sys
|
|
@@ -16,7 +18,10 @@ import uuid
|
|
|
16
18
|
from concurrent.futures import ProcessPoolExecutor, as_completed
|
|
17
19
|
from pathlib import Path
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
if __package__:
|
|
22
|
+
from .utils import parse_skill_md
|
|
23
|
+
else:
|
|
24
|
+
from utils import parse_skill_md
|
|
20
25
|
|
|
21
26
|
|
|
22
27
|
def find_project_root() -> Path:
|
|
@@ -33,153 +38,60 @@ def find_project_root() -> Path:
|
|
|
33
38
|
|
|
34
39
|
|
|
35
40
|
def run_single_query(
|
|
36
|
-
query: str,
|
|
37
|
-
|
|
38
|
-
skill_description: str,
|
|
39
|
-
timeout: int,
|
|
40
|
-
project_root: str,
|
|
41
|
-
model: str | None = None,
|
|
41
|
+
query: str, skill_name: str, skill_description: str, timeout: int,
|
|
42
|
+
project_root: str, model: str | None = None,
|
|
42
43
|
) -> bool:
|
|
43
|
-
"""
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
""
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
indented_desc = "\n ".join(skill_description.split("\n"))
|
|
60
|
-
command_content = (
|
|
61
|
-
f"---\n"
|
|
62
|
-
f"description: |\n"
|
|
63
|
-
f" {indented_desc}\n"
|
|
64
|
-
f"---\n\n"
|
|
65
|
-
f"# {skill_name}\n\n"
|
|
66
|
-
f"This skill handles: {skill_description}\n"
|
|
44
|
+
"""Evaluate only a temporary probe skill; never write into the user's repo."""
|
|
45
|
+
if os.environ.get("PRISMER_ALLOW_PAID_EVAL") != "1":
|
|
46
|
+
raise PermissionError("Set PRISMER_ALLOW_PAID_EVAL=1 after approving evaluation cost")
|
|
47
|
+
if not re.fullmatch(r"[a-z0-9]+(?:-[a-z0-9]+)*", skill_name):
|
|
48
|
+
raise ValueError("Unsafe skill name")
|
|
49
|
+
if timeout <= 0:
|
|
50
|
+
raise ValueError("timeout must be positive")
|
|
51
|
+
clean_name = f"{skill_name}-skill-{uuid.uuid4().hex[:8]}"
|
|
52
|
+
with tempfile.TemporaryDirectory(prefix="skill-trigger-") as directory:
|
|
53
|
+
skill_dir = Path(directory) / ".claude" / "skills" / clean_name
|
|
54
|
+
skill_dir.mkdir(parents=True)
|
|
55
|
+
description = "\\n ".join(skill_description.splitlines())
|
|
56
|
+
(skill_dir / "SKILL.md").write_text(
|
|
57
|
+
f"---\\nname: {clean_name}\\ndescription: |\\n {description}\\n---\\n"
|
|
58
|
+
"Report that this probe skill was selected. Do not execute any other action.\\n",
|
|
59
|
+
encoding="utf-8",
|
|
67
60
|
)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
"--output-format", "stream-json",
|
|
74
|
-
"--verbose",
|
|
75
|
-
"--include-partial-messages",
|
|
76
|
-
]
|
|
61
|
+
cmd = ["claude", "-p", query, "--output-format", "stream-json", "--verbose",
|
|
62
|
+
"--bare", "--tools", "Read,Skill", "--allowedTools", "Read,Skill",
|
|
63
|
+
"--permission-mode", "dontAsk", "--strict-mcp-config",
|
|
64
|
+
"--mcp-config", '{"mcpServers":{}}', "--setting-sources", "",
|
|
65
|
+
"--no-session-persistence", "--max-budget-usd", "0.25"]
|
|
77
66
|
if model:
|
|
78
67
|
cmd.extend(["--model", model])
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
triggered = False
|
|
94
|
-
start_time = time.time()
|
|
95
|
-
buffer = ""
|
|
96
|
-
# Track state for stream event detection
|
|
97
|
-
pending_tool_name = None
|
|
98
|
-
accumulated_json = ""
|
|
99
|
-
|
|
100
|
-
try:
|
|
101
|
-
while time.time() - start_time < timeout:
|
|
102
|
-
if process.poll() is not None:
|
|
103
|
-
remaining = process.stdout.read()
|
|
104
|
-
if remaining:
|
|
105
|
-
buffer += remaining.decode("utf-8", errors="replace")
|
|
106
|
-
break
|
|
107
|
-
|
|
108
|
-
ready, _, _ = select.select([process.stdout], [], [], 1.0)
|
|
109
|
-
if not ready:
|
|
110
|
-
continue
|
|
111
|
-
|
|
112
|
-
chunk = os.read(process.stdout.fileno(), 8192)
|
|
113
|
-
if not chunk:
|
|
114
|
-
break
|
|
115
|
-
buffer += chunk.decode("utf-8", errors="replace")
|
|
116
|
-
|
|
117
|
-
while "\n" in buffer:
|
|
118
|
-
line, buffer = buffer.split("\n", 1)
|
|
119
|
-
line = line.strip()
|
|
120
|
-
if not line:
|
|
121
|
-
continue
|
|
122
|
-
|
|
123
|
-
try:
|
|
124
|
-
event = json.loads(line)
|
|
125
|
-
except json.JSONDecodeError:
|
|
68
|
+
# communicate drains both pipes; errors are never scored as negatives.
|
|
69
|
+
completed = subprocess.run(cmd, cwd=directory, env=dict(os.environ),
|
|
70
|
+
capture_output=True, text=True, timeout=timeout)
|
|
71
|
+
if completed.returncode:
|
|
72
|
+
raise RuntimeError(f"Claude evaluation exited {completed.returncode}")
|
|
73
|
+
triggered, finished = False, False
|
|
74
|
+
for line in completed.stdout.splitlines():
|
|
75
|
+
try:
|
|
76
|
+
event = json.loads(line)
|
|
77
|
+
except json.JSONDecodeError:
|
|
78
|
+
continue
|
|
79
|
+
if event.get("type") == "assistant":
|
|
80
|
+
for block in event.get("message", {}).get("content", []):
|
|
81
|
+
if block.get("type") != "tool_use":
|
|
126
82
|
continue
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
pending_tool_name = tool_name
|
|
139
|
-
accumulated_json = ""
|
|
140
|
-
else:
|
|
141
|
-
return False
|
|
142
|
-
|
|
143
|
-
elif se_type == "content_block_delta" and pending_tool_name:
|
|
144
|
-
delta = se.get("delta", {})
|
|
145
|
-
if delta.get("type") == "input_json_delta":
|
|
146
|
-
accumulated_json += delta.get("partial_json", "")
|
|
147
|
-
if clean_name in accumulated_json:
|
|
148
|
-
return True
|
|
149
|
-
|
|
150
|
-
elif se_type in ("content_block_stop", "message_stop"):
|
|
151
|
-
if pending_tool_name:
|
|
152
|
-
return clean_name in accumulated_json
|
|
153
|
-
if se_type == "message_stop":
|
|
154
|
-
return False
|
|
155
|
-
|
|
156
|
-
# Fallback: full assistant message
|
|
157
|
-
elif event.get("type") == "assistant":
|
|
158
|
-
message = event.get("message", {})
|
|
159
|
-
for content_item in message.get("content", []):
|
|
160
|
-
if content_item.get("type") != "tool_use":
|
|
161
|
-
continue
|
|
162
|
-
tool_name = content_item.get("name", "")
|
|
163
|
-
tool_input = content_item.get("input", {})
|
|
164
|
-
if tool_name == "Skill" and clean_name in tool_input.get("skill", ""):
|
|
165
|
-
triggered = True
|
|
166
|
-
elif tool_name == "Read" and clean_name in tool_input.get("file_path", ""):
|
|
167
|
-
triggered = True
|
|
168
|
-
return triggered
|
|
169
|
-
|
|
170
|
-
elif event.get("type") == "result":
|
|
171
|
-
return triggered
|
|
172
|
-
finally:
|
|
173
|
-
# Clean up process on any exit path (return, exception, timeout)
|
|
174
|
-
if process.poll() is None:
|
|
175
|
-
process.kill()
|
|
176
|
-
process.wait()
|
|
177
|
-
|
|
83
|
+
args = block.get("input", {})
|
|
84
|
+
if block.get("name") == "Skill":
|
|
85
|
+
triggered |= clean_name in args.get("skill", "")
|
|
86
|
+
elif block.get("name") == "Read":
|
|
87
|
+
triggered |= clean_name in args.get("file_path", "")
|
|
88
|
+
elif event.get("type") == "result":
|
|
89
|
+
if event.get("is_error") or event.get("subtype") not in (None, "success"):
|
|
90
|
+
raise RuntimeError("Claude evaluation returned an error result")
|
|
91
|
+
finished = True
|
|
92
|
+
if not finished:
|
|
93
|
+
raise RuntimeError("Claude evaluation produced no successful terminal result")
|
|
178
94
|
return triggered
|
|
179
|
-
finally:
|
|
180
|
-
if command_file.exists():
|
|
181
|
-
command_file.unlink()
|
|
182
|
-
|
|
183
95
|
|
|
184
96
|
def run_eval(
|
|
185
97
|
eval_set: list[dict],
|
|
@@ -193,6 +105,14 @@ def run_eval(
|
|
|
193
105
|
model: str | None = None,
|
|
194
106
|
) -> dict:
|
|
195
107
|
"""Run the full eval set and return results."""
|
|
108
|
+
if not eval_set or num_workers < 1 or runs_per_query < 1 or timeout <= 0:
|
|
109
|
+
raise ValueError('Non-empty eval set and positive workers/runs/timeout required')
|
|
110
|
+
if not 0 < trigger_threshold <= 1:
|
|
111
|
+
raise ValueError('trigger_threshold must be in (0, 1]')
|
|
112
|
+
if len({item['query'] for item in eval_set}) != len(eval_set):
|
|
113
|
+
raise ValueError('Duplicate queries make train/test membership ambiguous')
|
|
114
|
+
if len(eval_set) * runs_per_query > 300 or num_workers > 10:
|
|
115
|
+
raise ValueError('Evaluation exceeds 300-call or 10-worker safety budget')
|
|
196
116
|
results = []
|
|
197
117
|
|
|
198
118
|
with ProcessPoolExecutor(max_workers=num_workers) as executor:
|
|
@@ -221,8 +141,7 @@ def run_eval(
|
|
|
221
141
|
try:
|
|
222
142
|
query_triggers[query].append(future.result())
|
|
223
143
|
except Exception as e:
|
|
224
|
-
|
|
225
|
-
query_triggers[query].append(False)
|
|
144
|
+
raise RuntimeError('Evaluation incomplete; failed calls cannot count as negative triggers') from e
|
|
226
145
|
|
|
227
146
|
for query, triggers in query_triggers.items():
|
|
228
147
|
item = query_items[query]
|
|
@@ -15,27 +15,37 @@ import time
|
|
|
15
15
|
import webbrowser
|
|
16
16
|
from pathlib import Path
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
from
|
|
20
|
-
from
|
|
21
|
-
from
|
|
18
|
+
if __package__:
|
|
19
|
+
from .generate_report import generate_html
|
|
20
|
+
from .improve_description import improve_description
|
|
21
|
+
from .run_eval import find_project_root, run_eval
|
|
22
|
+
from .utils import parse_skill_md
|
|
23
|
+
else:
|
|
24
|
+
from generate_report import generate_html
|
|
25
|
+
from improve_description import improve_description
|
|
26
|
+
from run_eval import find_project_root, run_eval
|
|
27
|
+
from utils import parse_skill_md
|
|
22
28
|
|
|
23
29
|
|
|
24
30
|
def split_eval_set(eval_set: list[dict], holdout: float, seed: int = 42) -> tuple[list[dict], list[dict]]:
|
|
25
31
|
"""Split eval set into train and test sets, stratified by should_trigger."""
|
|
26
|
-
random.
|
|
32
|
+
rng = random.Random(seed)
|
|
33
|
+
if not 0 < holdout < 1:
|
|
34
|
+
raise ValueError('holdout must be between 0 and 1')
|
|
27
35
|
|
|
28
36
|
# Separate by should_trigger
|
|
29
37
|
trigger = [e for e in eval_set if e["should_trigger"]]
|
|
30
38
|
no_trigger = [e for e in eval_set if not e["should_trigger"]]
|
|
31
39
|
|
|
32
40
|
# Shuffle each group
|
|
33
|
-
|
|
34
|
-
|
|
41
|
+
if len(trigger) < 2 or len(no_trigger) < 2:
|
|
42
|
+
raise ValueError('Stratified holdout needs at least two positive and two negative queries')
|
|
43
|
+
rng.shuffle(trigger)
|
|
44
|
+
rng.shuffle(no_trigger)
|
|
35
45
|
|
|
36
46
|
# Calculate split points
|
|
37
|
-
n_trigger_test = max(1, int(len(trigger) * holdout))
|
|
38
|
-
n_no_trigger_test = max(1, int(len(no_trigger) * holdout))
|
|
47
|
+
n_trigger_test = min(len(trigger) - 1, max(1, int(len(trigger) * holdout)))
|
|
48
|
+
n_no_trigger_test = min(len(no_trigger) - 1, max(1, int(len(no_trigger) * holdout)))
|
|
39
49
|
|
|
40
50
|
# Split
|
|
41
51
|
test_set = trigger[:n_trigger_test] + no_trigger[:n_no_trigger_test]
|
|
@@ -60,6 +70,8 @@ def run_loop(
|
|
|
60
70
|
log_dir: Path | None = None,
|
|
61
71
|
) -> dict:
|
|
62
72
|
"""Run the eval + improvement loop."""
|
|
73
|
+
if max_iterations < 1 or not 0 <= holdout < 1:
|
|
74
|
+
raise ValueError('Positive max_iterations and holdout in [0, 1) required')
|
|
63
75
|
project_root = find_project_root()
|
|
64
76
|
name, original_description, content = parse_skill_md(skill_path)
|
|
65
77
|
current_description = description_override or original_description
|
|
@@ -213,13 +225,9 @@ def run_loop(
|
|
|
213
225
|
|
|
214
226
|
current_description = new_description
|
|
215
227
|
|
|
216
|
-
#
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
best_score = f"{best['test_passed']}/{best['test_total']}"
|
|
220
|
-
else:
|
|
221
|
-
best = max(history, key=lambda h: h["train_passed"])
|
|
222
|
-
best_score = f"{best['train_passed']}/{best['train_total']}"
|
|
228
|
+
# Selection cannot use holdout scores; improvement also receives train only.
|
|
229
|
+
best = max(history, key=lambda h: h['train_passed'])
|
|
230
|
+
best_score = f"{best['train_passed']}/{best['train_total']}"
|
|
223
231
|
|
|
224
232
|
if verbose:
|
|
225
233
|
print(f"\nExit reason: {exit_reason}", file=sys.stderr)
|
|
@@ -29,7 +29,10 @@ class GIFBuilder:
|
|
|
29
29
|
self.width = width
|
|
30
30
|
self.height = height
|
|
31
31
|
self.fps = fps
|
|
32
|
+
if fps <= 0 or width <= 0 or height <= 0:
|
|
33
|
+
raise ValueError('Dimensions and fps must be positive')
|
|
32
34
|
self.frames: list[np.ndarray] = []
|
|
35
|
+
self._frame_ticks: list[int] = []
|
|
33
36
|
|
|
34
37
|
def add_frame(self, frame: np.ndarray | Image.Image):
|
|
35
38
|
"""
|
|
@@ -50,6 +53,7 @@ class GIFBuilder:
|
|
|
50
53
|
frame = np.array(pil_frame)
|
|
51
54
|
|
|
52
55
|
self.frames.append(frame)
|
|
56
|
+
self._frame_ticks.append(1)
|
|
53
57
|
|
|
54
58
|
def add_frames(self, frames: list[np.ndarray | Image.Image]):
|
|
55
59
|
"""Add multiple frames at once."""
|
|
@@ -136,6 +140,7 @@ class GIFBuilder:
|
|
|
136
140
|
return 0
|
|
137
141
|
|
|
138
142
|
deduplicated = [self.frames[0]]
|
|
143
|
+
ticks = [self._frame_ticks[0]]
|
|
139
144
|
removed_count = 0
|
|
140
145
|
|
|
141
146
|
for i in range(1, len(self.frames)):
|
|
@@ -151,10 +156,13 @@ class GIFBuilder:
|
|
|
151
156
|
# High threshold (0.9995+) means only remove nearly identical frames
|
|
152
157
|
if similarity < threshold:
|
|
153
158
|
deduplicated.append(self.frames[i])
|
|
159
|
+
ticks.append(self._frame_ticks[i])
|
|
154
160
|
else:
|
|
161
|
+
ticks[-1] += self._frame_ticks[i]
|
|
155
162
|
removed_count += 1
|
|
156
163
|
|
|
157
164
|
self.frames = deduplicated
|
|
165
|
+
self._frame_ticks = ticks
|
|
158
166
|
return removed_count
|
|
159
167
|
|
|
160
168
|
def save(
|
|
@@ -213,6 +221,8 @@ class GIFBuilder:
|
|
|
213
221
|
)
|
|
214
222
|
# Keep every nth frame to get close to 12 frames
|
|
215
223
|
keep_every = max(1, len(self.frames) // 12)
|
|
224
|
+
self._frame_ticks = [sum(self._frame_ticks[i:i + keep_every])
|
|
225
|
+
for i in range(0, len(self.frames), keep_every)]
|
|
216
226
|
self.frames = [
|
|
217
227
|
self.frames[i] for i in range(0, len(self.frames), keep_every)
|
|
218
228
|
]
|
|
@@ -221,7 +231,7 @@ class GIFBuilder:
|
|
|
221
231
|
optimized_frames = self.optimize_colors(num_colors, use_global_palette=True)
|
|
222
232
|
|
|
223
233
|
# Calculate frame duration in milliseconds
|
|
224
|
-
frame_duration = 1000 / self.fps
|
|
234
|
+
frame_duration = [1000 * ticks / self.fps for ticks in self._frame_ticks]
|
|
225
235
|
|
|
226
236
|
# Save GIF
|
|
227
237
|
imageio.imwrite(
|
|
@@ -242,7 +252,7 @@ class GIFBuilder:
|
|
|
242
252
|
"dimensions": f"{self.width}x{self.height}",
|
|
243
253
|
"frame_count": len(optimized_frames),
|
|
244
254
|
"fps": self.fps,
|
|
245
|
-
"duration_seconds":
|
|
255
|
+
"duration_seconds": sum(self._frame_ticks) / self.fps,
|
|
246
256
|
"colors": num_colors,
|
|
247
257
|
}
|
|
248
258
|
|
|
@@ -267,3 +277,4 @@ class GIFBuilder:
|
|
|
267
277
|
def clear(self):
|
|
268
278
|
"""Clear all frames (useful for creating multiple GIFs)."""
|
|
269
279
|
self.frames = []
|
|
280
|
+
self._frame_ticks = []
|
|
@@ -9,7 +9,8 @@ from pathlib import Path
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def validate_gif(
|
|
12
|
-
gif_path: str | Path, is_emoji: bool = True, verbose: bool = True
|
|
12
|
+
gif_path: str | Path, is_emoji: bool = True, verbose: bool = True,
|
|
13
|
+
max_bytes: int = 5 * 1024 * 1024,
|
|
13
14
|
) -> tuple[bool, dict]:
|
|
14
15
|
"""
|
|
15
16
|
Validate GIF for Slack (dimensions, size, frame count).
|
|
@@ -25,6 +26,8 @@ def validate_gif(
|
|
|
25
26
|
from PIL import Image
|
|
26
27
|
|
|
27
28
|
gif_path = Path(gif_path)
|
|
29
|
+
if max_bytes <= 0:
|
|
30
|
+
raise ValueError('max_bytes must be positive')
|
|
28
31
|
|
|
29
32
|
if not gif_path.exists():
|
|
30
33
|
return False, {"error": f"File not found: {gif_path}"}
|
|
@@ -37,21 +40,25 @@ def validate_gif(
|
|
|
37
40
|
# Get dimensions and frame info
|
|
38
41
|
try:
|
|
39
42
|
with Image.open(gif_path) as img:
|
|
43
|
+
if img.format != 'GIF':
|
|
44
|
+
return False, {'error': 'Input must be a GIF, not ' + str(img.format)}
|
|
40
45
|
width, height = img.size
|
|
41
46
|
|
|
42
47
|
# Count frames
|
|
43
48
|
frame_count = 0
|
|
49
|
+
duration_ms = 0
|
|
44
50
|
try:
|
|
45
51
|
while True:
|
|
46
52
|
img.seek(frame_count)
|
|
53
|
+
img.load()
|
|
54
|
+
duration_ms += img.info.get('duration', 0)
|
|
47
55
|
frame_count += 1
|
|
48
56
|
except EOFError:
|
|
49
57
|
pass
|
|
50
58
|
|
|
51
59
|
# Get duration
|
|
52
60
|
try:
|
|
53
|
-
|
|
54
|
-
total_duration = (duration_ms * frame_count) / 1000
|
|
61
|
+
total_duration = duration_ms / 1000
|
|
55
62
|
fps = frame_count / total_duration if total_duration > 0 else 0
|
|
56
63
|
except:
|
|
57
64
|
total_duration = None
|
|
@@ -73,9 +80,12 @@ def validate_gif(
|
|
|
73
80
|
)
|
|
74
81
|
dim_pass = aspect_ratio <= 2.0 and 320 <= min(width, height) <= 640
|
|
75
82
|
|
|
83
|
+
passes = dim_pass and size_bytes <= max_bytes and frame_count > 0
|
|
76
84
|
results = {
|
|
77
85
|
"file": str(gif_path),
|
|
78
|
-
"passes":
|
|
86
|
+
"passes": passes,
|
|
87
|
+
"size_pass": size_bytes <= max_bytes,
|
|
88
|
+
"max_bytes": max_bytes,
|
|
79
89
|
"width": width,
|
|
80
90
|
"height": height,
|
|
81
91
|
"size_kb": size_kb,
|
|
@@ -112,10 +122,10 @@ def validate_gif(
|
|
|
112
122
|
f" Note: {'Emoji should be 128x128' if is_emoji else 'Unusual dimensions for Slack'}"
|
|
113
123
|
)
|
|
114
124
|
|
|
115
|
-
if
|
|
116
|
-
print(f"
|
|
125
|
+
if size_bytes > max_bytes:
|
|
126
|
+
print(f" Failed: exceeds configured size budget ({max_bytes} bytes)")
|
|
117
127
|
|
|
118
|
-
return
|
|
128
|
+
return passes, results
|
|
119
129
|
|
|
120
130
|
|
|
121
131
|
def is_slack_ready(
|