@bastani/atomic 0.5.11 → 0.5.12-1
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/.agents/skills/adapt/SKILL.md +199 -0
- package/.agents/skills/advanced-evaluation/SKILL.md +402 -0
- package/.agents/skills/advanced-evaluation/references/bias-mitigation.md +288 -0
- package/.agents/skills/advanced-evaluation/references/evaluation-pipeline.md +43 -0
- package/.agents/skills/advanced-evaluation/references/implementation-patterns.md +315 -0
- package/.agents/skills/advanced-evaluation/references/metrics-guide.md +331 -0
- package/.agents/skills/advanced-evaluation/scripts/evaluation_example.py +392 -0
- package/.agents/skills/animate/SKILL.md +175 -0
- package/.agents/skills/arrange/SKILL.md +124 -0
- package/.agents/skills/audit/SKILL.md +148 -0
- package/.agents/skills/bdi-mental-states/SKILL.md +311 -0
- package/.agents/skills/bdi-mental-states/references/bdi-ontology-core.md +207 -0
- package/.agents/skills/bdi-mental-states/references/framework-integration.md +582 -0
- package/.agents/skills/bdi-mental-states/references/rdf-examples.md +315 -0
- package/.agents/skills/bdi-mental-states/references/sparql-competency.md +420 -0
- package/.agents/skills/bolder/SKILL.md +117 -0
- package/.agents/skills/bun/SKILL.md +199 -0
- package/.agents/skills/clarify/SKILL.md +183 -0
- package/.agents/skills/colorize/SKILL.md +143 -0
- package/.agents/skills/context-compression/SKILL.md +272 -0
- package/.agents/skills/context-compression/references/evaluation-framework.md +213 -0
- package/.agents/skills/context-compression/scripts/compression_evaluator.py +862 -0
- package/.agents/skills/context-compression/tests/test_compression_evaluator.py +56 -0
- package/.agents/skills/context-degradation/SKILL.md +206 -0
- package/.agents/skills/context-degradation/references/patterns.md +314 -0
- package/.agents/skills/context-degradation/scripts/degradation_detector.py +614 -0
- package/.agents/skills/context-fundamentals/SKILL.md +201 -0
- package/.agents/skills/context-fundamentals/references/context-components.md +283 -0
- package/.agents/skills/context-fundamentals/scripts/context_manager.py +533 -0
- package/.agents/skills/context-optimization/SKILL.md +195 -0
- package/.agents/skills/context-optimization/references/optimization_techniques.md +272 -0
- package/.agents/skills/context-optimization/scripts/compaction.py +562 -0
- package/.agents/skills/create-spec/SKILL.md +244 -0
- package/.agents/skills/critique/SKILL.md +225 -0
- package/.agents/skills/critique/reference/cognitive-load.md +106 -0
- package/.agents/skills/critique/reference/heuristics-scoring.md +234 -0
- package/.agents/skills/critique/reference/personas.md +178 -0
- package/.agents/skills/delight/SKILL.md +304 -0
- package/.agents/skills/distill/SKILL.md +122 -0
- package/.agents/skills/docx/LICENSE.txt +30 -0
- package/.agents/skills/docx/SKILL.md +590 -0
- package/.agents/skills/docx/scripts/__init__.py +1 -0
- package/.agents/skills/docx/scripts/accept_changes.py +135 -0
- package/.agents/skills/docx/scripts/comment.py +318 -0
- package/.agents/skills/docx/scripts/office/helpers/__init__.py +0 -0
- package/.agents/skills/docx/scripts/office/helpers/merge_runs.py +199 -0
- package/.agents/skills/docx/scripts/office/helpers/simplify_redlines.py +197 -0
- package/.agents/skills/docx/scripts/office/pack.py +159 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/.agents/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/.agents/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/.agents/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/.agents/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/.agents/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/.agents/skills/docx/scripts/office/schemas/mce/mc.xsd +75 -0
- package/.agents/skills/docx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
- package/.agents/skills/docx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
- package/.agents/skills/docx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
- package/.agents/skills/docx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/.agents/skills/docx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/.agents/skills/docx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/.agents/skills/docx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/.agents/skills/docx/scripts/office/soffice.py +183 -0
- package/.agents/skills/docx/scripts/office/unpack.py +132 -0
- package/.agents/skills/docx/scripts/office/validate.py +111 -0
- package/.agents/skills/docx/scripts/office/validators/__init__.py +15 -0
- package/.agents/skills/docx/scripts/office/validators/base.py +847 -0
- package/.agents/skills/docx/scripts/office/validators/docx.py +446 -0
- package/.agents/skills/docx/scripts/office/validators/pptx.py +275 -0
- package/.agents/skills/docx/scripts/office/validators/redlining.py +247 -0
- package/.agents/skills/docx/scripts/templates/comments.xml +3 -0
- package/.agents/skills/docx/scripts/templates/commentsExtended.xml +3 -0
- package/.agents/skills/docx/scripts/templates/commentsExtensible.xml +3 -0
- package/.agents/skills/docx/scripts/templates/commentsIds.xml +3 -0
- package/.agents/skills/docx/scripts/templates/people.xml +3 -0
- package/.agents/skills/evaluation/SKILL.md +251 -0
- package/.agents/skills/evaluation/references/metrics.md +339 -0
- package/.agents/skills/evaluation/scripts/evaluator.py +627 -0
- package/.agents/skills/explain-code/SKILL.md +230 -0
- package/.agents/skills/extract/SKILL.md +91 -0
- package/.agents/skills/filesystem-context/SKILL.md +287 -0
- package/.agents/skills/filesystem-context/references/implementation-patterns.md +549 -0
- package/.agents/skills/filesystem-context/scripts/filesystem_context.py +425 -0
- package/.agents/skills/find-skills/SKILL.md +142 -0
- package/.agents/skills/frontend-design/SKILL.md +147 -0
- package/.agents/skills/frontend-design/reference/color-and-contrast.md +132 -0
- package/.agents/skills/frontend-design/reference/interaction-design.md +195 -0
- package/.agents/skills/frontend-design/reference/motion-design.md +99 -0
- package/.agents/skills/frontend-design/reference/responsive-design.md +114 -0
- package/.agents/skills/frontend-design/reference/spatial-design.md +100 -0
- package/.agents/skills/frontend-design/reference/typography.md +133 -0
- package/.agents/skills/frontend-design/reference/ux-writing.md +107 -0
- package/.agents/skills/gh-commit/SKILL.md +243 -0
- package/.agents/skills/gh-create-pr/SKILL.md +93 -0
- package/.agents/skills/harden/SKILL.md +354 -0
- package/.agents/skills/hosted-agents/SKILL.md +260 -0
- package/.agents/skills/hosted-agents/references/infrastructure-patterns.md +700 -0
- package/.agents/skills/hosted-agents/scripts/sandbox_manager.py +590 -0
- package/.agents/skills/impeccable/SKILL.md +365 -0
- package/.agents/skills/impeccable/reference/color-and-contrast.md +105 -0
- package/.agents/skills/impeccable/reference/craft.md +70 -0
- package/.agents/skills/impeccable/reference/extract.md +70 -0
- package/.agents/skills/impeccable/reference/interaction-design.md +195 -0
- package/.agents/skills/impeccable/reference/motion-design.md +99 -0
- package/.agents/skills/impeccable/reference/responsive-design.md +114 -0
- package/.agents/skills/impeccable/reference/spatial-design.md +100 -0
- package/.agents/skills/impeccable/reference/typography.md +142 -0
- package/.agents/skills/impeccable/reference/ux-writing.md +107 -0
- package/.agents/skills/impeccable/scripts/cleanup-deprecated.mjs +214 -0
- package/.agents/skills/init/SKILL.md +138 -0
- package/.agents/skills/layout/SKILL.md +125 -0
- package/.agents/skills/liteparse/SKILL.md +222 -0
- package/.agents/skills/memory-systems/SKILL.md +219 -0
- package/.agents/skills/memory-systems/references/implementation.md +551 -0
- package/.agents/skills/memory-systems/scripts/memory_store.py +616 -0
- package/.agents/skills/multi-agent-patterns/SKILL.md +257 -0
- package/.agents/skills/multi-agent-patterns/references/frameworks.md +433 -0
- package/.agents/skills/multi-agent-patterns/scripts/coordination.py +613 -0
- package/.agents/skills/normalize/SKILL.md +70 -0
- package/.agents/skills/onboard/SKILL.md +245 -0
- package/.agents/skills/opentui/SKILL.md +201 -0
- package/.agents/skills/opentui/references/animation/REFERENCE.md +431 -0
- package/.agents/skills/opentui/references/components/REFERENCE.md +144 -0
- package/.agents/skills/opentui/references/components/code-diff.md +672 -0
- package/.agents/skills/opentui/references/components/containers.md +417 -0
- package/.agents/skills/opentui/references/components/inputs.md +531 -0
- package/.agents/skills/opentui/references/components/text-display.md +386 -0
- package/.agents/skills/opentui/references/core/REFERENCE.md +145 -0
- package/.agents/skills/opentui/references/core/api.md +543 -0
- package/.agents/skills/opentui/references/core/configuration.md +168 -0
- package/.agents/skills/opentui/references/core/gotchas.md +393 -0
- package/.agents/skills/opentui/references/core/patterns.md +449 -0
- package/.agents/skills/opentui/references/keyboard/REFERENCE.md +617 -0
- package/.agents/skills/opentui/references/layout/REFERENCE.md +337 -0
- package/.agents/skills/opentui/references/layout/patterns.md +444 -0
- package/.agents/skills/opentui/references/react/REFERENCE.md +174 -0
- package/.agents/skills/opentui/references/react/api.md +436 -0
- package/.agents/skills/opentui/references/react/configuration.md +302 -0
- package/.agents/skills/opentui/references/react/gotchas.md +443 -0
- package/.agents/skills/opentui/references/react/patterns.md +501 -0
- package/.agents/skills/opentui/references/solid/REFERENCE.md +201 -0
- package/.agents/skills/opentui/references/solid/api.md +564 -0
- package/.agents/skills/opentui/references/solid/configuration.md +316 -0
- package/.agents/skills/opentui/references/solid/gotchas.md +427 -0
- package/.agents/skills/opentui/references/solid/patterns.md +560 -0
- package/.agents/skills/opentui/references/testing/REFERENCE.md +614 -0
- package/.agents/skills/optimize/SKILL.md +266 -0
- package/.agents/skills/overdrive/SKILL.md +142 -0
- package/.agents/skills/pdf/LICENSE.txt +30 -0
- package/.agents/skills/pdf/SKILL.md +314 -0
- package/.agents/skills/pdf/forms.md +294 -0
- package/.agents/skills/pdf/reference.md +612 -0
- package/.agents/skills/pdf/scripts/check_bounding_boxes.py +65 -0
- package/.agents/skills/pdf/scripts/check_fillable_fields.py +11 -0
- package/.agents/skills/pdf/scripts/convert_pdf_to_images.py +33 -0
- package/.agents/skills/pdf/scripts/create_validation_image.py +37 -0
- package/.agents/skills/pdf/scripts/extract_form_field_info.py +122 -0
- package/.agents/skills/pdf/scripts/extract_form_structure.py +115 -0
- package/.agents/skills/pdf/scripts/fill_fillable_fields.py +98 -0
- package/.agents/skills/pdf/scripts/fill_pdf_form_with_annotations.py +107 -0
- package/.agents/skills/playwright-cli/SKILL.md +344 -0
- package/.agents/skills/playwright-cli/references/element-attributes.md +23 -0
- package/.agents/skills/playwright-cli/references/playwright-tests.md +39 -0
- package/.agents/skills/playwright-cli/references/request-mocking.md +87 -0
- package/.agents/skills/playwright-cli/references/running-code.md +231 -0
- package/.agents/skills/playwright-cli/references/session-management.md +169 -0
- package/.agents/skills/playwright-cli/references/storage-state.md +275 -0
- package/.agents/skills/playwright-cli/references/test-generation.md +88 -0
- package/.agents/skills/playwright-cli/references/tracing.md +139 -0
- package/.agents/skills/playwright-cli/references/video-recording.md +143 -0
- package/.agents/skills/polish/SKILL.md +224 -0
- package/.agents/skills/pptx/LICENSE.txt +30 -0
- package/.agents/skills/pptx/SKILL.md +232 -0
- package/.agents/skills/pptx/editing.md +205 -0
- package/.agents/skills/pptx/pptxgenjs.md +420 -0
- package/.agents/skills/pptx/scripts/__init__.py +0 -0
- package/.agents/skills/pptx/scripts/add_slide.py +195 -0
- package/.agents/skills/pptx/scripts/clean.py +286 -0
- package/.agents/skills/pptx/scripts/office/helpers/__init__.py +0 -0
- package/.agents/skills/pptx/scripts/office/helpers/merge_runs.py +199 -0
- package/.agents/skills/pptx/scripts/office/helpers/simplify_redlines.py +197 -0
- package/.agents/skills/pptx/scripts/office/pack.py +159 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/.agents/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/.agents/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/.agents/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/.agents/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/.agents/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/.agents/skills/pptx/scripts/office/schemas/mce/mc.xsd +75 -0
- package/.agents/skills/pptx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
- package/.agents/skills/pptx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
- package/.agents/skills/pptx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
- package/.agents/skills/pptx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/.agents/skills/pptx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/.agents/skills/pptx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/.agents/skills/pptx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/.agents/skills/pptx/scripts/office/soffice.py +183 -0
- package/.agents/skills/pptx/scripts/office/unpack.py +132 -0
- package/.agents/skills/pptx/scripts/office/validate.py +111 -0
- package/.agents/skills/pptx/scripts/office/validators/__init__.py +15 -0
- package/.agents/skills/pptx/scripts/office/validators/base.py +847 -0
- package/.agents/skills/pptx/scripts/office/validators/docx.py +446 -0
- package/.agents/skills/pptx/scripts/office/validators/pptx.py +275 -0
- package/.agents/skills/pptx/scripts/office/validators/redlining.py +247 -0
- package/.agents/skills/pptx/scripts/thumbnail.py +289 -0
- package/.agents/skills/project-development/SKILL.md +291 -0
- package/.agents/skills/project-development/references/case-studies.md +388 -0
- package/.agents/skills/project-development/references/pipeline-patterns.md +610 -0
- package/.agents/skills/project-development/scripts/pipeline_template.py +796 -0
- package/.agents/skills/prompt-engineer/SKILL.md +263 -0
- package/.agents/skills/prompt-engineer/references/advanced_patterns.md +271 -0
- package/.agents/skills/prompt-engineer/references/core_prompting.md +137 -0
- package/.agents/skills/prompt-engineer/references/quality_improvement.md +193 -0
- package/.agents/skills/quieter/SKILL.md +103 -0
- package/.agents/skills/research-codebase/SKILL.md +227 -0
- package/.agents/skills/shape/SKILL.md +96 -0
- package/.agents/skills/skill-creator/LICENSE.txt +202 -0
- package/.agents/skills/skill-creator/SKILL.md +485 -0
- package/.agents/skills/skill-creator/agents/analyzer.md +274 -0
- package/.agents/skills/skill-creator/agents/comparator.md +202 -0
- package/.agents/skills/skill-creator/agents/grader.md +223 -0
- package/.agents/skills/skill-creator/assets/eval_review.html +146 -0
- package/.agents/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/.agents/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/.agents/skills/skill-creator/references/schemas.md +430 -0
- package/.agents/skills/skill-creator/scripts/__init__.py +0 -0
- package/.agents/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/.agents/skills/skill-creator/scripts/generate_report.py +326 -0
- package/.agents/skills/skill-creator/scripts/improve_description.py +247 -0
- package/.agents/skills/skill-creator/scripts/package_skill.py +136 -0
- package/.agents/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/.agents/skills/skill-creator/scripts/run_eval.py +310 -0
- package/.agents/skills/skill-creator/scripts/run_loop.py +328 -0
- package/.agents/skills/skill-creator/scripts/utils.py +47 -0
- package/.agents/skills/sl-commit/SKILL.md +51 -0
- package/.agents/skills/sl-submit-diff/SKILL.md +55 -0
- package/.agents/skills/teach-impeccable/SKILL.md +71 -0
- package/.agents/skills/test-driven-development/SKILL.md +371 -0
- package/.agents/skills/test-driven-development/testing-anti-patterns.md +299 -0
- package/.agents/skills/tool-design/SKILL.md +271 -0
- package/.agents/skills/tool-design/references/architectural_reduction.md +210 -0
- package/.agents/skills/tool-design/references/best_practices.md +176 -0
- package/.agents/skills/tool-design/scripts/description_generator.py +528 -0
- package/.agents/skills/typescript-advanced-types/SKILL.md +719 -0
- package/.agents/skills/typescript-expert/SKILL.md +428 -0
- package/.agents/skills/typescript-expert/references/tsconfig-strict.json +92 -0
- package/.agents/skills/typescript-expert/references/typescript-cheatsheet.md +383 -0
- package/.agents/skills/typescript-expert/references/utility-types.ts +335 -0
- package/.agents/skills/typescript-expert/scripts/ts_diagnostic.py +203 -0
- package/.agents/skills/typescript-react-reviewer/SKILL.md +200 -0
- package/.agents/skills/typescript-react-reviewer/references/antipatterns.md +510 -0
- package/.agents/skills/typescript-react-reviewer/references/checklist.md +267 -0
- package/.agents/skills/typescript-react-reviewer/references/react19-patterns.md +305 -0
- package/.agents/skills/typeset/SKILL.md +116 -0
- package/.agents/skills/workflow-creator/SKILL.md +337 -0
- package/.agents/skills/workflow-creator/references/agent-sessions.md +789 -0
- package/.agents/skills/workflow-creator/references/computation-and-validation.md +224 -0
- package/.agents/skills/workflow-creator/references/control-flow.md +450 -0
- package/.agents/skills/workflow-creator/references/discovery-and-verification.md +156 -0
- package/.agents/skills/workflow-creator/references/failure-modes.md +732 -0
- package/.agents/skills/workflow-creator/references/getting-started.md +289 -0
- package/.agents/skills/workflow-creator/references/session-config.md +355 -0
- package/.agents/skills/workflow-creator/references/state-and-data-flow.md +374 -0
- package/.agents/skills/workflow-creator/references/user-input.md +206 -0
- package/.agents/skills/workflow-creator/references/workflow-inputs.md +274 -0
- package/.agents/skills/xlsx/LICENSE.txt +30 -0
- package/.agents/skills/xlsx/SKILL.md +292 -0
- package/.agents/skills/xlsx/scripts/office/helpers/__init__.py +0 -0
- package/.agents/skills/xlsx/scripts/office/helpers/merge_runs.py +199 -0
- package/.agents/skills/xlsx/scripts/office/helpers/simplify_redlines.py +197 -0
- package/.agents/skills/xlsx/scripts/office/pack.py +159 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/.agents/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/.agents/skills/xlsx/scripts/office/schemas/mce/mc.xsd +75 -0
- package/.agents/skills/xlsx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
- package/.agents/skills/xlsx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
- package/.agents/skills/xlsx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
- package/.agents/skills/xlsx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/.agents/skills/xlsx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/.agents/skills/xlsx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/.agents/skills/xlsx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/.agents/skills/xlsx/scripts/office/soffice.py +183 -0
- package/.agents/skills/xlsx/scripts/office/unpack.py +132 -0
- package/.agents/skills/xlsx/scripts/office/validate.py +111 -0
- package/.agents/skills/xlsx/scripts/office/validators/__init__.py +15 -0
- package/.agents/skills/xlsx/scripts/office/validators/base.py +847 -0
- package/.agents/skills/xlsx/scripts/office/validators/docx.py +446 -0
- package/.agents/skills/xlsx/scripts/office/validators/pptx.py +275 -0
- package/.agents/skills/xlsx/scripts/office/validators/redlining.py +247 -0
- package/.agents/skills/xlsx/scripts/recalc.py +184 -0
- package/.claude/agents/reviewer.md +1 -0
- package/.github/agents/reviewer.md +1 -0
- package/.opencode/agents/reviewer.md +1 -0
- package/README.md +274 -169
- package/package.json +6 -7
- package/src/commands/cli/init/index.ts +2 -2
- package/src/commands/cli/init/scm.ts +7 -8
- package/src/commands/cli/workflow-command.test.ts +74 -0
- package/src/commands/cli/workflow.ts +7 -2
- package/src/scripts/bundle-configs.ts +128 -0
- package/src/sdk/components/compact-switcher.tsx +1 -1
- package/src/sdk/components/orchestrator-panel-store.ts +13 -0
- package/src/sdk/components/orchestrator-panel.tsx +10 -0
- package/src/sdk/components/statusline.tsx +13 -1
- package/src/sdk/components/workflow-picker-panel.tsx +407 -296
- package/src/sdk/providers/claude.ts +50 -0
- package/src/sdk/runtime/executor.ts +111 -32
- package/src/sdk/types.ts +7 -0
- package/src/sdk/workflows/builtin/ralph/claude/index.ts +132 -76
- package/src/sdk/workflows/builtin/ralph/copilot/index.ts +129 -71
- package/src/sdk/workflows/builtin/ralph/helpers/git.ts +184 -17
- package/src/sdk/workflows/builtin/ralph/helpers/prompts.ts +463 -79
- package/src/sdk/workflows/builtin/ralph/opencode/index.ts +124 -80
- package/src/services/system/auto-sync.ts +31 -51
- package/src/services/system/skills.ts +56 -60
- package/dist/lib/path-root-guard.d.ts +0 -4
- package/dist/lib/path-root-guard.d.ts.map +0 -1
- package/dist/sdk/components/color-utils.d.ts +0 -4
- package/dist/sdk/components/color-utils.d.ts.map +0 -1
- package/dist/sdk/components/compact-switcher.d.ts +0 -10
- package/dist/sdk/components/compact-switcher.d.ts.map +0 -1
- package/dist/sdk/components/connectors.d.ts +0 -15
- package/dist/sdk/components/connectors.d.ts.map +0 -1
- package/dist/sdk/components/connectors.test.d.ts +0 -2
- package/dist/sdk/components/connectors.test.d.ts.map +0 -1
- package/dist/sdk/components/edge.d.ts +0 -4
- package/dist/sdk/components/edge.d.ts.map +0 -1
- package/dist/sdk/components/error-boundary.d.ts +0 -23
- package/dist/sdk/components/error-boundary.d.ts.map +0 -1
- package/dist/sdk/components/graph-theme.d.ts +0 -17
- package/dist/sdk/components/graph-theme.d.ts.map +0 -1
- package/dist/sdk/components/header.d.ts +0 -3
- package/dist/sdk/components/header.d.ts.map +0 -1
- package/dist/sdk/components/hooks.d.ts +0 -15
- package/dist/sdk/components/hooks.d.ts.map +0 -1
- package/dist/sdk/components/layout.d.ts +0 -27
- package/dist/sdk/components/layout.d.ts.map +0 -1
- package/dist/sdk/components/layout.test.d.ts +0 -2
- package/dist/sdk/components/layout.test.d.ts.map +0 -1
- package/dist/sdk/components/node-card.d.ts +0 -10
- package/dist/sdk/components/node-card.d.ts.map +0 -1
- package/dist/sdk/components/orchestrator-panel-contexts.d.ts +0 -16
- package/dist/sdk/components/orchestrator-panel-contexts.d.ts.map +0 -1
- package/dist/sdk/components/orchestrator-panel-store.d.ts +0 -46
- package/dist/sdk/components/orchestrator-panel-store.d.ts.map +0 -1
- package/dist/sdk/components/orchestrator-panel-store.test.d.ts +0 -2
- package/dist/sdk/components/orchestrator-panel-store.test.d.ts.map +0 -1
- package/dist/sdk/components/orchestrator-panel-types.d.ts +0 -18
- package/dist/sdk/components/orchestrator-panel-types.d.ts.map +0 -1
- package/dist/sdk/components/orchestrator-panel.d.ts +0 -52
- package/dist/sdk/components/orchestrator-panel.d.ts.map +0 -1
- package/dist/sdk/components/session-graph-panel.d.ts +0 -7
- package/dist/sdk/components/session-graph-panel.d.ts.map +0 -1
- package/dist/sdk/components/status-helpers.d.ts +0 -6
- package/dist/sdk/components/status-helpers.d.ts.map +0 -1
- package/dist/sdk/components/statusline.d.ts +0 -7
- package/dist/sdk/components/statusline.d.ts.map +0 -1
- package/dist/sdk/components/workflow-picker-panel.d.ts +0 -123
- package/dist/sdk/components/workflow-picker-panel.d.ts.map +0 -1
- package/dist/sdk/define-workflow.d.ts +0 -78
- package/dist/sdk/define-workflow.d.ts.map +0 -1
- package/dist/sdk/define-workflow.test.d.ts +0 -2
- package/dist/sdk/define-workflow.test.d.ts.map +0 -1
- package/dist/sdk/errors.d.ts +0 -24
- package/dist/sdk/errors.d.ts.map +0 -1
- package/dist/sdk/errors.test.d.ts +0 -2
- package/dist/sdk/errors.test.d.ts.map +0 -1
- package/dist/sdk/index.d.ts +0 -13
- package/dist/sdk/index.d.ts.map +0 -1
- package/dist/sdk/providers/claude.d.ts +0 -170
- package/dist/sdk/providers/claude.d.ts.map +0 -1
- package/dist/sdk/providers/copilot.d.ts +0 -11
- package/dist/sdk/providers/copilot.d.ts.map +0 -1
- package/dist/sdk/providers/opencode.d.ts +0 -11
- package/dist/sdk/providers/opencode.d.ts.map +0 -1
- package/dist/sdk/runtime/discovery.d.ts +0 -86
- package/dist/sdk/runtime/discovery.d.ts.map +0 -1
- package/dist/sdk/runtime/executor-entry.d.ts +0 -11
- package/dist/sdk/runtime/executor-entry.d.ts.map +0 -1
- package/dist/sdk/runtime/executor.d.ts +0 -72
- package/dist/sdk/runtime/executor.d.ts.map +0 -1
- package/dist/sdk/runtime/executor.test.d.ts +0 -2
- package/dist/sdk/runtime/executor.test.d.ts.map +0 -1
- package/dist/sdk/runtime/graph-inference.d.ts +0 -35
- package/dist/sdk/runtime/graph-inference.d.ts.map +0 -1
- package/dist/sdk/runtime/loader.d.ts +0 -70
- package/dist/sdk/runtime/loader.d.ts.map +0 -1
- package/dist/sdk/runtime/panel.d.ts +0 -9
- package/dist/sdk/runtime/panel.d.ts.map +0 -1
- package/dist/sdk/runtime/theme.d.ts +0 -28
- package/dist/sdk/runtime/theme.d.ts.map +0 -1
- package/dist/sdk/runtime/tmux.d.ts +0 -297
- package/dist/sdk/runtime/tmux.d.ts.map +0 -1
- package/dist/sdk/types.d.ts +0 -295
- package/dist/sdk/types.d.ts.map +0 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/claude/index.d.ts +0 -62
- package/dist/sdk/workflows/builtin/deep-research-codebase/claude/index.d.ts.map +0 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/copilot/index.d.ts +0 -46
- package/dist/sdk/workflows/builtin/deep-research-codebase/copilot/index.d.ts.map +0 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/heuristic.d.ts +0 -26
- package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/heuristic.d.ts.map +0 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/prompts.d.ts +0 -92
- package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/prompts.d.ts.map +0 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/scout.d.ts +0 -57
- package/dist/sdk/workflows/builtin/deep-research-codebase/helpers/scout.d.ts.map +0 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/opencode/index.d.ts +0 -49
- package/dist/sdk/workflows/builtin/deep-research-codebase/opencode/index.d.ts.map +0 -1
- package/dist/sdk/workflows/builtin/ralph/claude/index.d.ts +0 -14
- package/dist/sdk/workflows/builtin/ralph/claude/index.d.ts.map +0 -1
- package/dist/sdk/workflows/builtin/ralph/copilot/index.d.ts +0 -14
- package/dist/sdk/workflows/builtin/ralph/copilot/index.d.ts.map +0 -1
- package/dist/sdk/workflows/builtin/ralph/helpers/git.d.ts +0 -17
- package/dist/sdk/workflows/builtin/ralph/helpers/git.d.ts.map +0 -1
- package/dist/sdk/workflows/builtin/ralph/helpers/prompts.d.ts +0 -119
- package/dist/sdk/workflows/builtin/ralph/helpers/prompts.d.ts.map +0 -1
- package/dist/sdk/workflows/builtin/ralph/helpers/review.d.ts +0 -20
- package/dist/sdk/workflows/builtin/ralph/helpers/review.d.ts.map +0 -1
- package/dist/sdk/workflows/builtin/ralph/opencode/index.d.ts +0 -14
- package/dist/sdk/workflows/builtin/ralph/opencode/index.d.ts.map +0 -1
- package/dist/sdk/workflows/index.d.ts +0 -24
- package/dist/sdk/workflows/index.d.ts.map +0 -1
- package/dist/services/config/definitions.d.ts +0 -85
- package/dist/services/config/definitions.d.ts.map +0 -1
- package/dist/services/system/copy.d.ts +0 -77
- package/dist/services/system/copy.d.ts.map +0 -1
- package/dist/services/system/detect.d.ts +0 -75
- package/dist/services/system/detect.d.ts.map +0 -1
- package/tsconfig.json +0 -33
|
@@ -0,0 +1,700 @@
|
|
|
1
|
+
# Infrastructure Patterns for Hosted Agents
|
|
2
|
+
|
|
3
|
+
This reference provides detailed implementation patterns for building hosted agent infrastructure. These patterns are derived from production systems at scale.
|
|
4
|
+
|
|
5
|
+
## Sandbox Architecture
|
|
6
|
+
|
|
7
|
+
### Modal Integration Pattern
|
|
8
|
+
|
|
9
|
+
Modal provides the sandbox infrastructure with near-instant startup and filesystem snapshots.
|
|
10
|
+
|
|
11
|
+
```python
|
|
12
|
+
import modal
|
|
13
|
+
|
|
14
|
+
# Define the base image with all dependencies
|
|
15
|
+
image = modal.Image.debian_slim().pip_install([
|
|
16
|
+
"opencode",
|
|
17
|
+
"gitpython",
|
|
18
|
+
"psycopg2-binary",
|
|
19
|
+
])
|
|
20
|
+
|
|
21
|
+
# Create the app
|
|
22
|
+
app = modal.App("coding-agent")
|
|
23
|
+
|
|
24
|
+
# Sandbox class with snapshot support
|
|
25
|
+
@app.cls(image=image, timeout=3600)
|
|
26
|
+
class AgentSandbox:
|
|
27
|
+
def __init__(self, repo_url: str, snapshot_id: str = None):
|
|
28
|
+
self.repo_url = repo_url
|
|
29
|
+
self.snapshot_id = snapshot_id
|
|
30
|
+
|
|
31
|
+
@modal.enter()
|
|
32
|
+
def setup(self):
|
|
33
|
+
if self.snapshot_id:
|
|
34
|
+
# Restore from snapshot
|
|
35
|
+
modal.Sandbox.restore(self.snapshot_id)
|
|
36
|
+
else:
|
|
37
|
+
# Fresh setup from image
|
|
38
|
+
self._clone_and_setup()
|
|
39
|
+
|
|
40
|
+
def _clone_and_setup(self):
|
|
41
|
+
"""Clone repo and run initial setup."""
|
|
42
|
+
token = self._get_github_app_token()
|
|
43
|
+
os.system(f"git clone https://x-access-token:{token}@github.com/{self.repo_url}")
|
|
44
|
+
os.system("npm install")
|
|
45
|
+
os.system("npm run build")
|
|
46
|
+
|
|
47
|
+
@modal.method()
|
|
48
|
+
def execute_prompt(self, prompt: str, user_identity: dict) -> dict:
|
|
49
|
+
"""Execute a prompt in the sandbox."""
|
|
50
|
+
# Update git config for this user
|
|
51
|
+
os.system(f'git config user.name "{user_identity["name"]}"')
|
|
52
|
+
os.system(f'git config user.email "{user_identity["email"]}"')
|
|
53
|
+
|
|
54
|
+
# Run the agent
|
|
55
|
+
result = self.agent.run(prompt)
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
"result": result,
|
|
59
|
+
"snapshot_id": modal.Sandbox.snapshot()
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Image Build Pipeline
|
|
64
|
+
|
|
65
|
+
Build images on a schedule to keep them fresh:
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
import schedule
|
|
69
|
+
import time
|
|
70
|
+
from datetime import datetime
|
|
71
|
+
|
|
72
|
+
class ImageBuilder:
|
|
73
|
+
def __init__(self, repositories: list[str]):
|
|
74
|
+
self.repositories = repositories
|
|
75
|
+
self.images = {}
|
|
76
|
+
|
|
77
|
+
def build_all_images(self):
|
|
78
|
+
"""Build images for all repositories."""
|
|
79
|
+
for repo in self.repositories:
|
|
80
|
+
try:
|
|
81
|
+
image = self._build_image(repo)
|
|
82
|
+
self.images[repo] = {
|
|
83
|
+
"image": image,
|
|
84
|
+
"built_at": datetime.utcnow(),
|
|
85
|
+
"commit": self._get_latest_commit(repo)
|
|
86
|
+
}
|
|
87
|
+
except Exception as e:
|
|
88
|
+
# Log but continue with other repos
|
|
89
|
+
log.error(f"Failed to build image for {repo}: {e}")
|
|
90
|
+
|
|
91
|
+
def _build_image(self, repo: str) -> str:
|
|
92
|
+
"""Build a single repository image."""
|
|
93
|
+
sandbox = modal.Sandbox.create()
|
|
94
|
+
|
|
95
|
+
# Clone with app token
|
|
96
|
+
token = get_app_installation_token(repo)
|
|
97
|
+
sandbox.exec(f"git clone https://x-access-token:{token}@github.com/{repo} /workspace")
|
|
98
|
+
|
|
99
|
+
# Install dependencies
|
|
100
|
+
sandbox.exec("cd /workspace && npm install")
|
|
101
|
+
|
|
102
|
+
# Run build
|
|
103
|
+
sandbox.exec("cd /workspace && npm run build")
|
|
104
|
+
|
|
105
|
+
# Warm caches
|
|
106
|
+
sandbox.exec("cd /workspace && npm run dev &")
|
|
107
|
+
time.sleep(5) # Let dev server start
|
|
108
|
+
sandbox.exec("cd /workspace && npm test -- --run")
|
|
109
|
+
|
|
110
|
+
# Create snapshot
|
|
111
|
+
return sandbox.snapshot()
|
|
112
|
+
|
|
113
|
+
def get_latest_image(self, repo: str) -> str:
|
|
114
|
+
"""Get the most recent image for a repository."""
|
|
115
|
+
if repo not in self.images:
|
|
116
|
+
raise ValueError(f"No image available for {repo}")
|
|
117
|
+
return self.images[repo]["image"]
|
|
118
|
+
|
|
119
|
+
# Schedule builds every 30 minutes
|
|
120
|
+
builder = ImageBuilder(["org/frontend", "org/backend", "org/shared"])
|
|
121
|
+
schedule.every(30).minutes.do(builder.build_all_images)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Warm Pool Management
|
|
125
|
+
|
|
126
|
+
Maintain pre-warmed sandboxes for instant session starts:
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
from collections import defaultdict
|
|
130
|
+
from dataclasses import dataclass
|
|
131
|
+
from datetime import datetime, timedelta
|
|
132
|
+
|
|
133
|
+
@dataclass
|
|
134
|
+
class WarmSandbox:
|
|
135
|
+
sandbox_id: str
|
|
136
|
+
repo: str
|
|
137
|
+
created_at: datetime
|
|
138
|
+
image_version: str
|
|
139
|
+
is_claimed: bool = False
|
|
140
|
+
|
|
141
|
+
class WarmPoolManager:
|
|
142
|
+
def __init__(self, target_pool_size: int = 3):
|
|
143
|
+
self.target_size = target_pool_size
|
|
144
|
+
self.pools = defaultdict(list) # repo -> [WarmSandbox]
|
|
145
|
+
self.max_age = timedelta(minutes=25) # Expire before next image build
|
|
146
|
+
|
|
147
|
+
def get_warm_sandbox(self, repo: str) -> WarmSandbox | None:
|
|
148
|
+
"""Get a pre-warmed sandbox if available."""
|
|
149
|
+
pool = self.pools[repo]
|
|
150
|
+
|
|
151
|
+
for sandbox in pool:
|
|
152
|
+
if not sandbox.is_claimed and self._is_valid(sandbox):
|
|
153
|
+
sandbox.is_claimed = True
|
|
154
|
+
return sandbox
|
|
155
|
+
|
|
156
|
+
return None
|
|
157
|
+
|
|
158
|
+
def _is_valid(self, sandbox: WarmSandbox) -> bool:
|
|
159
|
+
"""Check if sandbox is still valid."""
|
|
160
|
+
age = datetime.utcnow() - sandbox.created_at
|
|
161
|
+
current_image = self.image_builder.get_latest_image(sandbox.repo)
|
|
162
|
+
|
|
163
|
+
return (
|
|
164
|
+
age < self.max_age and
|
|
165
|
+
sandbox.image_version == current_image
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
def maintain_pool(self, repo: str):
|
|
169
|
+
"""Ensure pool has target number of warm sandboxes."""
|
|
170
|
+
# Remove expired sandboxes
|
|
171
|
+
self.pools[repo] = [s for s in self.pools[repo] if self._is_valid(s)]
|
|
172
|
+
|
|
173
|
+
# Add new sandboxes to reach target
|
|
174
|
+
current_count = len([s for s in self.pools[repo] if not s.is_claimed])
|
|
175
|
+
needed = self.target_size - current_count
|
|
176
|
+
|
|
177
|
+
for _ in range(needed):
|
|
178
|
+
sandbox = self._create_warm_sandbox(repo)
|
|
179
|
+
self.pools[repo].append(sandbox)
|
|
180
|
+
|
|
181
|
+
def _create_warm_sandbox(self, repo: str) -> WarmSandbox:
|
|
182
|
+
"""Create a new warm sandbox from latest image."""
|
|
183
|
+
image = self.image_builder.get_latest_image(repo)
|
|
184
|
+
sandbox_id = modal.Sandbox.create(image=image)
|
|
185
|
+
|
|
186
|
+
# Sync to latest (runs in background)
|
|
187
|
+
self._sync_to_latest(sandbox_id, repo)
|
|
188
|
+
|
|
189
|
+
return WarmSandbox(
|
|
190
|
+
sandbox_id=sandbox_id,
|
|
191
|
+
repo=repo,
|
|
192
|
+
created_at=datetime.utcnow(),
|
|
193
|
+
image_version=image
|
|
194
|
+
)
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## API Layer Patterns
|
|
198
|
+
|
|
199
|
+
### Cloudflare Durable Objects for Session State
|
|
200
|
+
|
|
201
|
+
Each session gets its own Durable Object with isolated SQLite:
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
// Session Durable Object
|
|
205
|
+
export class SessionDO implements DurableObject {
|
|
206
|
+
private storage: DurableObjectStorage;
|
|
207
|
+
private sql: SqlStorage;
|
|
208
|
+
private connections: Map<string, WebSocket> = new Map();
|
|
209
|
+
|
|
210
|
+
constructor(ctx: DurableObjectState) {
|
|
211
|
+
this.storage = ctx.storage;
|
|
212
|
+
this.sql = ctx.storage.sql;
|
|
213
|
+
this.initializeSchema();
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
private initializeSchema() {
|
|
217
|
+
this.sql.exec(`
|
|
218
|
+
CREATE TABLE IF NOT EXISTS messages (
|
|
219
|
+
id INTEGER PRIMARY KEY,
|
|
220
|
+
role TEXT NOT NULL,
|
|
221
|
+
content TEXT NOT NULL,
|
|
222
|
+
author_id TEXT,
|
|
223
|
+
author_name TEXT,
|
|
224
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
CREATE TABLE IF NOT EXISTS artifacts (
|
|
228
|
+
id INTEGER PRIMARY KEY,
|
|
229
|
+
type TEXT NOT NULL,
|
|
230
|
+
path TEXT,
|
|
231
|
+
content TEXT,
|
|
232
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
CREATE TABLE IF NOT EXISTS events (
|
|
236
|
+
id INTEGER PRIMARY KEY,
|
|
237
|
+
type TEXT NOT NULL,
|
|
238
|
+
data TEXT,
|
|
239
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
240
|
+
);
|
|
241
|
+
`);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
async fetch(request: Request): Promise<Response> {
|
|
245
|
+
const url = new URL(request.url);
|
|
246
|
+
|
|
247
|
+
if (request.headers.get("Upgrade") === "websocket") {
|
|
248
|
+
return this.handleWebSocket(request);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
switch (url.pathname) {
|
|
252
|
+
case "/message":
|
|
253
|
+
return this.handleMessage(request);
|
|
254
|
+
case "/status":
|
|
255
|
+
return this.getStatus();
|
|
256
|
+
default:
|
|
257
|
+
return new Response("Not found", { status: 404 });
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
private handleWebSocket(request: Request): Response {
|
|
262
|
+
const pair = new WebSocketPair();
|
|
263
|
+
const [client, server] = Object.values(pair);
|
|
264
|
+
|
|
265
|
+
const connectionId = crypto.randomUUID();
|
|
266
|
+
this.connections.set(connectionId, server);
|
|
267
|
+
|
|
268
|
+
server.accept();
|
|
269
|
+
server.addEventListener("close", () => {
|
|
270
|
+
this.connections.delete(connectionId);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
return new Response(null, { status: 101, webSocket: client });
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
private broadcast(message: object) {
|
|
277
|
+
const data = JSON.stringify(message);
|
|
278
|
+
for (const ws of this.connections.values()) {
|
|
279
|
+
ws.send(data);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
async handleMessage(request: Request): Promise<Response> {
|
|
284
|
+
const { content, author } = await request.json();
|
|
285
|
+
|
|
286
|
+
// Store message
|
|
287
|
+
this.sql.exec(
|
|
288
|
+
`INSERT INTO messages (role, content, author_id, author_name) VALUES (?, ?, ?, ?)`,
|
|
289
|
+
["user", content, author.id, author.name]
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
// Broadcast to all connected clients
|
|
293
|
+
this.broadcast({
|
|
294
|
+
type: "message",
|
|
295
|
+
role: "user",
|
|
296
|
+
content,
|
|
297
|
+
author,
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
// Forward to sandbox for processing
|
|
301
|
+
const result = await this.forwardToSandbox(content, author);
|
|
302
|
+
|
|
303
|
+
return Response.json(result);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Real-Time Event Streaming
|
|
309
|
+
|
|
310
|
+
Stream events from sandbox to all connected clients:
|
|
311
|
+
|
|
312
|
+
```typescript
|
|
313
|
+
class EventStream {
|
|
314
|
+
private sessionDO: DurableObjectStub;
|
|
315
|
+
|
|
316
|
+
async streamFromSandbox(sandboxId: string, sessionId: string) {
|
|
317
|
+
const sandbox = await modal.Sandbox.get(sandboxId);
|
|
318
|
+
|
|
319
|
+
// Subscribe to sandbox events
|
|
320
|
+
for await (const event of sandbox.events()) {
|
|
321
|
+
// Forward to Durable Object for broadcast
|
|
322
|
+
await this.sessionDO.fetch(
|
|
323
|
+
new Request(`https://internal/event`, {
|
|
324
|
+
method: "POST",
|
|
325
|
+
body: JSON.stringify({
|
|
326
|
+
type: event.type,
|
|
327
|
+
data: event.data,
|
|
328
|
+
}),
|
|
329
|
+
})
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
## Client Integration Patterns
|
|
337
|
+
|
|
338
|
+
### Slack Bot with Repository Classification
|
|
339
|
+
|
|
340
|
+
```python
|
|
341
|
+
from slack_bolt import App
|
|
342
|
+
from slack_bolt.adapter.socket_mode import SocketModeHandler
|
|
343
|
+
|
|
344
|
+
app = App(token=os.environ["SLACK_BOT_TOKEN"])
|
|
345
|
+
|
|
346
|
+
# Repository descriptions for classification
|
|
347
|
+
REPO_DESCRIPTIONS = [
|
|
348
|
+
{
|
|
349
|
+
"name": "frontend-monorepo",
|
|
350
|
+
"description": "React frontend application with dashboard, user portal, and admin interfaces",
|
|
351
|
+
"hints": ["dashboard", "UI", "component", "page", "frontend"]
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
"name": "backend-services",
|
|
355
|
+
"description": "Node.js API services including auth, payments, and core business logic",
|
|
356
|
+
"hints": ["API", "endpoint", "service", "backend", "database"]
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
"name": "mobile-app",
|
|
360
|
+
"description": "React Native mobile application for iOS and Android",
|
|
361
|
+
"hints": ["mobile", "app", "iOS", "Android", "native"]
|
|
362
|
+
}
|
|
363
|
+
]
|
|
364
|
+
|
|
365
|
+
async def classify_repository(message: str, channel: str, thread: list[str]) -> str:
|
|
366
|
+
"""Use fast model to classify which repo the message refers to."""
|
|
367
|
+
prompt = f"""Classify which repository this message is about.
|
|
368
|
+
|
|
369
|
+
Message: {message}
|
|
370
|
+
Channel: #{channel}
|
|
371
|
+
Thread context: {' | '.join(thread[-3:])}
|
|
372
|
+
|
|
373
|
+
Repositories:
|
|
374
|
+
{json.dumps(REPO_DESCRIPTIONS, indent=2)}
|
|
375
|
+
|
|
376
|
+
Return ONLY the repository name, or "unknown" if unclear."""
|
|
377
|
+
|
|
378
|
+
response = await openai.chat.completions.create(
|
|
379
|
+
model="gpt-4o-mini",
|
|
380
|
+
messages=[{"role": "user", "content": prompt}],
|
|
381
|
+
max_tokens=50
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
return response.choices[0].message.content.strip()
|
|
385
|
+
|
|
386
|
+
@app.event("app_mention")
|
|
387
|
+
async def handle_mention(event, say, client):
|
|
388
|
+
"""Handle @mentions of the bot."""
|
|
389
|
+
channel = event["channel"]
|
|
390
|
+
message = event["text"]
|
|
391
|
+
thread_ts = event.get("thread_ts", event["ts"])
|
|
392
|
+
|
|
393
|
+
# Get thread context if in a thread
|
|
394
|
+
thread_messages = []
|
|
395
|
+
if "thread_ts" in event:
|
|
396
|
+
result = await client.conversations_replies(
|
|
397
|
+
channel=channel,
|
|
398
|
+
ts=thread_ts
|
|
399
|
+
)
|
|
400
|
+
thread_messages = [m["text"] for m in result["messages"]]
|
|
401
|
+
|
|
402
|
+
# Get channel info for context
|
|
403
|
+
channel_info = await client.conversations_info(channel=channel)
|
|
404
|
+
channel_name = channel_info["channel"]["name"]
|
|
405
|
+
|
|
406
|
+
# Classify repository
|
|
407
|
+
repo = await classify_repository(message, channel_name, thread_messages)
|
|
408
|
+
|
|
409
|
+
if repo == "unknown":
|
|
410
|
+
await say(
|
|
411
|
+
text="I'm not sure which repository you're referring to. Could you specify?",
|
|
412
|
+
thread_ts=thread_ts
|
|
413
|
+
)
|
|
414
|
+
return
|
|
415
|
+
|
|
416
|
+
# Start session and process
|
|
417
|
+
session = await start_session(repo, event["user"])
|
|
418
|
+
|
|
419
|
+
await say(
|
|
420
|
+
text=f":robot_face: Starting work in `{repo}`...",
|
|
421
|
+
thread_ts=thread_ts
|
|
422
|
+
)
|
|
423
|
+
|
|
424
|
+
result = await session.process(message)
|
|
425
|
+
|
|
426
|
+
# Post result with Block Kit formatting
|
|
427
|
+
await say(
|
|
428
|
+
blocks=format_result_blocks(result),
|
|
429
|
+
thread_ts=thread_ts
|
|
430
|
+
)
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
### Chrome Extension DOM Extraction
|
|
434
|
+
|
|
435
|
+
Extract DOM structure instead of sending screenshots:
|
|
436
|
+
|
|
437
|
+
```typescript
|
|
438
|
+
// content-script.ts
|
|
439
|
+
interface ElementInfo {
|
|
440
|
+
tag: string;
|
|
441
|
+
classes: string[];
|
|
442
|
+
id?: string;
|
|
443
|
+
text?: string;
|
|
444
|
+
rect: DOMRect;
|
|
445
|
+
reactComponent?: string;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function extractDOMInfo(element: Element): ElementInfo {
|
|
449
|
+
// Get React component name if available
|
|
450
|
+
let reactComponent: string | undefined;
|
|
451
|
+
const fiberKey = Object.keys(element).find((key) =>
|
|
452
|
+
key.startsWith("__reactFiber")
|
|
453
|
+
);
|
|
454
|
+
if (fiberKey) {
|
|
455
|
+
const fiber = (element as any)[fiberKey];
|
|
456
|
+
reactComponent = fiber?.type?.name || fiber?.type?.displayName;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
return {
|
|
460
|
+
tag: element.tagName.toLowerCase(),
|
|
461
|
+
classes: Array.from(element.classList),
|
|
462
|
+
id: element.id || undefined,
|
|
463
|
+
text: element.textContent?.slice(0, 100),
|
|
464
|
+
rect: element.getBoundingClientRect(),
|
|
465
|
+
reactComponent,
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
function extractSelectedArea(selection: DOMRect): ElementInfo[] {
|
|
470
|
+
const elements: ElementInfo[] = [];
|
|
471
|
+
|
|
472
|
+
// Find all elements within selection bounds
|
|
473
|
+
document.querySelectorAll("*").forEach((el) => {
|
|
474
|
+
const rect = el.getBoundingClientRect();
|
|
475
|
+
if (
|
|
476
|
+
rect.top >= selection.top &&
|
|
477
|
+
rect.left >= selection.left &&
|
|
478
|
+
rect.bottom <= selection.bottom &&
|
|
479
|
+
rect.right <= selection.right
|
|
480
|
+
) {
|
|
481
|
+
elements.push(extractDOMInfo(el));
|
|
482
|
+
}
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
return elements;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// Message handler for sidebar
|
|
489
|
+
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
|
490
|
+
if (request.type === "EXTRACT_SELECTION") {
|
|
491
|
+
const elements = extractSelectedArea(request.selection);
|
|
492
|
+
sendResponse({ elements });
|
|
493
|
+
}
|
|
494
|
+
});
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
## Multiplayer Implementation
|
|
498
|
+
|
|
499
|
+
### Authorship Tracking
|
|
500
|
+
|
|
501
|
+
Track which user made each change:
|
|
502
|
+
|
|
503
|
+
```python
|
|
504
|
+
@dataclass
|
|
505
|
+
class PromptContext:
|
|
506
|
+
content: str
|
|
507
|
+
author: Author
|
|
508
|
+
session_id: str
|
|
509
|
+
timestamp: datetime
|
|
510
|
+
|
|
511
|
+
@dataclass
|
|
512
|
+
class Author:
|
|
513
|
+
id: str
|
|
514
|
+
name: str
|
|
515
|
+
email: str
|
|
516
|
+
github_token: str # For PR creation
|
|
517
|
+
|
|
518
|
+
class MultiplayerSession:
|
|
519
|
+
def __init__(self, session_id: str):
|
|
520
|
+
self.session_id = session_id
|
|
521
|
+
self.participants: dict[str, Author] = {}
|
|
522
|
+
self.prompt_queue: list[PromptContext] = []
|
|
523
|
+
|
|
524
|
+
def add_participant(self, author: Author):
|
|
525
|
+
"""Add a participant to the session."""
|
|
526
|
+
self.participants[author.id] = author
|
|
527
|
+
self.broadcast_event("participant_joined", author)
|
|
528
|
+
|
|
529
|
+
async def process_prompt(self, prompt: PromptContext):
|
|
530
|
+
"""Process prompt with author attribution."""
|
|
531
|
+
# Update git config for this author
|
|
532
|
+
await self.sandbox.exec(
|
|
533
|
+
f'git config user.name "{prompt.author.name}"'
|
|
534
|
+
)
|
|
535
|
+
await self.sandbox.exec(
|
|
536
|
+
f'git config user.email "{prompt.author.email}"'
|
|
537
|
+
)
|
|
538
|
+
|
|
539
|
+
# Run agent
|
|
540
|
+
result = await self.agent.run(prompt.content)
|
|
541
|
+
|
|
542
|
+
# If changes were made, create PR with author's token
|
|
543
|
+
if result.has_changes:
|
|
544
|
+
await self.create_pr(
|
|
545
|
+
branch=result.branch,
|
|
546
|
+
author=prompt.author
|
|
547
|
+
)
|
|
548
|
+
|
|
549
|
+
return result
|
|
550
|
+
|
|
551
|
+
async def create_pr(self, branch: str, author: Author):
|
|
552
|
+
"""Create PR using the author's GitHub token."""
|
|
553
|
+
async with aiohttp.ClientSession() as session:
|
|
554
|
+
headers = {
|
|
555
|
+
"Authorization": f"Bearer {author.github_token}",
|
|
556
|
+
"Accept": "application/vnd.github.v3+json"
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
await session.post(
|
|
560
|
+
f"https://api.github.com/repos/{self.repo}/pulls",
|
|
561
|
+
headers=headers,
|
|
562
|
+
json={
|
|
563
|
+
"title": self.generate_pr_title(),
|
|
564
|
+
"body": self.generate_pr_body(),
|
|
565
|
+
"head": branch,
|
|
566
|
+
"base": "main"
|
|
567
|
+
}
|
|
568
|
+
)
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
## Metrics and Monitoring
|
|
572
|
+
|
|
573
|
+
### Key Metrics to Track
|
|
574
|
+
|
|
575
|
+
```python
|
|
576
|
+
from dataclasses import dataclass
|
|
577
|
+
from datetime import datetime, timedelta
|
|
578
|
+
|
|
579
|
+
@dataclass
|
|
580
|
+
class SessionMetrics:
|
|
581
|
+
session_id: str
|
|
582
|
+
started_at: datetime
|
|
583
|
+
first_token_at: datetime | None
|
|
584
|
+
completed_at: datetime | None
|
|
585
|
+
pr_created: bool
|
|
586
|
+
pr_merged: bool
|
|
587
|
+
prompts_count: int
|
|
588
|
+
participants_count: int
|
|
589
|
+
|
|
590
|
+
@property
|
|
591
|
+
def time_to_first_token(self) -> timedelta | None:
|
|
592
|
+
if self.first_token_at:
|
|
593
|
+
return self.first_token_at - self.started_at
|
|
594
|
+
return None
|
|
595
|
+
|
|
596
|
+
class MetricsAggregator:
|
|
597
|
+
def get_adoption_metrics(self, period: timedelta) -> dict:
|
|
598
|
+
"""Get adoption metrics for a time period."""
|
|
599
|
+
sessions = self.get_sessions_in_period(period)
|
|
600
|
+
|
|
601
|
+
total_prs = sum(1 for s in sessions if s.pr_created)
|
|
602
|
+
merged_prs = sum(1 for s in sessions if s.pr_merged)
|
|
603
|
+
|
|
604
|
+
return {
|
|
605
|
+
"total_sessions": len(sessions),
|
|
606
|
+
"prs_created": total_prs,
|
|
607
|
+
"prs_merged": merged_prs,
|
|
608
|
+
"merge_rate": merged_prs / total_prs if total_prs > 0 else 0,
|
|
609
|
+
"avg_time_to_first_token": self._avg_ttft(sessions),
|
|
610
|
+
"unique_users": len(set(s.author_id for s in sessions)),
|
|
611
|
+
"multiplayer_sessions": sum(
|
|
612
|
+
1 for s in sessions if s.participants_count > 1
|
|
613
|
+
)
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
def get_repository_metrics(self) -> dict[str, dict]:
|
|
617
|
+
"""Get metrics broken down by repository."""
|
|
618
|
+
metrics = {}
|
|
619
|
+
|
|
620
|
+
for repo in self.repositories:
|
|
621
|
+
repo_sessions = self.get_sessions_for_repo(repo)
|
|
622
|
+
total_prs = self.get_total_prs(repo)
|
|
623
|
+
agent_prs = sum(1 for s in repo_sessions if s.pr_merged)
|
|
624
|
+
|
|
625
|
+
metrics[repo] = {
|
|
626
|
+
"agent_pr_percentage": agent_prs / total_prs * 100,
|
|
627
|
+
"session_count": len(repo_sessions),
|
|
628
|
+
"avg_prompts_per_session": sum(
|
|
629
|
+
s.prompts_count for s in repo_sessions
|
|
630
|
+
) / len(repo_sessions)
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
return metrics
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
## Security Considerations
|
|
637
|
+
|
|
638
|
+
### Sandbox Isolation
|
|
639
|
+
|
|
640
|
+
```python
|
|
641
|
+
class SandboxSecurityConfig:
|
|
642
|
+
"""Security configuration for sandboxes."""
|
|
643
|
+
|
|
644
|
+
# Network restrictions
|
|
645
|
+
allowed_hosts = [
|
|
646
|
+
"github.com",
|
|
647
|
+
"api.github.com",
|
|
648
|
+
"registry.npmjs.org",
|
|
649
|
+
"pypi.org",
|
|
650
|
+
]
|
|
651
|
+
|
|
652
|
+
# Resource limits
|
|
653
|
+
max_memory_mb = 4096
|
|
654
|
+
max_cpu_cores = 2
|
|
655
|
+
max_disk_gb = 10
|
|
656
|
+
max_runtime_hours = 4
|
|
657
|
+
|
|
658
|
+
# Secrets handling
|
|
659
|
+
secrets_to_inject = [
|
|
660
|
+
"GITHUB_APP_TOKEN",
|
|
661
|
+
"NPM_TOKEN",
|
|
662
|
+
]
|
|
663
|
+
|
|
664
|
+
# Blocked operations
|
|
665
|
+
blocked_commands = [
|
|
666
|
+
"curl", # Use fetch tools instead
|
|
667
|
+
"wget",
|
|
668
|
+
"ssh",
|
|
669
|
+
]
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
### Token Handling
|
|
673
|
+
|
|
674
|
+
```python
|
|
675
|
+
class TokenManager:
|
|
676
|
+
"""Manage tokens for GitHub operations."""
|
|
677
|
+
|
|
678
|
+
def get_app_installation_token(self, repo: str) -> str:
|
|
679
|
+
"""Get short-lived token for repo access."""
|
|
680
|
+
# Token expires in 1 hour
|
|
681
|
+
return github_app.create_installation_token(
|
|
682
|
+
installation_id=self.get_installation_id(repo),
|
|
683
|
+
permissions={"contents": "write", "pull_requests": "write"}
|
|
684
|
+
)
|
|
685
|
+
|
|
686
|
+
def get_user_token(self, user_id: str) -> str:
|
|
687
|
+
"""Get user's OAuth token for PR creation."""
|
|
688
|
+
# Stored encrypted, decrypted at runtime
|
|
689
|
+
encrypted = self.storage.get(f"user_token:{user_id}")
|
|
690
|
+
return self.decrypt(encrypted)
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
## References
|
|
694
|
+
|
|
695
|
+
- [Modal Documentation](https://modal.com/docs)
|
|
696
|
+
- [Cloudflare Durable Objects](https://developers.cloudflare.com/durable-objects/)
|
|
697
|
+
- [Cloudflare Agents SDK](https://developers.cloudflare.com/agents/)
|
|
698
|
+
- [GitHub Apps Authentication](https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app)
|
|
699
|
+
- [Slack Bolt for Python](https://slack.dev/bolt-python/)
|
|
700
|
+
- [Chrome Extension APIs](https://developer.chrome.com/docs/extensions/)
|