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
docagent_cli/theme.py ADDED
@@ -0,0 +1,842 @@
1
+ """LangChain brand colors and semantic constants for the CLI.
2
+
3
+ Single source of truth for color values used in Python code (Rich markup,
4
+ `Content.styled`, `Content.from_markup`). CSS-side styling should reference
5
+ Textual CSS variables: built-in variables
6
+ (`$primary`, `$background`, `$text-muted`, `$error-muted`, etc.) are set via
7
+ `register_theme()` in `DeepAgentsApp.__init__`, while the few app-specific
8
+ variables (`$mode-bash`, `$mode-command`, `$skill`, `$skill-hover`, `$tool`,
9
+ `$tool-hover`) are backed by these constants via `App.get_theme_variable_defaults()`.
10
+
11
+ Code that needs custom CSS variable values should call
12
+ `get_css_variable_defaults(dark=...)`. For the full semantic color palette, look
13
+ up the `ThemeColors` instance via `ThemeEntry.REGISTRY`.
14
+
15
+ Users can define custom themes in `~/.docagent/config.toml` under
16
+ `[themes.<name>]` sections. Each new theme section must include `label` (str);
17
+ `dark` (bool) defaults to `False` if omitted (set to `True` for dark themes).
18
+ Color fields are optional and fall back to the built-in dark/light palette based
19
+ on the `dark` flag. Sections whose name matches a built-in theme override its
20
+ colors without replacing it. See `_load_user_themes()` for details.
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ import logging
26
+ import re
27
+ from dataclasses import dataclass, fields
28
+ from pathlib import Path
29
+ from types import MappingProxyType
30
+ from typing import TYPE_CHECKING, Any, ClassVar
31
+
32
+ if TYPE_CHECKING:
33
+ from collections.abc import Mapping
34
+
35
+ from textual.app import App
36
+
37
+ logger = logging.getLogger(__name__)
38
+
39
+ # ---------------------------------------------------------------------------
40
+ # Brand palette — dark (originally tokyonight-inspired, LangChain blue primary)
41
+ # ---------------------------------------------------------------------------
42
+ LC_DARK = "#11121D"
43
+ """Background — visible blue tint, distinguishable from pure black."""
44
+
45
+ LC_CARD = "#1A1B2E"
46
+ """Surface / card — clearly elevated above background."""
47
+
48
+ LC_BORDER_DK = "#25283B"
49
+ """Borders on dark backgrounds."""
50
+
51
+ LC_BORDER_LT = "#3A3E57"
52
+ """Borders on lighter / hovered backgrounds."""
53
+
54
+ LC_BODY = "#C0CAF5"
55
+ """Body text — high contrast on dark backgrounds."""
56
+
57
+ LC_BLUE = "#7AA2F7"
58
+ """Primary accent blue."""
59
+
60
+ LC_PURPLE = "#BB9AF7"
61
+ """Secondary accent / badges / labels."""
62
+
63
+ LC_GREEN = "#9ECE6A"
64
+ """Success / positive indicator."""
65
+
66
+ LC_AMBER = "#EB8B46"
67
+ """Warning / caution indicator."""
68
+
69
+ LC_PINK = "#F7768E"
70
+ """Error / destructive actions."""
71
+
72
+ LC_MUTED = "#545C7E"
73
+ """Muted / secondary text."""
74
+
75
+ LC_GREEN_BG = "#1C2A38"
76
+ """Subtle green-tinted background for diff additions."""
77
+
78
+ LC_PINK_BG = "#2A1F32"
79
+ """Subtle pink-tinted background for diff removals / errors."""
80
+
81
+ LC_PANEL = "#25283B"
82
+ """Panel — differentiated section background (above surface)."""
83
+
84
+ LC_SKILL = "#A78BFA"
85
+ """Skill invocation accent — border and header text."""
86
+
87
+ LC_SKILL_HOVER = "#C4B5FD"
88
+ """Skill invocation hover — lighter variant for interactive feedback."""
89
+
90
+ LC_TOOL = LC_AMBER
91
+ """Tool call accent — border and header text."""
92
+
93
+ LC_TOOL_HOVER = "#FFCB91"
94
+ """Tool call hover — lighter variant for interactive feedback."""
95
+
96
+
97
+ # ---------------------------------------------------------------------------
98
+ # Brand palette — light
99
+ # ---------------------------------------------------------------------------
100
+ LC_LIGHT_BG = "#F5F5F7"
101
+ """Background — warm neutral white."""
102
+
103
+ LC_LIGHT_SURFACE = "#EAEAEE"
104
+ """Surface / card — slightly darker than background."""
105
+
106
+ LC_LIGHT_BORDER = "#C8CAD0"
107
+ """Borders on light backgrounds."""
108
+
109
+ LC_LIGHT_BORDER_HVR = "#A0A4B0"
110
+ """Borders on hovered / focused surfaces."""
111
+
112
+ LC_LIGHT_BODY = "#24283B"
113
+ """Body text — high contrast on light backgrounds."""
114
+
115
+ LC_LIGHT_BLUE = "#2E5EAA"
116
+ """Primary accent blue (darkened for light bg contrast)."""
117
+
118
+ LC_LIGHT_PURPLE = "#7C3AED"
119
+ """Secondary accent (darkened for light bg contrast)."""
120
+
121
+ LC_LIGHT_GREEN = "#3A7D0A"
122
+ """Success / positive (darkened for light bg contrast)."""
123
+
124
+ LC_LIGHT_AMBER = "#B45309"
125
+ """Warning / caution (darkened for light bg contrast)."""
126
+
127
+ LC_LIGHT_PINK = "#BE185D"
128
+ """Error / destructive (darkened for light bg contrast)."""
129
+
130
+ LC_LIGHT_MUTED = "#6B7280"
131
+ """Muted / secondary text on light backgrounds."""
132
+
133
+ LC_LIGHT_GREEN_BG = "#DCFCE7"
134
+ """Subtle green-tinted background for diff additions."""
135
+
136
+ LC_LIGHT_PINK_BG = "#FEE2E2"
137
+ """Subtle pink-tinted background for diff removals / errors."""
138
+
139
+ LC_LIGHT_PANEL = "#E0E1E6"
140
+ """Panel for light theme — differentiated section background."""
141
+
142
+ LC_LIGHT_SKILL = "#7C3AED"
143
+ """Skill invocation accent (darkened for light bg contrast)."""
144
+
145
+ LC_LIGHT_SKILL_HOVER = "#6D28D9"
146
+ """Skill invocation hover (darkened for light bg contrast)."""
147
+
148
+ LC_LIGHT_TOOL = LC_LIGHT_AMBER
149
+ """Tool call accent (darkened for light bg contrast)."""
150
+
151
+ LC_LIGHT_TOOL_HOVER = "#78350F"
152
+ """Tool call hover (darkened for light bg contrast)."""
153
+
154
+
155
+ # ---------------------------------------------------------------------------
156
+ # Semantic constants (ANSI color names for Rich console output)
157
+ #
158
+ # These are ANSI color names resolved by the user's terminal palette, so they
159
+ # adapt to both dark and light terminal backgrounds automatically. They are
160
+ # used in Rich's `Console.print()` (non-interactive output, help screens,
161
+ # `non_interactive.py`, `main.py`).
162
+ #
163
+ # Textual widget code should NOT use these. Instead, call
164
+ # `get_theme_colors(self.app)` to obtain the active theme's `ThemeColors`
165
+ # (hex values), or reference CSS variables (`$primary`, `$muted`, etc.).
166
+ # ---------------------------------------------------------------------------
167
+ PRIMARY = "blue"
168
+ """Default accent for headings, borders, links, and active elements."""
169
+
170
+ PRIMARY_DEV = "bright_red"
171
+ """Accent used when running from an editable (dev) install."""
172
+
173
+ SUCCESS = "green"
174
+ """Positive outcomes — tool success, approved actions."""
175
+
176
+ WARNING = "yellow"
177
+ """Caution and notice states — auto-approve off, pending tool calls, notices."""
178
+
179
+ MUTED = "bright_black"
180
+ """De-emphasized text — timestamps, secondary labels."""
181
+
182
+ MODE_BASH = "red"
183
+ """Shell mode indicator — borders, prompts, and message prefixes."""
184
+
185
+ MODE_COMMAND = "magenta"
186
+ """Command mode indicator — borders, prompts, and message prefixes."""
187
+
188
+ # Diff colors
189
+ DIFF_ADD_FG = "green"
190
+ """Added-line foreground in inline diffs."""
191
+
192
+ DIFF_ADD_BG = "green"
193
+ """Added-line background in inline diffs."""
194
+
195
+ DIFF_REMOVE_FG = "red"
196
+ """Removed-line foreground in inline diffs."""
197
+
198
+ DIFF_REMOVE_BG = "red"
199
+ """Removed-line background in inline diffs."""
200
+
201
+ DIFF_CONTEXT = "bright_black"
202
+ """Unchanged context lines in inline diffs."""
203
+
204
+ # Tool call widget
205
+ TOOL_BORDER = "bright_black"
206
+ """Tool call card border."""
207
+
208
+ TOOL_HEADER = "yellow"
209
+ """Tool call headers, slash-command tokens, and approval-menu commands."""
210
+
211
+ # File listing colors
212
+ FILE_PYTHON = "blue"
213
+ """Python files in tool-call file listings."""
214
+
215
+ FILE_CONFIG = "yellow"
216
+ """Config / data files in tool-call file listings."""
217
+
218
+ FILE_DIR = "green"
219
+ """Directories in tool-call file listings."""
220
+
221
+ SPINNER = "blue"
222
+ """Loading spinner color."""
223
+
224
+
225
+ # ---------------------------------------------------------------------------
226
+ # Theme variant dataclass
227
+ # ---------------------------------------------------------------------------
228
+
229
+
230
+ _HEX_RE = re.compile(r"^#[0-9A-Fa-f]{6}$")
231
+ """Matches a 7-character hex color string like `#7AA2F7`.
232
+
233
+ Textual's `Color.parse` could also validate, but importing it here would pull
234
+ Textual into `theme.py` which is otherwise pure Python with zero framework deps.
235
+ """
236
+
237
+
238
+ @dataclass(frozen=True, slots=True)
239
+ class ThemeColors:
240
+ """Complete set of semantic colors for one theme variant.
241
+
242
+ Every field must be a 7-character hex color string (e.g., `'#7AA2F7'`).
243
+ """
244
+
245
+ primary: str
246
+ """Accent for headings, borders, links, and active elements."""
247
+
248
+ secondary: str
249
+ """Secondary accent for badges, labels, and decorative highlights."""
250
+
251
+ accent: str
252
+ """Attention-drawing contrast accent, distinct from primary/secondary."""
253
+
254
+ panel: str
255
+ """Differentiated section background (above surface)."""
256
+
257
+ success: str
258
+ """Positive outcomes — tool success, approved actions."""
259
+
260
+ warning: str
261
+ """Caution and notice states — pending tool calls, notices."""
262
+
263
+ error: str
264
+ """Error and destructive-action indicator."""
265
+
266
+ muted: str
267
+ """De-emphasized text — timestamps, secondary labels."""
268
+
269
+ mode_bash: str
270
+ """Shell mode indicator — borders, prompts, and message prefixes."""
271
+
272
+ mode_command: str
273
+ """Command mode indicator — borders, prompts, and message prefixes."""
274
+
275
+ skill: str
276
+ """Skill invocation accent — border and header text."""
277
+
278
+ skill_hover: str
279
+ """Skill invocation hover — contrasting variant for interactive feedback."""
280
+
281
+ tool: str
282
+ """Tool call accent — border and header text."""
283
+
284
+ tool_hover: str
285
+ """Tool call hover — contrasting variant for interactive feedback."""
286
+
287
+ foreground: str
288
+ """Primary body text."""
289
+
290
+ background: str
291
+ """Base application background."""
292
+
293
+ surface: str
294
+ """Elevated card / panel background."""
295
+
296
+ def __post_init__(self) -> None:
297
+ """Validate that every field is a valid hex color.
298
+
299
+ Raises:
300
+ ValueError: If any field is not a 7-character hex color string.
301
+ """
302
+ for f in fields(self):
303
+ val = getattr(self, f.name)
304
+ if not _HEX_RE.match(val):
305
+ msg = (
306
+ f"ThemeColors.{f.name} must be a 7-char hex color"
307
+ f" (#RRGGBB), got {val!r}"
308
+ )
309
+ raise ValueError(msg)
310
+
311
+ @classmethod
312
+ def merged(cls, base: ThemeColors, overrides: dict[str, str]) -> ThemeColors:
313
+ """Create a new `ThemeColors` by overlaying overrides onto a base.
314
+
315
+ Fields present in `overrides` replace the corresponding base value;
316
+ missing fields inherit from `base`. This lets users specify only the
317
+ colors they want to customize.
318
+
319
+ Args:
320
+ base: Fallback color set for any field not in `overrides`.
321
+ overrides: Field-name to hex-color mapping. Unknown keys are
322
+ silently ignored.
323
+
324
+ Returns:
325
+ New `ThemeColors` with merged values.
326
+ """
327
+ valid_names = {f.name for f in fields(cls)}
328
+ kwargs = {f.name: getattr(base, f.name) for f in fields(cls)}
329
+ kwargs.update({k: v for k, v in overrides.items() if k in valid_names})
330
+ return cls(**kwargs)
331
+
332
+
333
+ # ---------------------------------------------------------------------------
334
+ # Built-in theme color sets
335
+ # ---------------------------------------------------------------------------
336
+
337
+ DARK_COLORS = ThemeColors(
338
+ primary=LC_BLUE,
339
+ secondary=LC_PURPLE,
340
+ accent=LC_GREEN,
341
+ panel=LC_PANEL,
342
+ success=LC_GREEN,
343
+ warning=LC_AMBER,
344
+ error=LC_PINK,
345
+ muted=LC_MUTED,
346
+ mode_bash=LC_PINK,
347
+ mode_command=LC_PURPLE,
348
+ skill=LC_SKILL,
349
+ skill_hover=LC_SKILL_HOVER,
350
+ tool=LC_TOOL,
351
+ tool_hover=LC_TOOL_HOVER,
352
+ foreground=LC_BODY,
353
+ background=LC_DARK,
354
+ surface=LC_CARD,
355
+ )
356
+ """Color set for the dark LangChain theme."""
357
+
358
+ LIGHT_COLORS = ThemeColors(
359
+ primary=LC_LIGHT_BLUE,
360
+ secondary=LC_LIGHT_PURPLE,
361
+ accent=LC_LIGHT_GREEN,
362
+ panel=LC_LIGHT_PANEL,
363
+ success=LC_LIGHT_GREEN,
364
+ warning=LC_LIGHT_AMBER,
365
+ error=LC_LIGHT_PINK,
366
+ muted=LC_LIGHT_MUTED,
367
+ mode_bash=LC_LIGHT_PINK,
368
+ mode_command=LC_LIGHT_PURPLE,
369
+ skill=LC_LIGHT_SKILL,
370
+ skill_hover=LC_LIGHT_SKILL_HOVER,
371
+ tool=LC_LIGHT_TOOL,
372
+ tool_hover=LC_LIGHT_TOOL_HOVER,
373
+ foreground=LC_LIGHT_BODY,
374
+ background=LC_LIGHT_BG,
375
+ surface=LC_LIGHT_SURFACE,
376
+ )
377
+ """Color set for the light LangChain theme."""
378
+
379
+
380
+ # ---------------------------------------------------------------------------
381
+ # Available themes (name → display label, dark flag, colors)
382
+ # ---------------------------------------------------------------------------
383
+
384
+
385
+ @dataclass(frozen=True, slots=True)
386
+ class ThemeEntry:
387
+ """Metadata for a registered theme."""
388
+
389
+ label: str
390
+ """Human-readable label shown in the theme picker."""
391
+
392
+ dark: bool
393
+ """Whether this is a dark theme variant."""
394
+
395
+ colors: ThemeColors
396
+ """Resolved color set."""
397
+
398
+ custom: bool = True
399
+ """Whether this theme must be registered with Textual via `register_theme()`.
400
+
401
+ `True` for LangChain-branded themes and user-defined themes.
402
+ `False` for Textual built-in themes that Textual already knows about.
403
+ """
404
+
405
+ REGISTRY: ClassVar[Mapping[str, ThemeEntry]]
406
+ """All registered theme entries, keyed by Textual theme name.
407
+
408
+ Read-only after module load (`MappingProxyType`).
409
+ """
410
+
411
+ def __post_init__(self) -> None:
412
+ """Validate that the label is a non-empty string.
413
+
414
+ Raises:
415
+ ValueError: If `label` is empty or whitespace-only.
416
+ """
417
+ if not self.label.strip():
418
+ msg = "ThemeEntry.label must be a non-empty string"
419
+ raise ValueError(msg)
420
+
421
+
422
+ def _builtin_themes() -> dict[str, ThemeEntry]:
423
+ """Return the built-in theme entries as a mutable dict.
424
+
425
+ Returns:
426
+ Dict of built-in theme names to `ThemeEntry` instances.
427
+ """
428
+ r: dict[str, ThemeEntry] = {}
429
+ r["langchain"] = ThemeEntry(
430
+ label="LangChain Dark",
431
+ dark=True,
432
+ colors=DARK_COLORS,
433
+ )
434
+ r["langchain-light"] = ThemeEntry(
435
+ label="LangChain Light",
436
+ dark=False,
437
+ colors=LIGHT_COLORS,
438
+ )
439
+ # Textual built-in themes — not registered via register_theme() (Textual's
440
+ # own $primary, $background, etc. apply). The `colors` field provides
441
+ # fallback values for app-specific CSS vars ($mode-bash, $mode-command) and
442
+ # Python-side styling. For standard properties (primary, secondary, etc.),
443
+ # get_theme_colors() dynamically resolves from the actual Textual theme at
444
+ # runtime so the Python and CSS color systems stay in sync.
445
+
446
+ def _bi(label: str, *, is_dark: bool) -> ThemeEntry:
447
+ return ThemeEntry(
448
+ label=label,
449
+ dark=is_dark,
450
+ colors=DARK_COLORS if is_dark else LIGHT_COLORS,
451
+ custom=False,
452
+ )
453
+
454
+ r["textual-dark"] = _bi("Textual Dark", is_dark=True)
455
+ r["textual-light"] = _bi("Textual Light", is_dark=False)
456
+ r["textual-ansi"] = _bi("Terminal (ANSI)", is_dark=False)
457
+ # Popular community themes (all ship with Textual >= 8.0)
458
+ r["atom-one-dark"] = _bi("Atom One Dark", is_dark=True)
459
+ r["atom-one-light"] = _bi("Atom One Light", is_dark=False)
460
+ r["catppuccin-frappe"] = _bi("Catppuccin Frappé", is_dark=True)
461
+ r["catppuccin-latte"] = _bi("Catppuccin Latte", is_dark=False)
462
+ r["catppuccin-macchiato"] = _bi("Catppuccin Macchiato", is_dark=True)
463
+ r["catppuccin-mocha"] = _bi("Catppuccin Mocha", is_dark=True)
464
+ r["dracula"] = _bi("Dracula", is_dark=True)
465
+ r["flexoki"] = _bi("Flexoki", is_dark=True)
466
+ r["gruvbox"] = _bi("Gruvbox", is_dark=True)
467
+ r["monokai"] = _bi("Monokai", is_dark=True)
468
+ r["nord"] = _bi("Nord", is_dark=True)
469
+ r["rose-pine"] = _bi("Rosé Pine", is_dark=True)
470
+ r["rose-pine-dawn"] = _bi("Rosé Pine Dawn", is_dark=False)
471
+ r["rose-pine-moon"] = _bi("Rosé Pine Moon", is_dark=True)
472
+ r["solarized-dark"] = _bi("Solarized Dark", is_dark=True)
473
+ r["solarized-light"] = _bi("Solarized Light", is_dark=False)
474
+ r["tokyo-night"] = _bi("Tokyo Night", is_dark=True)
475
+ return r
476
+
477
+
478
+ _BUILTIN_NAMES: frozenset[str] = frozenset(_builtin_themes())
479
+ """Names of built-in themes.
480
+
481
+ User `[themes.<name>]` sections matching a built-in name override its colors
482
+ rather than creating a new theme. Derived from `_builtin_themes()` to stay in
483
+ sync automatically.
484
+ """
485
+
486
+
487
+ def _load_user_themes(
488
+ builtins: dict[str, ThemeEntry],
489
+ *,
490
+ config_path: Path | None = None,
491
+ ) -> None:
492
+ """Load user-defined themes from `config.toml` into `builtins` (mutated).
493
+
494
+ **New themes** — each `[themes.<name>]` section (where `<name>` is not a
495
+ built-in) must have:
496
+
497
+ - `label` (str) — human-readable name shown in the theme picker.
498
+ - `dark` (bool, optional) — whether this is a dark-mode variant.
499
+
500
+ Defaults to `False` (light).
501
+
502
+ **Built-in overrides** — if `<name>` matches a built-in theme, only color
503
+ fields are read; `label` and `dark` are inherited from the built-in.
504
+
505
+ All `ThemeColors` fields are optional. For new themes, omitted fields
506
+ fall back to the built-in dark or light palette based on the `dark` flag.
507
+
508
+ For built-in overrides, omitted fields retain the existing built-in colors.
509
+
510
+ Invalid themes (bad hex, missing required keys) are logged as warnings
511
+ and skipped — they never crash startup.
512
+
513
+ Example `config.toml` snippet:
514
+
515
+ ```toml
516
+ # New custom theme
517
+ [themes.my-solarized]
518
+ label = "My Solarized"
519
+ dark = true
520
+ primary = "#268BD2"
521
+ warning = "#B58900"
522
+
523
+ # Override built-in theme colors
524
+ [themes.langchain]
525
+ primary = "#FF5500"
526
+ ```
527
+
528
+ Args:
529
+ builtins: Mutable dict to update (new themes are added, built-in
530
+ overrides replace existing entries).
531
+ config_path: Override for the config file path (testing).
532
+ """
533
+ if config_path is None:
534
+ try:
535
+ config_path = Path.home() / ".docagent" / "config.toml"
536
+ except RuntimeError:
537
+ logger.debug("Cannot determine home directory; skipping user theme loading")
538
+ return
539
+
540
+ import tomllib
541
+
542
+ try:
543
+ if not config_path.exists():
544
+ return
545
+
546
+ with config_path.open("rb") as f:
547
+ data = tomllib.load(f)
548
+ except (tomllib.TOMLDecodeError, PermissionError, OSError) as exc:
549
+ logger.warning(
550
+ "Could not read %s for user themes: %s",
551
+ config_path,
552
+ exc,
553
+ )
554
+ return
555
+
556
+ themes_section: Any = data.get("themes")
557
+ if not isinstance(themes_section, dict) or not themes_section:
558
+ return
559
+
560
+ valid_color_names = {f.name for f in fields(ThemeColors)}
561
+ reserved = {"label", "dark"}
562
+
563
+ for name, section in themes_section.items():
564
+ if not isinstance(section, dict):
565
+ logger.warning("Ignoring non-table [themes.%s]", name)
566
+ continue
567
+
568
+ # --- Parse color overrides (shared by built-in overrides & new themes)
569
+ color_overrides: dict[str, str] = {}
570
+ for k, v in section.items():
571
+ if k in reserved:
572
+ continue
573
+ if not isinstance(v, str):
574
+ logger.warning(
575
+ "User theme '%s' field '%s' must be a string, got %s; ignoring",
576
+ name,
577
+ k,
578
+ type(v).__name__,
579
+ )
580
+ continue
581
+ if k in valid_color_names:
582
+ color_overrides[k] = v
583
+ else:
584
+ logger.warning(
585
+ "User theme '%s' has unknown color field '%s'; ignoring",
586
+ name,
587
+ k,
588
+ )
589
+
590
+ # --- Built-in override: merge color tweaks into the existing entry
591
+ if name in _BUILTIN_NAMES:
592
+ existing = builtins.get(name)
593
+ if existing is None:
594
+ logger.warning(
595
+ "Built-in theme '%s' not in builtins dict; skipping override",
596
+ name,
597
+ )
598
+ continue
599
+ if not color_overrides:
600
+ continue
601
+ try:
602
+ colors = ThemeColors.merged(existing.colors, color_overrides)
603
+ except ValueError as exc:
604
+ logger.warning(
605
+ "Built-in theme '%s' color override invalid: %s; skipping",
606
+ name,
607
+ exc,
608
+ )
609
+ continue
610
+ builtins[name] = ThemeEntry(
611
+ label=existing.label,
612
+ dark=existing.dark,
613
+ colors=colors,
614
+ custom=existing.custom,
615
+ )
616
+ continue
617
+
618
+ # --- New custom theme: label required, dark defaults to False (light)
619
+ label = section.get("label")
620
+ if not isinstance(label, str) or not label.strip():
621
+ logger.warning(
622
+ "User theme '%s' missing required 'label' (str); skipping",
623
+ name,
624
+ )
625
+ continue
626
+
627
+ dark = section.get("dark", False)
628
+ if not isinstance(dark, bool):
629
+ logger.warning(
630
+ "User theme '%s': 'dark' must be true or false, got %s (%r);"
631
+ " defaulting to light",
632
+ name,
633
+ type(dark).__name__,
634
+ dark,
635
+ )
636
+ dark = False
637
+
638
+ base = DARK_COLORS if dark else LIGHT_COLORS
639
+ try:
640
+ colors = ThemeColors.merged(base, color_overrides)
641
+ except ValueError as exc:
642
+ logger.warning(
643
+ "User theme '%s' has invalid colors: %s; skipping",
644
+ name,
645
+ exc,
646
+ )
647
+ continue
648
+
649
+ builtins[name] = ThemeEntry(
650
+ label=label,
651
+ dark=dark,
652
+ colors=colors,
653
+ custom=True,
654
+ )
655
+
656
+
657
+ def _build_registry(
658
+ *, config_path: Path | None = None
659
+ ) -> MappingProxyType[str, ThemeEntry]:
660
+ """Build and freeze the theme registry (built-in + user themes).
661
+
662
+ Args:
663
+ config_path: Override for the config file path (testing).
664
+
665
+ Returns:
666
+ Read-only mapping of theme names to `ThemeEntry` instances.
667
+ """
668
+ r = _builtin_themes()
669
+ _load_user_themes(r, config_path=config_path)
670
+ return MappingProxyType(r)
671
+
672
+
673
+ ThemeEntry.REGISTRY = _build_registry()
674
+ """Read-only mapping of Textual theme names to `ThemeEntry` instances.
675
+
676
+ Built via `_build_registry()` so the mutable staging dict is scoped to a
677
+ function call and cannot be mutated after freeze. The `ClassVar` declaration on
678
+ `ThemeEntry` provides the type; this assignment supplies the value.
679
+ """
680
+
681
+ DEFAULT_THEME = "langchain"
682
+ """Theme name used when no preference is saved."""
683
+
684
+
685
+ def reload_registry() -> MappingProxyType[str, ThemeEntry]:
686
+ """Rebuild the theme registry from disk and update `ThemeEntry.REGISTRY`.
687
+
688
+ Re-reads `~/.docagent/config.toml` for user-defined themes so that
689
+ `/reload` can pick up config changes without restarting the app.
690
+
691
+ Returns:
692
+ The new frozen registry.
693
+ """
694
+ ThemeEntry.REGISTRY = _build_registry()
695
+ return ThemeEntry.REGISTRY
696
+
697
+
698
+ def get_css_variable_defaults(
699
+ *, dark: bool = True, colors: ThemeColors | None = None
700
+ ) -> dict[str, str]:
701
+ """Return custom CSS variable defaults for the given mode.
702
+
703
+ Most styling is handled by Textual's built-in CSS variables (`$primary`,
704
+ `$text-muted`, `$error-muted`, etc.). This function only returns
705
+ app-specific semantic variables that have no Textual equivalent.
706
+
707
+ Args:
708
+ dark: Selects `DARK_COLORS` or `LIGHT_COLORS` when `colors` is None.
709
+ colors: Explicit color set to use. Takes precedence over `dark`.
710
+
711
+ Returns:
712
+ Dict of CSS variable names to hex color values.
713
+ """
714
+ c = colors if colors is not None else (DARK_COLORS if dark else LIGHT_COLORS)
715
+ return {
716
+ "mode-bash": c.mode_bash,
717
+ "mode-command": c.mode_command,
718
+ "skill": c.skill,
719
+ "skill-hover": c.skill_hover,
720
+ "tool": c.tool,
721
+ "tool-hover": c.tool_hover,
722
+ }
723
+
724
+
725
+ def _resolve_app(widget_or_app: object) -> object:
726
+ """Resolve a widget or App to the App instance.
727
+
728
+ Args:
729
+ widget_or_app: Textual `App` or a mounted widget.
730
+
731
+ Returns:
732
+ The resolved App instance.
733
+ """
734
+ return (
735
+ widget_or_app.app # type: ignore[attr-defined]
736
+ if hasattr(type(widget_or_app), "app")
737
+ else widget_or_app
738
+ )
739
+
740
+
741
+ def _colors_from_textual_theme(app: object) -> ThemeColors:
742
+ """Construct `ThemeColors` from the app's active Textual theme.
743
+
744
+ Reads standard properties (primary, secondary, etc.) from the resolved
745
+ theme so Python-side styling matches CSS. `muted` falls back to the
746
+ dark/light base unconditionally (no Textual equivalent).
747
+ `mode_bash` is derived from the theme's `error` color, and `mode_command`
748
+ from `secondary`, falling back to the base palette when non-hex.
749
+
750
+ Non-hex values (e.g. `ansi_blue` in the ANSI theme) are detected and fall
751
+ back to the base palette automatically.
752
+
753
+ Args:
754
+ app: The Textual App instance.
755
+
756
+ Returns:
757
+ `ThemeColors` derived from the active theme.
758
+ """
759
+ ct = app.current_theme # type: ignore[attr-defined]
760
+ dark: bool = ct.dark
761
+ base = DARK_COLORS if dark else LIGHT_COLORS
762
+
763
+ def _hex_or(val: str | None, fallback: str) -> str:
764
+ """Return `val` if it is a valid `#RRGGBB` hex color, else `fallback`.
765
+
766
+ Args:
767
+ val: Color string from the active Textual theme (may be `None` or
768
+ a non-hex name like `ansi_blue`).
769
+ fallback: Guaranteed-hex value from our base palette.
770
+
771
+ Returns:
772
+ `val` if it matches `#RRGGBB`, otherwise `fallback`.
773
+ """
774
+ if val is not None and _HEX_RE.match(val):
775
+ return val
776
+ return fallback
777
+
778
+ return ThemeColors(
779
+ primary=_hex_or(ct.primary, base.primary),
780
+ secondary=_hex_or(ct.secondary, base.secondary),
781
+ accent=_hex_or(ct.accent, base.accent),
782
+ panel=_hex_or(ct.panel, base.panel),
783
+ success=_hex_or(ct.success, base.success),
784
+ warning=_hex_or(ct.warning, base.warning),
785
+ error=_hex_or(ct.error, base.error),
786
+ muted=base.muted,
787
+ mode_bash=_hex_or(ct.error, base.mode_bash),
788
+ mode_command=_hex_or(ct.secondary, base.mode_command),
789
+ # No Textual equivalent — always use base palette.
790
+ skill=base.skill,
791
+ skill_hover=base.skill_hover,
792
+ # Derived from Textual's warning color (shared amber hue).
793
+ tool=_hex_or(ct.warning, base.tool),
794
+ # No Textual equivalent — always base palette (may diverge from
795
+ # tool in custom themes that override warning).
796
+ tool_hover=base.tool_hover,
797
+ foreground=_hex_or(ct.foreground, base.foreground),
798
+ background=_hex_or(ct.background, base.background),
799
+ surface=_hex_or(ct.surface, base.surface),
800
+ )
801
+
802
+
803
+ def get_theme_colors(widget_or_app: App | object | None = None) -> ThemeColors:
804
+ """Return the `ThemeColors` for the active Textual theme.
805
+
806
+ For custom themes (LangChain-branded and user-defined), the pre-built
807
+ `ThemeColors` from the registry is returned directly. For Textual built-in
808
+ themes, colors are resolved dynamically from the actual theme properties so
809
+ Python-side styling stays in sync with CSS variables.
810
+
811
+ Textual widget code should call this instead of reading the module-level
812
+ ANSI constants, which are intended for Rich console output only.
813
+
814
+ Args:
815
+ widget_or_app: Textual `App`, a mounted widget, or `None`.
816
+
817
+ Returns:
818
+ `ThemeColors` for the active theme.
819
+ """
820
+ if widget_or_app is None:
821
+ # Fall back to the active Textual app context var when no explicit
822
+ # widget/app is passed (e.g. from @staticmethod helpers).
823
+ try:
824
+ from textual._context import active_app # noqa: PLC2701
825
+
826
+ widget_or_app = active_app.get()
827
+ except (ImportError, LookupError):
828
+ return DARK_COLORS
829
+ app = _resolve_app(widget_or_app)
830
+ entry = ThemeEntry.REGISTRY.get(app.theme) # type: ignore[attr-defined]
831
+ # Custom themes (LC-branded / user-defined) use pre-built colors.
832
+ if entry is not None and entry.custom:
833
+ return entry.colors
834
+ # Built-in or unrecognized themes — derive from the resolved Textual
835
+ # theme so Python styling matches CSS.
836
+ try:
837
+ return _colors_from_textual_theme(app)
838
+ except Exception:
839
+ logger.warning("Could not resolve theme colors dynamically", exc_info=True)
840
+ if entry is not None:
841
+ return entry.colors
842
+ return DARK_COLORS