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.
Files changed (300) hide show
  1. docagent_cli/__init__.py +36 -0
  2. docagent_cli/__main__.py +6 -0
  3. docagent_cli/_ask_user_types.py +90 -0
  4. docagent_cli/_cli_context.py +27 -0
  5. docagent_cli/_debug.py +52 -0
  6. docagent_cli/_env_vars.py +56 -0
  7. docagent_cli/_server_config.py +352 -0
  8. docagent_cli/_session_stats.py +114 -0
  9. docagent_cli/_testing_models.py +144 -0
  10. docagent_cli/_version.py +17 -0
  11. docagent_cli/agent.py +1193 -0
  12. docagent_cli/app.py +4979 -0
  13. docagent_cli/app.tcss +283 -0
  14. docagent_cli/ask_user.py +301 -0
  15. docagent_cli/built_in_skills/__init__.py +5 -0
  16. docagent_cli/built_in_skills/doc-coauthoring/SKILL.md +375 -0
  17. docagent_cli/built_in_skills/docx/LICENSE.txt +30 -0
  18. docagent_cli/built_in_skills/docx/SKILL.md +590 -0
  19. docagent_cli/built_in_skills/docx/scripts/__init__.py +1 -0
  20. docagent_cli/built_in_skills/docx/scripts/accept_changes.py +135 -0
  21. docagent_cli/built_in_skills/docx/scripts/comment.py +318 -0
  22. docagent_cli/built_in_skills/docx/scripts/office/helpers/__init__.py +0 -0
  23. docagent_cli/built_in_skills/docx/scripts/office/helpers/merge_runs.py +199 -0
  24. docagent_cli/built_in_skills/docx/scripts/office/helpers/simplify_redlines.py +197 -0
  25. docagent_cli/built_in_skills/docx/scripts/office/pack.py +159 -0
  26. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  27. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  28. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  29. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  30. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  31. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  32. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  33. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  34. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  35. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  36. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  37. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  38. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  39. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  40. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  41. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  42. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  43. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  44. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  45. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  46. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  47. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  48. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  49. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  50. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  51. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  52. docagent_cli/built_in_skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  53. docagent_cli/built_in_skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  54. docagent_cli/built_in_skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  55. docagent_cli/built_in_skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  56. docagent_cli/built_in_skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  57. docagent_cli/built_in_skills/docx/scripts/office/schemas/mce/mc.xsd +75 -0
  58. docagent_cli/built_in_skills/docx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
  59. docagent_cli/built_in_skills/docx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
  60. docagent_cli/built_in_skills/docx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
  61. docagent_cli/built_in_skills/docx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
  62. docagent_cli/built_in_skills/docx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
  63. docagent_cli/built_in_skills/docx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  64. docagent_cli/built_in_skills/docx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
  65. docagent_cli/built_in_skills/docx/scripts/office/soffice.py +183 -0
  66. docagent_cli/built_in_skills/docx/scripts/office/unpack.py +132 -0
  67. docagent_cli/built_in_skills/docx/scripts/office/validate.py +111 -0
  68. docagent_cli/built_in_skills/docx/scripts/office/validators/__init__.py +15 -0
  69. docagent_cli/built_in_skills/docx/scripts/office/validators/base.py +847 -0
  70. docagent_cli/built_in_skills/docx/scripts/office/validators/docx.py +446 -0
  71. docagent_cli/built_in_skills/docx/scripts/office/validators/pptx.py +275 -0
  72. docagent_cli/built_in_skills/docx/scripts/office/validators/redlining.py +247 -0
  73. docagent_cli/built_in_skills/docx/scripts/templates/comments.xml +3 -0
  74. docagent_cli/built_in_skills/docx/scripts/templates/commentsExtended.xml +3 -0
  75. docagent_cli/built_in_skills/docx/scripts/templates/commentsExtensible.xml +3 -0
  76. docagent_cli/built_in_skills/docx/scripts/templates/commentsIds.xml +3 -0
  77. docagent_cli/built_in_skills/docx/scripts/templates/people.xml +3 -0
  78. docagent_cli/built_in_skills/pdf/LICENSE.txt +30 -0
  79. docagent_cli/built_in_skills/pdf/SKILL.md +314 -0
  80. docagent_cli/built_in_skills/pdf/forms.md +294 -0
  81. docagent_cli/built_in_skills/pdf/reference.md +612 -0
  82. docagent_cli/built_in_skills/pdf/scripts/check_bounding_boxes.py +65 -0
  83. docagent_cli/built_in_skills/pdf/scripts/check_fillable_fields.py +11 -0
  84. docagent_cli/built_in_skills/pdf/scripts/convert_pdf_to_images.py +33 -0
  85. docagent_cli/built_in_skills/pdf/scripts/create_validation_image.py +37 -0
  86. docagent_cli/built_in_skills/pdf/scripts/extract_form_field_info.py +122 -0
  87. docagent_cli/built_in_skills/pdf/scripts/extract_form_structure.py +115 -0
  88. docagent_cli/built_in_skills/pdf/scripts/fill_fillable_fields.py +98 -0
  89. docagent_cli/built_in_skills/pdf/scripts/fill_pdf_form_with_annotations.py +107 -0
  90. docagent_cli/built_in_skills/pptx/LICENSE.txt +30 -0
  91. docagent_cli/built_in_skills/pptx/SKILL.md +232 -0
  92. docagent_cli/built_in_skills/pptx/editing.md +205 -0
  93. docagent_cli/built_in_skills/pptx/pptxgenjs.md +420 -0
  94. docagent_cli/built_in_skills/pptx/scripts/__init__.py +0 -0
  95. docagent_cli/built_in_skills/pptx/scripts/add_slide.py +195 -0
  96. docagent_cli/built_in_skills/pptx/scripts/clean.py +286 -0
  97. docagent_cli/built_in_skills/pptx/scripts/office/helpers/__init__.py +0 -0
  98. docagent_cli/built_in_skills/pptx/scripts/office/helpers/merge_runs.py +199 -0
  99. docagent_cli/built_in_skills/pptx/scripts/office/helpers/simplify_redlines.py +197 -0
  100. docagent_cli/built_in_skills/pptx/scripts/office/pack.py +159 -0
  101. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  102. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  103. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  104. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  105. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  106. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  107. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  108. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  109. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  110. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  111. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  112. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  113. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  114. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  115. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  116. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  117. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  118. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  119. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  120. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  121. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  122. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  123. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  124. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  125. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  126. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  127. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  128. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  129. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  130. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  131. docagent_cli/built_in_skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  132. docagent_cli/built_in_skills/pptx/scripts/office/schemas/mce/mc.xsd +75 -0
  133. docagent_cli/built_in_skills/pptx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
  134. docagent_cli/built_in_skills/pptx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
  135. docagent_cli/built_in_skills/pptx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
  136. docagent_cli/built_in_skills/pptx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
  137. docagent_cli/built_in_skills/pptx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
  138. docagent_cli/built_in_skills/pptx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  139. docagent_cli/built_in_skills/pptx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
  140. docagent_cli/built_in_skills/pptx/scripts/office/soffice.py +183 -0
  141. docagent_cli/built_in_skills/pptx/scripts/office/unpack.py +132 -0
  142. docagent_cli/built_in_skills/pptx/scripts/office/validate.py +111 -0
  143. docagent_cli/built_in_skills/pptx/scripts/office/validators/__init__.py +15 -0
  144. docagent_cli/built_in_skills/pptx/scripts/office/validators/base.py +847 -0
  145. docagent_cli/built_in_skills/pptx/scripts/office/validators/docx.py +446 -0
  146. docagent_cli/built_in_skills/pptx/scripts/office/validators/pptx.py +275 -0
  147. docagent_cli/built_in_skills/pptx/scripts/office/validators/redlining.py +247 -0
  148. docagent_cli/built_in_skills/pptx/scripts/thumbnail.py +289 -0
  149. docagent_cli/built_in_skills/remember/SKILL.md +118 -0
  150. docagent_cli/built_in_skills/skill-creator/LICENSE.txt +202 -0
  151. docagent_cli/built_in_skills/skill-creator/SKILL.md +485 -0
  152. docagent_cli/built_in_skills/skill-creator/agents/analyzer.md +274 -0
  153. docagent_cli/built_in_skills/skill-creator/agents/comparator.md +202 -0
  154. docagent_cli/built_in_skills/skill-creator/agents/grader.md +223 -0
  155. docagent_cli/built_in_skills/skill-creator/assets/eval_review.html +146 -0
  156. docagent_cli/built_in_skills/skill-creator/eval-viewer/generate_review.py +471 -0
  157. docagent_cli/built_in_skills/skill-creator/eval-viewer/viewer.html +1325 -0
  158. docagent_cli/built_in_skills/skill-creator/references/schemas.md +430 -0
  159. docagent_cli/built_in_skills/skill-creator/scripts/__init__.py +0 -0
  160. docagent_cli/built_in_skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  161. docagent_cli/built_in_skills/skill-creator/scripts/generate_report.py +326 -0
  162. docagent_cli/built_in_skills/skill-creator/scripts/improve_description.py +247 -0
  163. docagent_cli/built_in_skills/skill-creator/scripts/package_skill.py +136 -0
  164. docagent_cli/built_in_skills/skill-creator/scripts/quick_validate.py +103 -0
  165. docagent_cli/built_in_skills/skill-creator/scripts/run_eval.py +310 -0
  166. docagent_cli/built_in_skills/skill-creator/scripts/run_loop.py +328 -0
  167. docagent_cli/built_in_skills/skill-creator/scripts/utils.py +47 -0
  168. docagent_cli/built_in_skills/theme-factory/LICENSE.txt +202 -0
  169. docagent_cli/built_in_skills/theme-factory/SKILL.md +59 -0
  170. docagent_cli/built_in_skills/theme-factory/theme-showcase.pdf +0 -0
  171. docagent_cli/built_in_skills/theme-factory/themes/arctic-frost.md +19 -0
  172. docagent_cli/built_in_skills/theme-factory/themes/botanical-garden.md +19 -0
  173. docagent_cli/built_in_skills/theme-factory/themes/desert-rose.md +19 -0
  174. docagent_cli/built_in_skills/theme-factory/themes/forest-canopy.md +19 -0
  175. docagent_cli/built_in_skills/theme-factory/themes/golden-hour.md +19 -0
  176. docagent_cli/built_in_skills/theme-factory/themes/midnight-galaxy.md +19 -0
  177. docagent_cli/built_in_skills/theme-factory/themes/modern-minimalist.md +19 -0
  178. docagent_cli/built_in_skills/theme-factory/themes/ocean-depths.md +19 -0
  179. docagent_cli/built_in_skills/theme-factory/themes/sunset-boulevard.md +19 -0
  180. docagent_cli/built_in_skills/theme-factory/themes/tech-innovation.md +19 -0
  181. docagent_cli/built_in_skills/xlsx/LICENSE.txt +30 -0
  182. docagent_cli/built_in_skills/xlsx/SKILL.md +292 -0
  183. docagent_cli/built_in_skills/xlsx/scripts/office/helpers/__init__.py +0 -0
  184. docagent_cli/built_in_skills/xlsx/scripts/office/helpers/merge_runs.py +199 -0
  185. docagent_cli/built_in_skills/xlsx/scripts/office/helpers/simplify_redlines.py +197 -0
  186. docagent_cli/built_in_skills/xlsx/scripts/office/pack.py +159 -0
  187. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  188. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  189. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  190. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  191. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  192. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  193. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  194. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  195. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  196. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  197. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  198. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  199. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  200. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  201. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  202. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  203. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  204. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  205. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  206. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  207. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  208. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  209. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  210. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  211. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  212. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  213. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  214. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  215. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  216. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  217. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  218. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/mce/mc.xsd +75 -0
  219. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
  220. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
  221. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
  222. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
  223. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
  224. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  225. docagent_cli/built_in_skills/xlsx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
  226. docagent_cli/built_in_skills/xlsx/scripts/office/soffice.py +183 -0
  227. docagent_cli/built_in_skills/xlsx/scripts/office/unpack.py +132 -0
  228. docagent_cli/built_in_skills/xlsx/scripts/office/validate.py +111 -0
  229. docagent_cli/built_in_skills/xlsx/scripts/office/validators/__init__.py +15 -0
  230. docagent_cli/built_in_skills/xlsx/scripts/office/validators/base.py +847 -0
  231. docagent_cli/built_in_skills/xlsx/scripts/office/validators/docx.py +446 -0
  232. docagent_cli/built_in_skills/xlsx/scripts/office/validators/pptx.py +275 -0
  233. docagent_cli/built_in_skills/xlsx/scripts/office/validators/redlining.py +247 -0
  234. docagent_cli/built_in_skills/xlsx/scripts/recalc.py +184 -0
  235. docagent_cli/clipboard.py +128 -0
  236. docagent_cli/command_registry.py +284 -0
  237. docagent_cli/config.py +2418 -0
  238. docagent_cli/configurable_model.py +162 -0
  239. docagent_cli/default_agent_prompt.md +12 -0
  240. docagent_cli/editor.py +142 -0
  241. docagent_cli/file_ops.py +473 -0
  242. docagent_cli/formatting.py +28 -0
  243. docagent_cli/hooks.py +206 -0
  244. docagent_cli/input.py +787 -0
  245. docagent_cli/integrations/__init__.py +1 -0
  246. docagent_cli/integrations/sandbox_factory.py +873 -0
  247. docagent_cli/integrations/sandbox_provider.py +71 -0
  248. docagent_cli/local_context.py +718 -0
  249. docagent_cli/main.py +1641 -0
  250. docagent_cli/mcp_tools.py +707 -0
  251. docagent_cli/mcp_trust.py +168 -0
  252. docagent_cli/media_utils.py +478 -0
  253. docagent_cli/model_config.py +1620 -0
  254. docagent_cli/non_interactive.py +948 -0
  255. docagent_cli/offload.py +371 -0
  256. docagent_cli/output.py +69 -0
  257. docagent_cli/project_utils.py +188 -0
  258. docagent_cli/py.typed +0 -0
  259. docagent_cli/remote_client.py +515 -0
  260. docagent_cli/server.py +520 -0
  261. docagent_cli/server_graph.py +196 -0
  262. docagent_cli/server_manager.py +365 -0
  263. docagent_cli/sessions.py +1262 -0
  264. docagent_cli/skills/__init__.py +18 -0
  265. docagent_cli/skills/commands.py +1090 -0
  266. docagent_cli/skills/load.py +192 -0
  267. docagent_cli/subagents.py +173 -0
  268. docagent_cli/system_prompt.md +247 -0
  269. docagent_cli/textual_adapter.py +1352 -0
  270. docagent_cli/theme.py +842 -0
  271. docagent_cli/token_state.py +31 -0
  272. docagent_cli/tool_display.py +298 -0
  273. docagent_cli/tools.py +236 -0
  274. docagent_cli/ui.py +420 -0
  275. docagent_cli/unicode_security.py +516 -0
  276. docagent_cli/update_check.py +454 -0
  277. docagent_cli/widgets/__init__.py +9 -0
  278. docagent_cli/widgets/_links.py +63 -0
  279. docagent_cli/widgets/approval.py +442 -0
  280. docagent_cli/widgets/ask_user.py +398 -0
  281. docagent_cli/widgets/autocomplete.py +691 -0
  282. docagent_cli/widgets/chat_input.py +1827 -0
  283. docagent_cli/widgets/diff.py +248 -0
  284. docagent_cli/widgets/history.py +188 -0
  285. docagent_cli/widgets/loading.py +177 -0
  286. docagent_cli/widgets/mcp_viewer.py +362 -0
  287. docagent_cli/widgets/message_store.py +675 -0
  288. docagent_cli/widgets/messages.py +1751 -0
  289. docagent_cli/widgets/model_selector.py +964 -0
  290. docagent_cli/widgets/status.py +372 -0
  291. docagent_cli/widgets/theme_selector.py +164 -0
  292. docagent_cli/widgets/thread_selector.py +1905 -0
  293. docagent_cli/widgets/tool_renderers.py +148 -0
  294. docagent_cli/widgets/tool_widgets.py +274 -0
  295. docagent_cli/widgets/welcome.py +339 -0
  296. docagent_cli-0.0.35.data/data/docagent_cli/default_agent_prompt.md +12 -0
  297. docagent_cli-0.0.35.dist-info/METADATA +200 -0
  298. docagent_cli-0.0.35.dist-info/RECORD +300 -0
  299. docagent_cli-0.0.35.dist-info/WHEEL +4 -0
  300. 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)."""