docagent-cli 0.0.35__py3-none-any.whl
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.
- docagent_cli/__init__.py +36 -0
- docagent_cli/__main__.py +6 -0
- docagent_cli/_ask_user_types.py +90 -0
- docagent_cli/_cli_context.py +27 -0
- docagent_cli/_debug.py +52 -0
- docagent_cli/_env_vars.py +56 -0
- docagent_cli/_server_config.py +352 -0
- docagent_cli/_session_stats.py +114 -0
- docagent_cli/_testing_models.py +144 -0
- docagent_cli/_version.py +17 -0
- docagent_cli/agent.py +1193 -0
- docagent_cli/app.py +4979 -0
- docagent_cli/app.tcss +283 -0
- docagent_cli/ask_user.py +301 -0
- docagent_cli/built_in_skills/__init__.py +5 -0
- docagent_cli/built_in_skills/doc-coauthoring/SKILL.md +375 -0
- docagent_cli/built_in_skills/docx/LICENSE.txt +30 -0
- docagent_cli/built_in_skills/docx/SKILL.md +590 -0
- docagent_cli/built_in_skills/docx/scripts/__init__.py +1 -0
- docagent_cli/built_in_skills/docx/scripts/accept_changes.py +135 -0
- docagent_cli/built_in_skills/docx/scripts/comment.py +318 -0
- docagent_cli/built_in_skills/docx/scripts/office/helpers/__init__.py +0 -0
- docagent_cli/built_in_skills/docx/scripts/office/helpers/merge_runs.py +199 -0
- docagent_cli/built_in_skills/docx/scripts/office/helpers/simplify_redlines.py +197 -0
- docagent_cli/built_in_skills/docx/scripts/office/pack.py +159 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/mce/mc.xsd +75 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- docagent_cli/built_in_skills/docx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
- docagent_cli/built_in_skills/docx/scripts/office/soffice.py +183 -0
- docagent_cli/built_in_skills/docx/scripts/office/unpack.py +132 -0
- docagent_cli/built_in_skills/docx/scripts/office/validate.py +111 -0
- docagent_cli/built_in_skills/docx/scripts/office/validators/__init__.py +15 -0
- docagent_cli/built_in_skills/docx/scripts/office/validators/base.py +847 -0
- docagent_cli/built_in_skills/docx/scripts/office/validators/docx.py +446 -0
- docagent_cli/built_in_skills/docx/scripts/office/validators/pptx.py +275 -0
- docagent_cli/built_in_skills/docx/scripts/office/validators/redlining.py +247 -0
- docagent_cli/built_in_skills/docx/scripts/templates/comments.xml +3 -0
- docagent_cli/built_in_skills/docx/scripts/templates/commentsExtended.xml +3 -0
- docagent_cli/built_in_skills/docx/scripts/templates/commentsExtensible.xml +3 -0
- docagent_cli/built_in_skills/docx/scripts/templates/commentsIds.xml +3 -0
- docagent_cli/built_in_skills/docx/scripts/templates/people.xml +3 -0
- docagent_cli/built_in_skills/pdf/LICENSE.txt +30 -0
- docagent_cli/built_in_skills/pdf/SKILL.md +314 -0
- docagent_cli/built_in_skills/pdf/forms.md +294 -0
- docagent_cli/built_in_skills/pdf/reference.md +612 -0
- docagent_cli/built_in_skills/pdf/scripts/check_bounding_boxes.py +65 -0
- docagent_cli/built_in_skills/pdf/scripts/check_fillable_fields.py +11 -0
- docagent_cli/built_in_skills/pdf/scripts/convert_pdf_to_images.py +33 -0
- docagent_cli/built_in_skills/pdf/scripts/create_validation_image.py +37 -0
- docagent_cli/built_in_skills/pdf/scripts/extract_form_field_info.py +122 -0
- docagent_cli/built_in_skills/pdf/scripts/extract_form_structure.py +115 -0
- docagent_cli/built_in_skills/pdf/scripts/fill_fillable_fields.py +98 -0
- docagent_cli/built_in_skills/pdf/scripts/fill_pdf_form_with_annotations.py +107 -0
- docagent_cli/built_in_skills/pptx/LICENSE.txt +30 -0
- docagent_cli/built_in_skills/pptx/SKILL.md +232 -0
- docagent_cli/built_in_skills/pptx/editing.md +205 -0
- docagent_cli/built_in_skills/pptx/pptxgenjs.md +420 -0
- docagent_cli/built_in_skills/pptx/scripts/__init__.py +0 -0
- docagent_cli/built_in_skills/pptx/scripts/add_slide.py +195 -0
- docagent_cli/built_in_skills/pptx/scripts/clean.py +286 -0
- docagent_cli/built_in_skills/pptx/scripts/office/helpers/__init__.py +0 -0
- docagent_cli/built_in_skills/pptx/scripts/office/helpers/merge_runs.py +199 -0
- docagent_cli/built_in_skills/pptx/scripts/office/helpers/simplify_redlines.py +197 -0
- docagent_cli/built_in_skills/pptx/scripts/office/pack.py +159 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/mce/mc.xsd +75 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- docagent_cli/built_in_skills/pptx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
- docagent_cli/built_in_skills/pptx/scripts/office/soffice.py +183 -0
- docagent_cli/built_in_skills/pptx/scripts/office/unpack.py +132 -0
- docagent_cli/built_in_skills/pptx/scripts/office/validate.py +111 -0
- docagent_cli/built_in_skills/pptx/scripts/office/validators/__init__.py +15 -0
- docagent_cli/built_in_skills/pptx/scripts/office/validators/base.py +847 -0
- docagent_cli/built_in_skills/pptx/scripts/office/validators/docx.py +446 -0
- docagent_cli/built_in_skills/pptx/scripts/office/validators/pptx.py +275 -0
- docagent_cli/built_in_skills/pptx/scripts/office/validators/redlining.py +247 -0
- docagent_cli/built_in_skills/pptx/scripts/thumbnail.py +289 -0
- docagent_cli/built_in_skills/remember/SKILL.md +118 -0
- docagent_cli/built_in_skills/skill-creator/LICENSE.txt +202 -0
- docagent_cli/built_in_skills/skill-creator/SKILL.md +485 -0
- docagent_cli/built_in_skills/skill-creator/agents/analyzer.md +274 -0
- docagent_cli/built_in_skills/skill-creator/agents/comparator.md +202 -0
- docagent_cli/built_in_skills/skill-creator/agents/grader.md +223 -0
- docagent_cli/built_in_skills/skill-creator/assets/eval_review.html +146 -0
- docagent_cli/built_in_skills/skill-creator/eval-viewer/generate_review.py +471 -0
- docagent_cli/built_in_skills/skill-creator/eval-viewer/viewer.html +1325 -0
- docagent_cli/built_in_skills/skill-creator/references/schemas.md +430 -0
- docagent_cli/built_in_skills/skill-creator/scripts/__init__.py +0 -0
- docagent_cli/built_in_skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- docagent_cli/built_in_skills/skill-creator/scripts/generate_report.py +326 -0
- docagent_cli/built_in_skills/skill-creator/scripts/improve_description.py +247 -0
- docagent_cli/built_in_skills/skill-creator/scripts/package_skill.py +136 -0
- docagent_cli/built_in_skills/skill-creator/scripts/quick_validate.py +103 -0
- docagent_cli/built_in_skills/skill-creator/scripts/run_eval.py +310 -0
- docagent_cli/built_in_skills/skill-creator/scripts/run_loop.py +328 -0
- docagent_cli/built_in_skills/skill-creator/scripts/utils.py +47 -0
- docagent_cli/built_in_skills/theme-factory/LICENSE.txt +202 -0
- docagent_cli/built_in_skills/theme-factory/SKILL.md +59 -0
- docagent_cli/built_in_skills/theme-factory/theme-showcase.pdf +0 -0
- docagent_cli/built_in_skills/theme-factory/themes/arctic-frost.md +19 -0
- docagent_cli/built_in_skills/theme-factory/themes/botanical-garden.md +19 -0
- docagent_cli/built_in_skills/theme-factory/themes/desert-rose.md +19 -0
- docagent_cli/built_in_skills/theme-factory/themes/forest-canopy.md +19 -0
- docagent_cli/built_in_skills/theme-factory/themes/golden-hour.md +19 -0
- docagent_cli/built_in_skills/theme-factory/themes/midnight-galaxy.md +19 -0
- docagent_cli/built_in_skills/theme-factory/themes/modern-minimalist.md +19 -0
- docagent_cli/built_in_skills/theme-factory/themes/ocean-depths.md +19 -0
- docagent_cli/built_in_skills/theme-factory/themes/sunset-boulevard.md +19 -0
- docagent_cli/built_in_skills/theme-factory/themes/tech-innovation.md +19 -0
- docagent_cli/built_in_skills/xlsx/LICENSE.txt +30 -0
- docagent_cli/built_in_skills/xlsx/SKILL.md +292 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/helpers/__init__.py +0 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/helpers/merge_runs.py +199 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/helpers/simplify_redlines.py +197 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/pack.py +159 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/mce/mc.xsd +75 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/soffice.py +183 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/unpack.py +132 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/validate.py +111 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/validators/__init__.py +15 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/validators/base.py +847 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/validators/docx.py +446 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/validators/pptx.py +275 -0
- docagent_cli/built_in_skills/xlsx/scripts/office/validators/redlining.py +247 -0
- docagent_cli/built_in_skills/xlsx/scripts/recalc.py +184 -0
- docagent_cli/clipboard.py +128 -0
- docagent_cli/command_registry.py +284 -0
- docagent_cli/config.py +2418 -0
- docagent_cli/configurable_model.py +162 -0
- docagent_cli/default_agent_prompt.md +12 -0
- docagent_cli/editor.py +142 -0
- docagent_cli/file_ops.py +473 -0
- docagent_cli/formatting.py +28 -0
- docagent_cli/hooks.py +206 -0
- docagent_cli/input.py +787 -0
- docagent_cli/integrations/__init__.py +1 -0
- docagent_cli/integrations/sandbox_factory.py +873 -0
- docagent_cli/integrations/sandbox_provider.py +71 -0
- docagent_cli/local_context.py +718 -0
- docagent_cli/main.py +1641 -0
- docagent_cli/mcp_tools.py +707 -0
- docagent_cli/mcp_trust.py +168 -0
- docagent_cli/media_utils.py +478 -0
- docagent_cli/model_config.py +1620 -0
- docagent_cli/non_interactive.py +948 -0
- docagent_cli/offload.py +371 -0
- docagent_cli/output.py +69 -0
- docagent_cli/project_utils.py +188 -0
- docagent_cli/py.typed +0 -0
- docagent_cli/remote_client.py +515 -0
- docagent_cli/server.py +520 -0
- docagent_cli/server_graph.py +196 -0
- docagent_cli/server_manager.py +365 -0
- docagent_cli/sessions.py +1262 -0
- docagent_cli/skills/__init__.py +18 -0
- docagent_cli/skills/commands.py +1090 -0
- docagent_cli/skills/load.py +192 -0
- docagent_cli/subagents.py +173 -0
- docagent_cli/system_prompt.md +247 -0
- docagent_cli/textual_adapter.py +1352 -0
- docagent_cli/theme.py +842 -0
- docagent_cli/token_state.py +31 -0
- docagent_cli/tool_display.py +298 -0
- docagent_cli/tools.py +236 -0
- docagent_cli/ui.py +420 -0
- docagent_cli/unicode_security.py +516 -0
- docagent_cli/update_check.py +454 -0
- docagent_cli/widgets/__init__.py +9 -0
- docagent_cli/widgets/_links.py +63 -0
- docagent_cli/widgets/approval.py +442 -0
- docagent_cli/widgets/ask_user.py +398 -0
- docagent_cli/widgets/autocomplete.py +691 -0
- docagent_cli/widgets/chat_input.py +1827 -0
- docagent_cli/widgets/diff.py +248 -0
- docagent_cli/widgets/history.py +188 -0
- docagent_cli/widgets/loading.py +177 -0
- docagent_cli/widgets/mcp_viewer.py +362 -0
- docagent_cli/widgets/message_store.py +675 -0
- docagent_cli/widgets/messages.py +1751 -0
- docagent_cli/widgets/model_selector.py +964 -0
- docagent_cli/widgets/status.py +372 -0
- docagent_cli/widgets/theme_selector.py +164 -0
- docagent_cli/widgets/thread_selector.py +1905 -0
- docagent_cli/widgets/tool_renderers.py +148 -0
- docagent_cli/widgets/tool_widgets.py +274 -0
- docagent_cli/widgets/welcome.py +339 -0
- docagent_cli-0.0.35.data/data/docagent_cli/default_agent_prompt.md +12 -0
- docagent_cli-0.0.35.dist-info/METADATA +200 -0
- docagent_cli-0.0.35.dist-info/RECORD +300 -0
- docagent_cli-0.0.35.dist-info/WHEEL +4 -0
- docagent_cli-0.0.35.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
"""Enhanced diff widget for displaying unified diffs."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
from typing import TYPE_CHECKING, Any
|
|
7
|
+
|
|
8
|
+
from textual.containers import Vertical
|
|
9
|
+
from textual.content import Content
|
|
10
|
+
from textual.widgets import Static
|
|
11
|
+
|
|
12
|
+
from docagent_cli import theme
|
|
13
|
+
from docagent_cli.config import get_glyphs, is_ascii_mode
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from textual.app import ComposeResult
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def compose_diff_lines(
|
|
20
|
+
diff: str,
|
|
21
|
+
max_lines: int | None = 100,
|
|
22
|
+
) -> ComposeResult:
|
|
23
|
+
"""Yield per-line Static widgets for a unified diff.
|
|
24
|
+
|
|
25
|
+
Each added/removed line gets a CSS class (`.diff-line-added`,
|
|
26
|
+
`.diff-line-removed`) so background colors are driven by CSS variables
|
|
27
|
+
and update automatically on theme change.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
diff: Unified diff string.
|
|
31
|
+
max_lines: Maximum number of diff lines to show (None for unlimited).
|
|
32
|
+
|
|
33
|
+
Yields:
|
|
34
|
+
Static widgets — one per diff line — with appropriate CSS classes.
|
|
35
|
+
"""
|
|
36
|
+
if not diff:
|
|
37
|
+
yield Static(Content.styled("No changes detected", "dim"))
|
|
38
|
+
else:
|
|
39
|
+
yield from _compose_diff_content(diff, max_lines)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _compose_diff_content(
|
|
43
|
+
diff: str,
|
|
44
|
+
max_lines: int | None,
|
|
45
|
+
) -> ComposeResult:
|
|
46
|
+
"""Yield styled diff line widgets for non-empty diff content.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
diff: Non-empty unified diff string.
|
|
50
|
+
max_lines: Maximum number of diff lines to show (None for unlimited).
|
|
51
|
+
|
|
52
|
+
Yields:
|
|
53
|
+
Static widgets for stats header and individual diff lines.
|
|
54
|
+
"""
|
|
55
|
+
colors = theme.get_theme_colors()
|
|
56
|
+
glyphs = get_glyphs()
|
|
57
|
+
lines = diff.splitlines()
|
|
58
|
+
|
|
59
|
+
# Compute stats first
|
|
60
|
+
additions = sum(
|
|
61
|
+
1 for ln in lines if ln.startswith("+") and not ln.startswith("+++")
|
|
62
|
+
)
|
|
63
|
+
deletions = sum(
|
|
64
|
+
1 for ln in lines if ln.startswith("-") and not ln.startswith("---")
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
# Stats header
|
|
68
|
+
stats_parts: list[str | tuple[str, str] | Content] = []
|
|
69
|
+
if additions:
|
|
70
|
+
stats_parts.append((f"+{additions}", colors.success))
|
|
71
|
+
if deletions:
|
|
72
|
+
if stats_parts:
|
|
73
|
+
stats_parts.append(" ")
|
|
74
|
+
stats_parts.append((f"-{deletions}", colors.error))
|
|
75
|
+
if stats_parts:
|
|
76
|
+
yield Static(Content.assemble(*stats_parts))
|
|
77
|
+
|
|
78
|
+
# Find max line number for width calculation
|
|
79
|
+
max_line = 0
|
|
80
|
+
for line in lines:
|
|
81
|
+
if m := re.match(r"@@ -(\d+)(?:,\d+)? \+(\d+)", line):
|
|
82
|
+
max_line = max(max_line, int(m.group(1)), int(m.group(2)))
|
|
83
|
+
width = max(3, len(str(max_line + len(lines))))
|
|
84
|
+
|
|
85
|
+
old_num = new_num = 0
|
|
86
|
+
line_count = 0
|
|
87
|
+
|
|
88
|
+
for line in lines:
|
|
89
|
+
if max_lines and line_count >= max_lines:
|
|
90
|
+
yield Static(
|
|
91
|
+
Content.styled(f"\n... ({len(lines) - line_count} more lines)", "dim")
|
|
92
|
+
)
|
|
93
|
+
break
|
|
94
|
+
|
|
95
|
+
# Skip file headers (--- and +++)
|
|
96
|
+
if line.startswith(("---", "+++")):
|
|
97
|
+
continue
|
|
98
|
+
|
|
99
|
+
# Handle hunk headers - just update line numbers, don't display
|
|
100
|
+
if m := re.match(r"@@ -(\d+)(?:,\d+)? \+(\d+)", line):
|
|
101
|
+
old_num, new_num = int(m.group(1)), int(m.group(2))
|
|
102
|
+
continue
|
|
103
|
+
|
|
104
|
+
# Handle diff lines - use gutter bar instead of +/- prefix
|
|
105
|
+
content = line[1:] if line else ""
|
|
106
|
+
|
|
107
|
+
if line.startswith("-"):
|
|
108
|
+
# Deletion — red gutter bar, background via CSS
|
|
109
|
+
yield Static(
|
|
110
|
+
Content.assemble(
|
|
111
|
+
(f"{glyphs.gutter_bar}", f"{colors.error} bold"),
|
|
112
|
+
(f"{old_num:>{width}}", "dim"),
|
|
113
|
+
f" {content}",
|
|
114
|
+
),
|
|
115
|
+
classes="diff-line-removed",
|
|
116
|
+
)
|
|
117
|
+
old_num += 1
|
|
118
|
+
line_count += 1
|
|
119
|
+
elif line.startswith("+"):
|
|
120
|
+
# Addition — green gutter bar, background via CSS
|
|
121
|
+
yield Static(
|
|
122
|
+
Content.assemble(
|
|
123
|
+
(f"{glyphs.gutter_bar}", f"{colors.success} bold"),
|
|
124
|
+
(f"{new_num:>{width}}", "dim"),
|
|
125
|
+
f" {content}",
|
|
126
|
+
),
|
|
127
|
+
classes="diff-line-added",
|
|
128
|
+
)
|
|
129
|
+
new_num += 1
|
|
130
|
+
line_count += 1
|
|
131
|
+
elif line.startswith(" "):
|
|
132
|
+
# Context line — dim gutter
|
|
133
|
+
yield Static(
|
|
134
|
+
Content.assemble(
|
|
135
|
+
(f"{glyphs.box_vertical}{old_num:>{width}}", "dim"),
|
|
136
|
+
f" {content}",
|
|
137
|
+
),
|
|
138
|
+
)
|
|
139
|
+
old_num += 1
|
|
140
|
+
new_num += 1
|
|
141
|
+
line_count += 1
|
|
142
|
+
elif line.strip() == "...":
|
|
143
|
+
# Truncation marker
|
|
144
|
+
yield Static(Content.styled("...", "dim"))
|
|
145
|
+
line_count += 1
|
|
146
|
+
else:
|
|
147
|
+
# Unrecognized diff line (e.g., "")
|
|
148
|
+
yield Static(Content.styled(line, "dim"))
|
|
149
|
+
line_count += 1
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class EnhancedDiff(Vertical):
|
|
153
|
+
"""Widget for displaying a unified diff with syntax highlighting."""
|
|
154
|
+
|
|
155
|
+
DEFAULT_CSS = """
|
|
156
|
+
EnhancedDiff {
|
|
157
|
+
height: auto;
|
|
158
|
+
padding: 1;
|
|
159
|
+
background: $surface-darken-1;
|
|
160
|
+
border: round $primary;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
EnhancedDiff .diff-title {
|
|
164
|
+
color: $primary;
|
|
165
|
+
text-style: bold;
|
|
166
|
+
margin-bottom: 1;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
EnhancedDiff .diff-content {
|
|
170
|
+
height: auto;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
EnhancedDiff .diff-stats {
|
|
174
|
+
color: $text-muted;
|
|
175
|
+
margin-top: 1;
|
|
176
|
+
}
|
|
177
|
+
"""
|
|
178
|
+
|
|
179
|
+
def __init__(
|
|
180
|
+
self,
|
|
181
|
+
diff: str,
|
|
182
|
+
title: str = "Diff",
|
|
183
|
+
max_lines: int | None = 100,
|
|
184
|
+
**kwargs: Any,
|
|
185
|
+
) -> None:
|
|
186
|
+
"""Initialize the diff widget.
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
diff: Unified diff string
|
|
190
|
+
title: Title to display above the diff
|
|
191
|
+
max_lines: Maximum number of diff lines to show
|
|
192
|
+
**kwargs: Additional arguments passed to parent
|
|
193
|
+
"""
|
|
194
|
+
super().__init__(**kwargs)
|
|
195
|
+
self._diff = diff
|
|
196
|
+
self._title = title
|
|
197
|
+
self._max_lines = max_lines
|
|
198
|
+
self._stats = self._compute_stats()
|
|
199
|
+
|
|
200
|
+
def _compute_stats(self) -> tuple[int, int]:
|
|
201
|
+
"""Compute additions and deletions count.
|
|
202
|
+
|
|
203
|
+
Returns:
|
|
204
|
+
Tuple of (additions count, deletions count).
|
|
205
|
+
"""
|
|
206
|
+
additions = 0
|
|
207
|
+
deletions = 0
|
|
208
|
+
for line in self._diff.splitlines():
|
|
209
|
+
if line.startswith("+") and not line.startswith("+++"):
|
|
210
|
+
additions += 1
|
|
211
|
+
elif line.startswith("-") and not line.startswith("---"):
|
|
212
|
+
deletions += 1
|
|
213
|
+
return additions, deletions
|
|
214
|
+
|
|
215
|
+
def on_mount(self) -> None:
|
|
216
|
+
"""Set border style based on charset mode."""
|
|
217
|
+
if is_ascii_mode():
|
|
218
|
+
colors = theme.get_theme_colors(self)
|
|
219
|
+
self.styles.border = ("ascii", colors.primary)
|
|
220
|
+
|
|
221
|
+
def compose(self) -> ComposeResult:
|
|
222
|
+
"""Compose the diff widget layout.
|
|
223
|
+
|
|
224
|
+
Yields:
|
|
225
|
+
Widgets for title, formatted diff content, and stats.
|
|
226
|
+
"""
|
|
227
|
+
colors = theme.get_theme_colors(self)
|
|
228
|
+
glyphs = get_glyphs()
|
|
229
|
+
h = glyphs.box_double_horizontal
|
|
230
|
+
yield Static(
|
|
231
|
+
Content.styled(
|
|
232
|
+
f"{h}{h}{h} {self._title} {h}{h}{h}", f"bold {colors.primary}"
|
|
233
|
+
),
|
|
234
|
+
classes="diff-title",
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
yield from compose_diff_lines(self._diff, self._max_lines)
|
|
238
|
+
|
|
239
|
+
additions, deletions = self._stats
|
|
240
|
+
if additions or deletions:
|
|
241
|
+
content_parts: list[str | tuple[str, str]] = []
|
|
242
|
+
if additions:
|
|
243
|
+
content_parts.append((f"+{additions}", colors.success))
|
|
244
|
+
if deletions:
|
|
245
|
+
if content_parts:
|
|
246
|
+
content_parts.append(" ")
|
|
247
|
+
content_parts.append((f"-{deletions}", colors.error))
|
|
248
|
+
yield Static(Content.assemble(*content_parts), classes="diff-stats")
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"""Command history manager for input persistence."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import logging
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class HistoryManager:
|
|
16
|
+
"""Manages command history with file persistence.
|
|
17
|
+
|
|
18
|
+
Uses append-only writes for concurrent safety. Multiple agents can
|
|
19
|
+
safely write to the same history file without corruption.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def __init__(self, history_file: Path, max_entries: int = 100) -> None:
|
|
23
|
+
"""Initialize the history manager.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
history_file: Path to the JSON-lines history file
|
|
27
|
+
max_entries: Maximum number of entries to keep
|
|
28
|
+
"""
|
|
29
|
+
self.history_file = history_file
|
|
30
|
+
self.max_entries = max_entries
|
|
31
|
+
self._entries: list[str] = []
|
|
32
|
+
self._current_index: int = -1
|
|
33
|
+
self._temp_input: str = ""
|
|
34
|
+
self._query: str = ""
|
|
35
|
+
self._load_history()
|
|
36
|
+
|
|
37
|
+
def _load_history(self) -> None:
|
|
38
|
+
"""Load history from file."""
|
|
39
|
+
if not self.history_file.exists():
|
|
40
|
+
return
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
with self.history_file.open("r", encoding="utf-8") as f:
|
|
44
|
+
entries = []
|
|
45
|
+
for raw_line in f:
|
|
46
|
+
line = raw_line.rstrip("\n\r")
|
|
47
|
+
if not line:
|
|
48
|
+
continue
|
|
49
|
+
try:
|
|
50
|
+
entry = json.loads(line)
|
|
51
|
+
except json.JSONDecodeError:
|
|
52
|
+
entry = line
|
|
53
|
+
entries.append(entry if isinstance(entry, str) else str(entry))
|
|
54
|
+
self._entries = entries[-self.max_entries :]
|
|
55
|
+
except (OSError, UnicodeDecodeError):
|
|
56
|
+
logger.warning(
|
|
57
|
+
"Failed to load history from %s; starting with empty history",
|
|
58
|
+
self.history_file,
|
|
59
|
+
exc_info=True,
|
|
60
|
+
)
|
|
61
|
+
self._entries = []
|
|
62
|
+
|
|
63
|
+
def _append_to_file(self, text: str) -> None:
|
|
64
|
+
"""Append a single entry to history file (concurrent-safe)."""
|
|
65
|
+
try:
|
|
66
|
+
self.history_file.parent.mkdir(parents=True, exist_ok=True)
|
|
67
|
+
with self.history_file.open("a", encoding="utf-8") as f:
|
|
68
|
+
f.write(json.dumps(text) + "\n")
|
|
69
|
+
except OSError:
|
|
70
|
+
logger.warning(
|
|
71
|
+
"Failed to append history entry to %s",
|
|
72
|
+
self.history_file,
|
|
73
|
+
exc_info=True,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
def _compact_history(self) -> None:
|
|
77
|
+
"""Rewrite history file to remove old entries.
|
|
78
|
+
|
|
79
|
+
Only called when entries exceed 2x max_entries to minimize rewrites.
|
|
80
|
+
"""
|
|
81
|
+
try:
|
|
82
|
+
self.history_file.parent.mkdir(parents=True, exist_ok=True)
|
|
83
|
+
with self.history_file.open("w", encoding="utf-8") as f:
|
|
84
|
+
for entry in self._entries:
|
|
85
|
+
f.write(json.dumps(entry) + "\n")
|
|
86
|
+
except OSError:
|
|
87
|
+
logger.warning(
|
|
88
|
+
"Failed to compact history file %s",
|
|
89
|
+
self.history_file,
|
|
90
|
+
exc_info=True,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
def add(self, text: str) -> None:
|
|
94
|
+
"""Add a command to history.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
text: The command text to add
|
|
98
|
+
"""
|
|
99
|
+
text = text.strip()
|
|
100
|
+
# Skip empty or slash commands
|
|
101
|
+
if not text or text.startswith("/"):
|
|
102
|
+
return
|
|
103
|
+
|
|
104
|
+
# Skip duplicates of the last entry
|
|
105
|
+
if self._entries and self._entries[-1] == text:
|
|
106
|
+
return
|
|
107
|
+
|
|
108
|
+
self._entries.append(text)
|
|
109
|
+
|
|
110
|
+
# Append to file (fast, concurrent-safe)
|
|
111
|
+
self._append_to_file(text)
|
|
112
|
+
|
|
113
|
+
# Compact only when we have 2x max entries (rare operation)
|
|
114
|
+
if len(self._entries) > self.max_entries * 2:
|
|
115
|
+
self._entries = self._entries[-self.max_entries :]
|
|
116
|
+
self._compact_history()
|
|
117
|
+
|
|
118
|
+
self.reset_navigation()
|
|
119
|
+
|
|
120
|
+
def get_previous(self, current_input: str, *, query: str = "") -> str | None:
|
|
121
|
+
"""Get the previous history entry matching a substring query.
|
|
122
|
+
|
|
123
|
+
The query is captured on the first call of a navigation session
|
|
124
|
+
(when `_current_index == -1`) and reused for all subsequent calls until
|
|
125
|
+
`reset_navigation`. Passing a different value on later calls has
|
|
126
|
+
no effect.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
current_input: Current input text. Saved only on the first call of a
|
|
130
|
+
navigation session; ignored on subsequent calls.
|
|
131
|
+
query: Substring to match against history entries.
|
|
132
|
+
Captured once on the first call of a navigation session.
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
Previous matching entry or `None`.
|
|
136
|
+
"""
|
|
137
|
+
if not self._entries:
|
|
138
|
+
return None
|
|
139
|
+
|
|
140
|
+
# Save current input and capture query on first navigation
|
|
141
|
+
if self._current_index == -1:
|
|
142
|
+
self._temp_input = current_input
|
|
143
|
+
self._current_index = len(self._entries)
|
|
144
|
+
self._query = query.strip().lower()
|
|
145
|
+
|
|
146
|
+
# Search backwards for matching entry
|
|
147
|
+
for i in range(self._current_index - 1, -1, -1):
|
|
148
|
+
if not self._query or self._query in self._entries[i].lower():
|
|
149
|
+
self._current_index = i
|
|
150
|
+
return self._entries[i]
|
|
151
|
+
|
|
152
|
+
return None
|
|
153
|
+
|
|
154
|
+
def get_next(self) -> str | None:
|
|
155
|
+
"""Get the next history entry matching the stored query.
|
|
156
|
+
|
|
157
|
+
Uses the query captured by the most recent `get_previous` call.
|
|
158
|
+
|
|
159
|
+
Returns:
|
|
160
|
+
The next matching entry, or the original input when past the newest
|
|
161
|
+
match.
|
|
162
|
+
|
|
163
|
+
`None` if not currently navigating history.
|
|
164
|
+
"""
|
|
165
|
+
if self._current_index == -1:
|
|
166
|
+
return None
|
|
167
|
+
|
|
168
|
+
# Search forwards for matching entry
|
|
169
|
+
for i in range(self._current_index + 1, len(self._entries)):
|
|
170
|
+
if not self._query or self._query in self._entries[i].lower():
|
|
171
|
+
self._current_index = i
|
|
172
|
+
return self._entries[i]
|
|
173
|
+
|
|
174
|
+
# Return to original input at the end
|
|
175
|
+
result = self._temp_input
|
|
176
|
+
self.reset_navigation()
|
|
177
|
+
return result
|
|
178
|
+
|
|
179
|
+
@property
|
|
180
|
+
def in_history(self) -> bool:
|
|
181
|
+
"""Whether currently navigating history entries."""
|
|
182
|
+
return self._current_index >= 0
|
|
183
|
+
|
|
184
|
+
def reset_navigation(self) -> None:
|
|
185
|
+
"""Reset navigation state."""
|
|
186
|
+
self._current_index = -1
|
|
187
|
+
self._temp_input = ""
|
|
188
|
+
self._query = ""
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"""Loading widget with animated spinner for agent activity."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from time import time
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
from textual.containers import Horizontal
|
|
9
|
+
from textual.content import Content
|
|
10
|
+
from textual.widgets import Static
|
|
11
|
+
|
|
12
|
+
from docagent_cli.config import get_glyphs
|
|
13
|
+
from docagent_cli.formatting import format_duration
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from textual.app import ComposeResult
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Spinner:
|
|
20
|
+
"""Animated spinner using charset-appropriate frames."""
|
|
21
|
+
|
|
22
|
+
def __init__(self) -> None:
|
|
23
|
+
"""Initialize spinner."""
|
|
24
|
+
self._position = 0
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def frames(self) -> tuple[str, ...]:
|
|
28
|
+
"""Get spinner frames from glyphs config."""
|
|
29
|
+
return get_glyphs().spinner_frames
|
|
30
|
+
|
|
31
|
+
def next_frame(self) -> str:
|
|
32
|
+
"""Get next animation frame.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
The next spinner character in the animation sequence.
|
|
36
|
+
"""
|
|
37
|
+
frames = self.frames
|
|
38
|
+
frame = frames[self._position]
|
|
39
|
+
self._position = (self._position + 1) % len(frames)
|
|
40
|
+
return frame
|
|
41
|
+
|
|
42
|
+
def current_frame(self) -> str:
|
|
43
|
+
"""Get current frame without advancing.
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
The current spinner character.
|
|
47
|
+
"""
|
|
48
|
+
return self.frames[self._position]
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class LoadingWidget(Static):
|
|
52
|
+
"""Animated loading indicator with status text and elapsed time.
|
|
53
|
+
|
|
54
|
+
Displays: <spinner> Thinking... (3s, esc to interrupt)
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
DEFAULT_CSS = """
|
|
58
|
+
LoadingWidget {
|
|
59
|
+
height: auto;
|
|
60
|
+
padding: 0 1;
|
|
61
|
+
margin-top: 1;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
LoadingWidget .loading-container {
|
|
65
|
+
height: auto;
|
|
66
|
+
width: 100%;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
LoadingWidget .loading-spinner {
|
|
70
|
+
width: auto;
|
|
71
|
+
color: $primary;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
LoadingWidget .loading-status {
|
|
75
|
+
width: auto;
|
|
76
|
+
color: $primary;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
LoadingWidget .loading-hint {
|
|
80
|
+
width: auto;
|
|
81
|
+
color: $text-muted;
|
|
82
|
+
margin-left: 1;
|
|
83
|
+
}
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
def __init__(self, status: str = "Thinking") -> None:
|
|
87
|
+
"""Initialize loading widget.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
status: Initial status text to display
|
|
91
|
+
"""
|
|
92
|
+
super().__init__()
|
|
93
|
+
self._status = status
|
|
94
|
+
self._spinner = Spinner()
|
|
95
|
+
self._start_time: float | None = None
|
|
96
|
+
self._spinner_widget: Static | None = None
|
|
97
|
+
self._status_widget: Static | None = None
|
|
98
|
+
self._hint_widget: Static | None = None
|
|
99
|
+
self._paused = False
|
|
100
|
+
self._paused_elapsed: int = 0
|
|
101
|
+
|
|
102
|
+
def compose(self) -> ComposeResult:
|
|
103
|
+
"""Compose the loading widget layout.
|
|
104
|
+
|
|
105
|
+
Yields:
|
|
106
|
+
Widgets for spinner, status text, and hint.
|
|
107
|
+
"""
|
|
108
|
+
with Horizontal(classes="loading-container"):
|
|
109
|
+
self._spinner_widget = Static(
|
|
110
|
+
self._spinner.current_frame(), classes="loading-spinner"
|
|
111
|
+
)
|
|
112
|
+
yield self._spinner_widget
|
|
113
|
+
|
|
114
|
+
self._status_widget = Static(
|
|
115
|
+
f" {self._status}... ", classes="loading-status"
|
|
116
|
+
)
|
|
117
|
+
yield self._status_widget
|
|
118
|
+
|
|
119
|
+
self._hint_widget = Static("(0s, esc to interrupt)", classes="loading-hint")
|
|
120
|
+
yield self._hint_widget
|
|
121
|
+
|
|
122
|
+
def on_mount(self) -> None:
|
|
123
|
+
"""Start animation on mount."""
|
|
124
|
+
self._start_time = time()
|
|
125
|
+
self.set_interval(0.1, self._update_animation)
|
|
126
|
+
|
|
127
|
+
def _update_animation(self) -> None:
|
|
128
|
+
"""Update spinner and elapsed time."""
|
|
129
|
+
if self._paused:
|
|
130
|
+
return
|
|
131
|
+
|
|
132
|
+
if self._spinner_widget:
|
|
133
|
+
frame = self._spinner.next_frame()
|
|
134
|
+
self._spinner_widget.update(frame)
|
|
135
|
+
|
|
136
|
+
if self._hint_widget and self._start_time is not None:
|
|
137
|
+
elapsed = int(time() - self._start_time)
|
|
138
|
+
self._hint_widget.update(f"({format_duration(elapsed)}, esc to interrupt)")
|
|
139
|
+
|
|
140
|
+
def set_status(self, status: str) -> None:
|
|
141
|
+
"""Update the status text.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
status: New status text
|
|
145
|
+
"""
|
|
146
|
+
self._status = status
|
|
147
|
+
if self._status_widget:
|
|
148
|
+
self._status_widget.update(f" {self._status}... ")
|
|
149
|
+
|
|
150
|
+
def pause(self, status: str = "Awaiting decision") -> None:
|
|
151
|
+
"""Pause the animation and update status.
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
status: Status to show while paused
|
|
155
|
+
"""
|
|
156
|
+
self._paused = True
|
|
157
|
+
if self._start_time is not None:
|
|
158
|
+
self._paused_elapsed = int(time() - self._start_time)
|
|
159
|
+
self._status = status
|
|
160
|
+
if self._status_widget:
|
|
161
|
+
self._status_widget.update(f" {status}... ")
|
|
162
|
+
if self._hint_widget:
|
|
163
|
+
self._hint_widget.update(
|
|
164
|
+
f"(paused at {format_duration(self._paused_elapsed)})"
|
|
165
|
+
)
|
|
166
|
+
if self._spinner_widget:
|
|
167
|
+
self._spinner_widget.update(Content.styled(get_glyphs().pause, "dim"))
|
|
168
|
+
|
|
169
|
+
def resume(self) -> None:
|
|
170
|
+
"""Resume the animation."""
|
|
171
|
+
self._paused = False
|
|
172
|
+
self._status = "Thinking"
|
|
173
|
+
if self._status_widget:
|
|
174
|
+
self._status_widget.update(f" {self._status}... ")
|
|
175
|
+
|
|
176
|
+
def stop(self) -> None:
|
|
177
|
+
"""Stop the animation (widget will be removed by caller)."""
|