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,1090 @@
1
+ """CLI commands for skill management.
2
+
3
+ These commands are registered with the CLI via main.py:
4
+ - docagent skills list [options]
5
+ - docagent skills create <name> [options]
6
+ - docagent skills info <name> [options]
7
+ - docagent skills delete <name> [options]
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import argparse
13
+ import shutil
14
+ from pathlib import Path
15
+ from typing import TYPE_CHECKING, Any
16
+
17
+ if TYPE_CHECKING:
18
+ from collections.abc import Callable
19
+
20
+ from deepagents.middleware.skills import SkillMetadata
21
+
22
+ from docagent_cli.output import OutputFormat
23
+
24
+ from docagent_cli import theme
25
+
26
+ MAX_SKILL_NAME_LENGTH = 64
27
+
28
+
29
+ def _validate_name(name: str) -> tuple[bool, str]:
30
+ """Validate name per Agent Skills spec.
31
+
32
+ Requirements (https://agentskills.io/specification):
33
+ - Max 64 characters
34
+ - Unicode lowercase alphanumeric and hyphens only
35
+ - Cannot start or end with hyphen
36
+ - No consecutive hyphens
37
+ - No path traversal sequences
38
+
39
+ Unicode lowercase alphanumeric means any character where
40
+ `c.isalpha() and c.islower()` or `c.isdigit()` returns `True`,
41
+ which covers accented Latin characters (e.g., `'cafe'`,
42
+ `'uber-tool'`) and other scripts. This matches the SDK's
43
+ `_validate_skill_name` implementation.
44
+
45
+ Args:
46
+ name: The name to validate.
47
+
48
+ Returns:
49
+ Tuple of (is_valid, error_message). If valid, error_message is empty.
50
+ """
51
+ # Check for empty or whitespace-only names
52
+ if not name or not name.strip():
53
+ return False, "cannot be empty"
54
+
55
+ # Check length (spec: max 64 chars)
56
+ if len(name) > MAX_SKILL_NAME_LENGTH:
57
+ return False, "cannot exceed 64 characters"
58
+
59
+ # Check for path traversal sequences (CLI-specific; the SDK validates
60
+ # against the directory name instead, but the CLI accepts user input
61
+ # directly so we need explicit path-safety checks)
62
+ if ".." in name or "/" in name or "\\" in name:
63
+ return False, "cannot contain path components"
64
+
65
+ # Structural hyphen checks
66
+ if name.startswith("-") or name.endswith("-") or "--" in name:
67
+ return (
68
+ False,
69
+ "must be lowercase alphanumeric with single hyphens only",
70
+ )
71
+
72
+ # Character-by-character check (matches SDK's _validate_skill_name)
73
+ for c in name:
74
+ if c == "-":
75
+ continue
76
+ if (c.isalpha() and c.islower()) or c.isdigit():
77
+ continue
78
+ return (
79
+ False,
80
+ "must be lowercase alphanumeric with single hyphens only",
81
+ )
82
+
83
+ return True, ""
84
+
85
+
86
+ def _validate_skill_path(skill_dir: Path, base_dir: Path) -> tuple[bool, str]:
87
+ """Validate that the resolved skill directory is within the base directory.
88
+
89
+ Args:
90
+ skill_dir: The skill directory path to validate
91
+ base_dir: The base skills directory that should contain skill_dir
92
+
93
+ Returns:
94
+ Tuple of (is_valid, error_message). If valid, error_message is empty.
95
+ """
96
+ try:
97
+ # Resolve both paths to their canonical form
98
+ resolved_skill = skill_dir.resolve()
99
+ resolved_base = base_dir.resolve()
100
+
101
+ # Check if skill_dir is within base_dir
102
+ if not resolved_skill.is_relative_to(resolved_base):
103
+ return False, f"Skill directory must be within {base_dir}"
104
+ except (OSError, RuntimeError) as e:
105
+ return False, f"Invalid path: {e}"
106
+ else:
107
+ return True, ""
108
+
109
+
110
+ def _format_info_fields(skill: SkillMetadata) -> list[tuple[str, str]]:
111
+ """Extract non-empty optional metadata fields for display.
112
+
113
+ The upstream `_parse_skill_metadata` normalises empty/whitespace license
114
+ and compatibility values to `None`, so the truthy checks below are
115
+ sufficient.
116
+
117
+ Args:
118
+ skill: Skill metadata to extract display fields from.
119
+
120
+ Returns:
121
+ Ordered list of (label, value) tuples for non-empty fields.
122
+ Fields appear in order: License, Compatibility, Allowed Tools,
123
+ Metadata.
124
+ """
125
+ fields: list[tuple[str, str]] = []
126
+ license_val = skill.get("license")
127
+ if license_val:
128
+ fields.append(("License", license_val))
129
+ compat_val = skill.get("compatibility")
130
+ if compat_val:
131
+ fields.append(("Compatibility", compat_val))
132
+ if skill.get("allowed_tools"):
133
+ fields.append(
134
+ ("Allowed Tools", ", ".join(str(t) for t in skill["allowed_tools"]))
135
+ )
136
+ meta = skill.get("metadata")
137
+ if meta and isinstance(meta, dict):
138
+ formatted = ", ".join(f"{k}={v}" for k, v in meta.items())
139
+ fields.append(("Metadata", formatted))
140
+ return fields
141
+
142
+
143
+ def _list(
144
+ agent: str, *, project: bool = False, output_format: OutputFormat = "text"
145
+ ) -> None:
146
+ """List all available skills for the specified agent.
147
+
148
+ Args:
149
+ agent: Agent identifier for skills (default: agent).
150
+ project: If True, show only project skills.
151
+ If False, show all skills (user + project).
152
+ output_format: Output format — `'text'` (Rich) or `'json'`.
153
+ """
154
+ from rich.markup import escape as escape_markup
155
+
156
+ from docagent_cli.config import Settings, console, get_glyphs
157
+ from docagent_cli.skills.load import list_skills
158
+
159
+ settings = Settings.from_environment()
160
+ user_skills_dir = settings.get_user_skills_dir(agent)
161
+ project_skills_dir = settings.get_project_skills_dir()
162
+ user_agent_skills_dir = settings.get_user_agent_skills_dir()
163
+ project_agent_skills_dir = settings.get_project_agent_skills_dir()
164
+
165
+ # If --project flag is used, only show project skills
166
+ if project:
167
+ if not project_skills_dir:
168
+ if output_format == "json":
169
+ from docagent_cli.output import write_json
170
+
171
+ write_json("skills list", [])
172
+ return
173
+ console.print("[yellow]Not in a project directory.[/yellow]")
174
+ console.print(
175
+ "[dim]Project skills require a .git directory "
176
+ "in the project root.[/dim]",
177
+ style=theme.MUTED,
178
+ )
179
+ return
180
+
181
+ # Check both project skill directories
182
+ has_docagent_skills = project_skills_dir.exists() and any(
183
+ project_skills_dir.iterdir()
184
+ )
185
+ has_agent_skills = (
186
+ project_agent_skills_dir
187
+ and project_agent_skills_dir.exists()
188
+ and any(project_agent_skills_dir.iterdir())
189
+ )
190
+
191
+ if not has_docagent_skills and not has_agent_skills:
192
+ if output_format == "json":
193
+ from docagent_cli.output import write_json
194
+
195
+ write_json("skills list", [])
196
+ return
197
+ console.print("[yellow]No project skills found.[/yellow]")
198
+ console.print(
199
+ f"[dim]Project skills will be created in {project_skills_dir}/ "
200
+ "when you add them.[/dim]",
201
+ style=theme.MUTED,
202
+ )
203
+ console.print(
204
+ "\n[dim]Create a project skill:\n"
205
+ " docagent skills create my-skill --project[/dim]",
206
+ style=theme.MUTED,
207
+ )
208
+ return
209
+
210
+ skills = list_skills(
211
+ user_skills_dir=None,
212
+ project_skills_dir=project_skills_dir,
213
+ user_agent_skills_dir=None,
214
+ project_agent_skills_dir=project_agent_skills_dir,
215
+ )
216
+
217
+ if output_format == "json":
218
+ from docagent_cli.output import write_json
219
+
220
+ write_json("skills list", [dict(s) for s in skills])
221
+ return
222
+
223
+ console.print("\n[bold]Project Skills:[/bold]\n", style=theme.PRIMARY)
224
+ else:
225
+ # Load skills from all directories (including built-in)
226
+ skills = list_skills(
227
+ built_in_skills_dir=settings.get_built_in_skills_dir(),
228
+ user_skills_dir=user_skills_dir,
229
+ project_skills_dir=project_skills_dir,
230
+ user_agent_skills_dir=user_agent_skills_dir,
231
+ project_agent_skills_dir=project_agent_skills_dir,
232
+ )
233
+
234
+ if output_format == "json":
235
+ from docagent_cli.output import write_json
236
+
237
+ write_json("skills list", [dict(s) for s in skills])
238
+ return
239
+
240
+ if not skills:
241
+ console.print()
242
+ console.print("[yellow]No skills found.[/yellow]")
243
+ console.print()
244
+ console.print(
245
+ "[dim]Skills are loaded from these directories "
246
+ "(highest precedence first):\n"
247
+ " 1. .agents/skills/ project skills\n"
248
+ " 2. .docagent/skills/ project skills (alias)\n"
249
+ " 3. ~/.agents/skills/ user skills\n"
250
+ " 4. ~/.docagent/<agent>/skills/ user skills (alias)\n"
251
+ " 5. <package>/built_in_skills/ built-in skills[/dim]",
252
+ style=theme.MUTED,
253
+ )
254
+ console.print(
255
+ "\n[dim]Create your first skill:\n"
256
+ " docagent skills create my-skill[/dim]",
257
+ style=theme.MUTED,
258
+ )
259
+ return
260
+
261
+ console.print("\n[bold]Available Skills:[/bold]\n", style=theme.PRIMARY)
262
+
263
+ # Group skills by source
264
+ user_skills = [s for s in skills if s["source"] == "user"]
265
+ project_skills_list = [s for s in skills if s["source"] == "project"]
266
+ built_in_skills_list = [s for s in skills if s["source"] == "built-in"]
267
+
268
+ # Show user skills
269
+ if user_skills and not project:
270
+ console.print("[bold cyan]User Skills:[/bold cyan]", style=theme.PRIMARY)
271
+ bullet = get_glyphs().bullet
272
+ for skill in user_skills:
273
+ skill_path = Path(skill["path"])
274
+ name = escape_markup(skill["name"])
275
+ console.print(f" {bullet} [bold]{name}[/bold]", style=theme.PRIMARY)
276
+ console.print(
277
+ f" {escape_markup(str(skill_path.parent))}/",
278
+ style=theme.MUTED,
279
+ )
280
+ console.print()
281
+ console.print(
282
+ f" {escape_markup(skill['description'])}",
283
+ style=theme.MUTED,
284
+ )
285
+ console.print()
286
+
287
+ # Show project skills
288
+ if project_skills_list:
289
+ if not project and user_skills:
290
+ console.print()
291
+ console.print("[bold green]Project Skills:[/bold green]", style=theme.PRIMARY)
292
+ bullet = get_glyphs().bullet
293
+ for skill in project_skills_list:
294
+ skill_path = Path(skill["path"])
295
+ name = escape_markup(skill["name"])
296
+ console.print(f" {bullet} [bold]{name}[/bold]", style=theme.PRIMARY)
297
+ console.print(
298
+ f" {escape_markup(str(skill_path.parent))}/",
299
+ style=theme.MUTED,
300
+ )
301
+ console.print()
302
+ console.print(
303
+ f" {escape_markup(skill['description'])}",
304
+ style=theme.MUTED,
305
+ )
306
+ console.print()
307
+
308
+ # Show built-in skills
309
+ if built_in_skills_list and not project:
310
+ if user_skills or project_skills_list:
311
+ console.print()
312
+ console.print(
313
+ "[bold magenta]Built-in Skills:[/bold magenta]", style=theme.PRIMARY
314
+ )
315
+ bullet = get_glyphs().bullet
316
+ for skill in built_in_skills_list:
317
+ name = escape_markup(skill["name"])
318
+ console.print(f" {bullet} [bold]{name}[/bold]", style=theme.PRIMARY)
319
+ console.print()
320
+ console.print(
321
+ f" {escape_markup(skill['description'])}",
322
+ style=theme.MUTED,
323
+ )
324
+ console.print()
325
+
326
+
327
+ def _generate_template(skill_name: str) -> str:
328
+ """Generate a `SKILL.md` template for a new skill.
329
+
330
+ The template follows the Agent Skills spec
331
+ (https://agentskills.io/specification) and the skill-creator guidance:
332
+
333
+ - Description includes "when to use" trigger information (not the body)
334
+ - Body contains only instructions loaded after the skill triggers
335
+
336
+ Args:
337
+ skill_name: Name of the skill (used in frontmatter and heading).
338
+
339
+ Returns:
340
+ Complete `SKILL.md` content with YAML frontmatter and markdown body.
341
+ """
342
+ title = skill_name.title().replace("-", " ")
343
+ description = (
344
+ "TODO: Explain what this skill does and when to use it. "
345
+ "Include specific triggers — scenarios, file types, or phrases "
346
+ "that should activate this skill. Example: 'Create and edit PDF "
347
+ "documents. Use when the user asks to merge, split, fill, or "
348
+ "annotate PDF files.'"
349
+ )
350
+ return f"""---
351
+ name: {skill_name}
352
+ description: "{description}"
353
+ # (Warning: SKILL.md files exceeding 10 MB are silently skipped at load time.)
354
+ # Optional fields per Agent Skills spec:
355
+ # license: Apache-2.0
356
+ # compatibility: Designed for Deep Agents CLI
357
+ # metadata:
358
+ # author: your-org
359
+ # version: "1.0"
360
+ # allowed-tools: Bash(git:*) Read
361
+ ---
362
+
363
+ # {title}
364
+
365
+ ## Overview
366
+
367
+ [TODO: 1-2 sentences explaining what this skill enables]
368
+
369
+ ## Instructions
370
+
371
+ ### Step 1: [First Action]
372
+ [Explain what to do first]
373
+
374
+ ### Step 2: [Second Action]
375
+ [Explain what to do next]
376
+
377
+ ### Step 3: [Final Action]
378
+ [Explain how to complete the task]
379
+
380
+ ## Best Practices
381
+
382
+ - [Best practice 1]
383
+ - [Best practice 2]
384
+ - [Best practice 3]
385
+
386
+ ## Examples
387
+
388
+ ### Example 1: [Scenario Name]
389
+
390
+ **User Request:** "[Example user request]"
391
+
392
+ **Approach:**
393
+ 1. [Step-by-step breakdown]
394
+ 2. [Using tools and commands]
395
+ 3. [Expected outcome]
396
+ """
397
+
398
+
399
+ def _create(
400
+ skill_name: str,
401
+ agent: str,
402
+ project: bool = False,
403
+ *,
404
+ output_format: OutputFormat = "text",
405
+ ) -> None:
406
+ """Create a new skill with a template SKILL.md file.
407
+
408
+ Args:
409
+ skill_name: Name of the skill to create.
410
+ agent: Agent identifier for skills
411
+ project: If True, create in project skills directory.
412
+ If False, create in user skills directory.
413
+ output_format: Output format — `'text'` (Rich) or `'json'`.
414
+
415
+ Raises:
416
+ SystemExit: If the skill name is invalid or the directory cannot be created.
417
+ """
418
+ from docagent_cli.config import Settings, console, get_glyphs
419
+
420
+ # Validate skill name first (per Agent Skills spec)
421
+ is_valid, error_msg = _validate_name(skill_name)
422
+ if not is_valid:
423
+ console.print(f"[bold red]Error:[/bold red] Invalid skill name: {error_msg}")
424
+ console.print(
425
+ "[dim]Per Agent Skills spec: names must be lowercase alphanumeric "
426
+ "with hyphens only.\n"
427
+ "Examples: web-research, code-review, data-analysis[/dim]",
428
+ style=theme.MUTED,
429
+ )
430
+ raise SystemExit(1)
431
+
432
+ # Determine target directory
433
+ settings = Settings.from_environment()
434
+ if project:
435
+ if not settings.project_root:
436
+ console.print("[bold red]Error:[/bold red] Not in a project directory.")
437
+ console.print(
438
+ "[dim]Project skills require a .git directory "
439
+ "in the project root.[/dim]",
440
+ style=theme.MUTED,
441
+ )
442
+ raise SystemExit(1)
443
+ skills_dir = settings.ensure_project_skills_dir()
444
+ if skills_dir is None:
445
+ console.print(
446
+ "[bold red]Error:[/bold red] Could not create project skills directory."
447
+ )
448
+ raise SystemExit(1)
449
+ else:
450
+ skills_dir = settings.ensure_user_skills_dir(agent)
451
+
452
+ skill_dir = skills_dir / skill_name
453
+
454
+ # Validate the resolved path is within skills_dir
455
+ is_valid_path, path_error = _validate_skill_path(skill_dir, skills_dir)
456
+ if not is_valid_path:
457
+ console.print(f"[bold red]Error:[/bold red] {path_error}")
458
+ raise SystemExit(1)
459
+
460
+ if skill_dir.exists():
461
+ if output_format == "json":
462
+ from docagent_cli.output import write_json
463
+
464
+ write_json(
465
+ "skills create",
466
+ {
467
+ "name": skill_name,
468
+ "path": str(skill_dir),
469
+ "project": project,
470
+ "already_existed": True,
471
+ },
472
+ )
473
+ return
474
+ console.print(
475
+ f"Skill '{skill_name}' already exists at {skill_dir}",
476
+ style=theme.MUTED,
477
+ )
478
+ return
479
+
480
+ # Create skill directory
481
+ skill_dir.mkdir(parents=True, exist_ok=True)
482
+
483
+ template = _generate_template(skill_name)
484
+ skill_md = skill_dir / "SKILL.md"
485
+ skill_md.write_text(template)
486
+
487
+ if output_format == "json":
488
+ from docagent_cli.output import write_json
489
+
490
+ write_json(
491
+ "skills create",
492
+ {
493
+ "name": skill_name,
494
+ "path": str(skill_dir),
495
+ "project": project,
496
+ },
497
+ )
498
+ return
499
+
500
+ checkmark = get_glyphs().checkmark
501
+ console.print(
502
+ f"\n[bold]{checkmark} Skill '{skill_name}' created successfully![/bold]",
503
+ style=theme.PRIMARY,
504
+ )
505
+ console.print(f"Location: {skill_dir}\n", style=theme.MUTED)
506
+ console.print(
507
+ "[dim]Edit the SKILL.md file to customize:\n"
508
+ " 1. Update the description in YAML frontmatter\n"
509
+ " 2. Fill in the instructions and examples\n"
510
+ " 3. Add any supporting files (scripts, configs, etc.)\n"
511
+ "\n"
512
+ f" nano {skill_md}\n"
513
+ "\n"
514
+ " See examples/skills/ in the docagent-cli repo for example skills:\n"
515
+ " - web-research: Structured research workflow\n"
516
+ " - langgraph-docs: LangGraph documentation lookup\n"
517
+ "\n"
518
+ " Copy an example:\n"
519
+ " cp -r examples/skills/web-research ~/.docagent/agent/skills/\n",
520
+ style=theme.MUTED,
521
+ )
522
+
523
+
524
+ def _info(
525
+ skill_name: str,
526
+ *,
527
+ agent: str = "agent",
528
+ project: bool = False,
529
+ output_format: OutputFormat = "text",
530
+ ) -> None:
531
+ """Show detailed information about a specific skill.
532
+
533
+ Args:
534
+ skill_name: Name of the skill to show info for.
535
+ agent: Agent identifier for skills (default: agent).
536
+ project: If True, only search in project skills.
537
+ If False, search in both user and project skills.
538
+ output_format: Output format — `'text'` (Rich) or `'json'`.
539
+
540
+ Raises:
541
+ SystemExit: If the skill is not found or not in a project directory.
542
+ """
543
+ from rich.markup import escape as escape_markup
544
+
545
+ from docagent_cli.config import Settings, console
546
+ from docagent_cli.skills.load import list_skills
547
+
548
+ settings = Settings.from_environment()
549
+ user_skills_dir = settings.get_user_skills_dir(agent)
550
+ project_skills_dir = settings.get_project_skills_dir()
551
+ user_agent_skills_dir = settings.get_user_agent_skills_dir()
552
+ project_agent_skills_dir = settings.get_project_agent_skills_dir()
553
+
554
+ # Load skills based on --project flag
555
+ if project:
556
+ if not project_skills_dir:
557
+ console.print("[bold red]Error:[/bold red] Not in a project directory.")
558
+ raise SystemExit(1)
559
+ skills = list_skills(
560
+ user_skills_dir=None,
561
+ project_skills_dir=project_skills_dir,
562
+ user_agent_skills_dir=None,
563
+ project_agent_skills_dir=project_agent_skills_dir,
564
+ )
565
+ else:
566
+ skills = list_skills(
567
+ built_in_skills_dir=settings.get_built_in_skills_dir(),
568
+ user_skills_dir=user_skills_dir,
569
+ project_skills_dir=project_skills_dir,
570
+ user_agent_skills_dir=user_agent_skills_dir,
571
+ project_agent_skills_dir=project_agent_skills_dir,
572
+ )
573
+
574
+ # Find the skill
575
+ skill = next((s for s in skills if s["name"] == skill_name), None)
576
+
577
+ if not skill:
578
+ console.print(f"[bold red]Error:[/bold red] Skill '{skill_name}' not found.")
579
+ console.print("\n[dim]Available skills:[/dim]", style=theme.MUTED)
580
+ for s in skills:
581
+ console.print(f" - {s['name']}", style=theme.MUTED)
582
+ raise SystemExit(1)
583
+
584
+ if output_format == "json":
585
+ from docagent_cli.output import write_json
586
+
587
+ write_json("skills info", dict(skill))
588
+ return
589
+
590
+ # Read the full SKILL.md file
591
+ skill_path = Path(skill["path"])
592
+ skill_content = skill_path.read_text(encoding="utf-8")
593
+
594
+ # Determine source label
595
+ source_labels = {
596
+ "project": ("Project Skill", "green"),
597
+ "user": ("User Skill", "cyan"),
598
+ "built-in": ("Built-in Skill", "magenta"),
599
+ }
600
+ source_label, source_color = source_labels.get(skill["source"], ("Skill", "dim"))
601
+
602
+ # Check if this project skill shadows a user skill with the same name.
603
+ # This is a cosmetic hint — if the second list_skills() call fails
604
+ # (e.g. permission error reading user dirs) we silently skip the warning
605
+ # rather than crashing the entire `skills info` display.
606
+ shadowed_user_skill = False
607
+ if skill["source"] == "project" and not project:
608
+ try:
609
+ user_only = list_skills(
610
+ user_skills_dir=user_skills_dir,
611
+ project_skills_dir=None,
612
+ user_agent_skills_dir=user_agent_skills_dir,
613
+ project_agent_skills_dir=None,
614
+ )
615
+ shadowed_user_skill = any(s["name"] == skill_name for s in user_only)
616
+ except Exception: # noqa: BLE001, S110 # Shadow detection is cosmetic, safe to swallow
617
+ pass
618
+
619
+ console.print(
620
+ f"\n[bold]Skill: {escape_markup(skill['name'])}[/bold] "
621
+ f"[bold {source_color}]({source_label})[/bold {source_color}]\n",
622
+ style=theme.PRIMARY,
623
+ )
624
+ if shadowed_user_skill:
625
+ console.print(
626
+ f"[yellow]Note: Overrides user skill '{escape_markup(skill_name)}' "
627
+ "of the same name[/yellow]\n"
628
+ )
629
+ console.print(
630
+ f"[bold]Location:[/bold] {escape_markup(str(skill_path.parent))}/\n",
631
+ style=theme.MUTED,
632
+ )
633
+ console.print(
634
+ f"[bold]Description:[/bold] {escape_markup(skill['description'])}\n",
635
+ style=theme.MUTED,
636
+ )
637
+
638
+ # Show optional metadata fields
639
+ for label, value in _format_info_fields(skill):
640
+ console.print(
641
+ f"[bold]{label}:[/bold] {escape_markup(value)}\n",
642
+ style=theme.MUTED,
643
+ )
644
+
645
+ # List supporting files
646
+ skill_dir = skill_path.parent
647
+ supporting_files = [f for f in skill_dir.iterdir() if f.name != "SKILL.md"]
648
+
649
+ if supporting_files:
650
+ console.print("[bold]Supporting Files:[/bold]", style=theme.MUTED)
651
+ for file in supporting_files:
652
+ console.print(f" - {escape_markup(file.name)}", style=theme.MUTED)
653
+ console.print()
654
+
655
+ # Show the full SKILL.md content
656
+ console.print("[bold]Full SKILL.md Content:[/bold]\n", style=theme.PRIMARY)
657
+ console.print(skill_content, style=theme.MUTED)
658
+ console.print()
659
+
660
+
661
+ def _delete(
662
+ skill_name: str,
663
+ *,
664
+ agent: str = "agent",
665
+ project: bool = False,
666
+ force: bool = False,
667
+ dry_run: bool = False,
668
+ output_format: OutputFormat = "text",
669
+ ) -> None:
670
+ """Delete a skill directory after validation and optional user confirmation.
671
+
672
+ Validates the skill name, locates the skill in user or project directories,
673
+ confirms the deletion with the user (unless `force` is `True`), and
674
+ recursively removes the skill directory.
675
+
676
+ Args:
677
+ skill_name: Name of the skill to delete.
678
+ agent: Agent identifier for skills.
679
+ project: If `True`, only search in project skills.
680
+
681
+ If `False`, search in both user and project skills.
682
+ force: If `True`, skip confirmation prompt.
683
+ dry_run: If `True`, print what would be removed without deleting.
684
+ output_format: Output format — `'text'` (Rich) or `'json'`.
685
+
686
+ Raises:
687
+ SystemExit: If the deletion fails or a safety check is violated.
688
+ """
689
+ from rich.markup import escape as escape_markup
690
+
691
+ from docagent_cli.config import Settings, console, get_glyphs
692
+ from docagent_cli.skills.load import list_skills
693
+
694
+ # Validate skill name first (per Agent Skills spec)
695
+ is_valid, error_msg = _validate_name(skill_name)
696
+ if not is_valid:
697
+ console.print(f"[bold red]Error:[/bold red] Invalid skill name: {error_msg}")
698
+ raise SystemExit(1)
699
+
700
+ settings = Settings.from_environment()
701
+ user_skills_dir = settings.get_user_skills_dir(agent)
702
+ project_skills_dir = settings.get_project_skills_dir()
703
+ user_agent_skills_dir = settings.get_user_agent_skills_dir()
704
+ project_agent_skills_dir = settings.get_project_agent_skills_dir()
705
+
706
+ # Load skills based on --project flag
707
+ if project:
708
+ if not project_skills_dir:
709
+ console.print("[bold red]Error:[/bold red] Not in a project directory.")
710
+ raise SystemExit(1)
711
+ skills = list_skills(
712
+ user_skills_dir=None,
713
+ project_skills_dir=project_skills_dir,
714
+ user_agent_skills_dir=None,
715
+ project_agent_skills_dir=project_agent_skills_dir,
716
+ )
717
+ else:
718
+ skills = list_skills(
719
+ user_skills_dir=user_skills_dir,
720
+ project_skills_dir=project_skills_dir,
721
+ user_agent_skills_dir=user_agent_skills_dir,
722
+ project_agent_skills_dir=project_agent_skills_dir,
723
+ )
724
+
725
+ # Find the skill
726
+ skill = next((s for s in skills if s["name"] == skill_name), None)
727
+
728
+ if not skill:
729
+ console.print(f"[bold red]Error:[/bold red] Skill '{skill_name}' not found.")
730
+ console.print("\n[dim]Available skills:[/dim]", style=theme.MUTED)
731
+ for s in skills:
732
+ source_tag = "[project]" if s["source"] == "project" else "[user]"
733
+ console.print(f" - {s['name']} {source_tag}", style=theme.MUTED)
734
+ raise SystemExit(1)
735
+
736
+ skill_path = Path(skill["path"])
737
+ skill_dir = skill_path.parent
738
+
739
+ # Validate the path is safe to delete
740
+ base_dir = project_skills_dir if skill["source"] == "project" else user_skills_dir
741
+ if not base_dir:
742
+ console.print(
743
+ "[bold red]Error:[/bold red] Cannot determine base skills directory. "
744
+ "Refusing to delete."
745
+ )
746
+ raise SystemExit(1)
747
+ is_valid_path, path_error = _validate_skill_path(skill_dir, base_dir)
748
+ if not is_valid_path:
749
+ console.print(f"[bold red]Error:[/bold red] {path_error}")
750
+ raise SystemExit(1)
751
+
752
+ if dry_run:
753
+ if output_format == "json":
754
+ from docagent_cli.output import write_json
755
+
756
+ write_json(
757
+ "skills delete",
758
+ {
759
+ "name": skill_name,
760
+ "path": str(skill_dir),
761
+ "dry_run": True,
762
+ },
763
+ )
764
+ return
765
+ console.print(
766
+ f"Would delete skill '{skill_name}' at {skill_dir}",
767
+ )
768
+ console.print("No changes made.", style=theme.MUTED)
769
+ return
770
+
771
+ # Display confirmation summary (text mode only)
772
+ if output_format != "json":
773
+ source_label = "Project Skill" if skill["source"] == "project" else "User Skill"
774
+ source_color = "green" if skill["source"] == "project" else "cyan"
775
+
776
+ # Count files for the confirmation summary (display-only; a permission
777
+ # error in a subdirectory should not abort the entire delete flow).
778
+ try:
779
+ file_count = sum(1 for f in skill_dir.rglob("*") if f.is_file())
780
+ except OSError:
781
+ file_count = -1
782
+
783
+ console.print(
784
+ f"\n[bold]Skill:[/bold] {escape_markup(skill_name)}"
785
+ f" [bold {source_color}]({source_label})[/bold {source_color}]",
786
+ style=theme.PRIMARY,
787
+ )
788
+ console.print(
789
+ f"[bold]Location:[/bold] {escape_markup(str(skill_dir))}/",
790
+ style=theme.MUTED,
791
+ )
792
+ if file_count >= 0:
793
+ console.print(
794
+ f"[bold]Files:[/bold] {file_count} file(s) will be deleted\n",
795
+ style=theme.MUTED,
796
+ )
797
+ else:
798
+ console.print(
799
+ "[bold]Files:[/bold] (unable to count files)\n",
800
+ style=theme.MUTED,
801
+ )
802
+
803
+ # Confirmation (skip in JSON mode — no interactive prompt)
804
+ if not force and output_format != "json":
805
+ console.print(
806
+ "[yellow]Are you sure you want to delete this skill? (y/N)[/yellow] ",
807
+ end="",
808
+ )
809
+ try:
810
+ response = input().strip().lower()
811
+ except (EOFError, KeyboardInterrupt):
812
+ console.print("\n[dim]Cancelled.[/dim]")
813
+ return
814
+
815
+ if response not in {"y", "yes"}:
816
+ console.print("[dim]Cancelled.[/dim]")
817
+ return
818
+
819
+ # Re-validate immediately before deletion to narrow the TOCTOU window
820
+ # (the user may have paused at the confirmation prompt).
821
+ if skill_dir.is_symlink():
822
+ console.print(
823
+ "[bold red]Error:[/bold red] Skill directory is a symlink. "
824
+ "Refusing to delete for safety."
825
+ )
826
+ raise SystemExit(1)
827
+
828
+ is_valid_path, path_error = _validate_skill_path(skill_dir, base_dir)
829
+ if not is_valid_path:
830
+ console.print(f"[bold red]Error:[/bold red] {path_error}")
831
+ raise SystemExit(1)
832
+
833
+ # Delete the skill directory
834
+ try:
835
+ shutil.rmtree(skill_dir)
836
+ except OSError as e:
837
+ console.print(
838
+ f"[bold red]Error:[/bold red] Failed to fully delete skill: {e}\n"
839
+ f"[yellow]Warning:[/yellow] Some files may have been partially removed.\n"
840
+ f"Please inspect: {skill_dir}/"
841
+ )
842
+ raise SystemExit(1) from e
843
+
844
+ if output_format == "json":
845
+ from docagent_cli.output import write_json
846
+
847
+ write_json(
848
+ "skills delete",
849
+ {
850
+ "name": skill_name,
851
+ "path": str(skill_dir),
852
+ "deleted": True,
853
+ },
854
+ )
855
+ return
856
+
857
+ checkmark = get_glyphs().checkmark
858
+ console.print(
859
+ f"{checkmark} Skill '{skill_name}' deleted successfully!",
860
+ style=theme.PRIMARY,
861
+ )
862
+
863
+
864
+ def setup_skills_parser(
865
+ subparsers: Any, # noqa: ANN401 # argparse subparsers uses dynamic typing
866
+ *,
867
+ make_help_action: Callable[[Callable[[], None]], type[argparse.Action]],
868
+ add_output_args: Callable[[argparse.ArgumentParser], None] | None = None,
869
+ ) -> argparse.ArgumentParser:
870
+ """Setup the skills subcommand parser with all its subcommands.
871
+
872
+ Each subcommand gets a dedicated help screen so that
873
+ `docagent skills -h` shows skills-specific help, not the
874
+ global help.
875
+
876
+ Args:
877
+ subparsers: The parent subparsers object to add the skills parser to.
878
+ make_help_action: Factory that accepts a zero-argument help
879
+ callable and returns an argparse Action class wired to it.
880
+ add_output_args: Optional hook to add a shared `--json` flag.
881
+
882
+ Returns:
883
+ The skills subparser for argument handling.
884
+ """
885
+
886
+ # Lazy wrapper: defers ui import until the help action fires.
887
+ def _lazy_help(fn_name: str) -> Callable[[], None]:
888
+ def _show() -> None:
889
+ from docagent_cli import ui
890
+
891
+ getattr(ui, fn_name)()
892
+
893
+ return _show
894
+
895
+ def help_parent(help_fn: Callable[[], None]) -> list[argparse.ArgumentParser]:
896
+ parent = argparse.ArgumentParser(add_help=False)
897
+ parent.add_argument("-h", "--help", action=make_help_action(help_fn))
898
+ return [parent]
899
+
900
+ skills_parser = subparsers.add_parser(
901
+ "skills",
902
+ help="Manage agent skills",
903
+ description="Manage agent skills - list, create, view, and delete skills.",
904
+ add_help=False,
905
+ parents=help_parent(_lazy_help("show_skills_help")),
906
+ )
907
+ if add_output_args is not None:
908
+ add_output_args(skills_parser)
909
+ skills_subparsers = skills_parser.add_subparsers(
910
+ dest="skills_command", help="Skills command"
911
+ )
912
+
913
+ # Skills list
914
+ list_parser = skills_subparsers.add_parser(
915
+ "list",
916
+ aliases=["ls"],
917
+ help="List all available skills",
918
+ description=(
919
+ "List skills from all four skill directories "
920
+ "(user, user alias, project, project alias)."
921
+ ),
922
+ add_help=False,
923
+ parents=help_parent(_lazy_help("show_skills_list_help")),
924
+ )
925
+ if add_output_args is not None:
926
+ add_output_args(list_parser)
927
+ list_parser.add_argument(
928
+ "--agent",
929
+ default="agent",
930
+ help="Agent identifier for skills (default: agent)",
931
+ )
932
+ list_parser.add_argument(
933
+ "--project",
934
+ action="store_true",
935
+ help="Show only project-level skills",
936
+ )
937
+
938
+ # Skills create
939
+ create_parser = skills_subparsers.add_parser(
940
+ "create",
941
+ help="Create a new skill",
942
+ description=(
943
+ "Create a new skill with a template SKILL.md file. "
944
+ "By default, skills are created in "
945
+ "~/.docagent/<agent>/skills/. "
946
+ "Use --project to create in the project's "
947
+ ".docagent/skills/ directory."
948
+ ),
949
+ add_help=False,
950
+ parents=help_parent(_lazy_help("show_skills_create_help")),
951
+ )
952
+ if add_output_args is not None:
953
+ add_output_args(create_parser)
954
+ create_parser.add_argument(
955
+ "name",
956
+ help="Name of the skill to create (e.g., web-research)",
957
+ )
958
+ create_parser.add_argument(
959
+ "--agent",
960
+ default="agent",
961
+ help="Agent identifier for skills (default: agent)",
962
+ )
963
+ create_parser.add_argument(
964
+ "--project",
965
+ action="store_true",
966
+ help="Create skill in project directory instead of user directory",
967
+ )
968
+
969
+ # Skills info
970
+ info_parser = skills_subparsers.add_parser(
971
+ "info",
972
+ help="Show detailed information about a skill",
973
+ description="Show detailed information about a specific skill",
974
+ add_help=False,
975
+ parents=help_parent(_lazy_help("show_skills_info_help")),
976
+ )
977
+ if add_output_args is not None:
978
+ add_output_args(info_parser)
979
+ info_parser.add_argument("name", help="Name of the skill to show info for")
980
+ info_parser.add_argument(
981
+ "--agent",
982
+ default="agent",
983
+ help="Agent identifier for skills (default: agent)",
984
+ )
985
+ info_parser.add_argument(
986
+ "--project",
987
+ action="store_true",
988
+ help="Search only in project skills",
989
+ )
990
+
991
+ # Skills delete
992
+ delete_parser = skills_subparsers.add_parser(
993
+ "delete",
994
+ help="Delete a skill",
995
+ description="Delete a skill directory and all its contents",
996
+ add_help=False,
997
+ parents=help_parent(_lazy_help("show_skills_delete_help")),
998
+ )
999
+ if add_output_args is not None:
1000
+ add_output_args(delete_parser)
1001
+ delete_parser.add_argument("name", help="Name of the skill to delete")
1002
+ delete_parser.add_argument(
1003
+ "--agent",
1004
+ default="agent",
1005
+ help="Agent identifier for skills (default: agent)",
1006
+ )
1007
+ delete_parser.add_argument(
1008
+ "--project",
1009
+ action="store_true",
1010
+ help="Search only in project skills",
1011
+ )
1012
+ delete_parser.add_argument(
1013
+ "-f",
1014
+ "--force",
1015
+ action="store_true",
1016
+ help="Skip confirmation prompt",
1017
+ )
1018
+ delete_parser.add_argument(
1019
+ "--dry-run",
1020
+ action="store_true",
1021
+ help="Show what would happen without making changes",
1022
+ )
1023
+ return skills_parser
1024
+
1025
+
1026
+ def execute_skills_command(args: argparse.Namespace) -> None:
1027
+ """Execute skills subcommands based on parsed arguments.
1028
+
1029
+ Args:
1030
+ args: Parsed command line arguments with skills_command attribute
1031
+
1032
+ Raises:
1033
+ SystemExit: If the agent name is invalid.
1034
+ """
1035
+ from docagent_cli.config import console
1036
+
1037
+ # validate agent argument
1038
+ if args.agent:
1039
+ is_valid, error_msg = _validate_name(args.agent)
1040
+ if not is_valid:
1041
+ console.print(
1042
+ f"[bold red]Error:[/bold red] Invalid agent name: {error_msg}"
1043
+ )
1044
+ console.print(
1045
+ "[dim]Agent names must only contain letters, numbers, "
1046
+ "hyphens, and underscores.[/dim]",
1047
+ style=theme.MUTED,
1048
+ )
1049
+ raise SystemExit(1)
1050
+
1051
+ output_format = getattr(args, "output_format", "text")
1052
+
1053
+ # "ls" is an argparse alias for "list" — argparse stores the alias
1054
+ # as-is in the namespace, so we must match both values.
1055
+ if args.skills_command in {"list", "ls"}:
1056
+ _list(agent=args.agent, project=args.project, output_format=output_format)
1057
+ elif args.skills_command == "create":
1058
+ _create(
1059
+ args.name,
1060
+ agent=args.agent,
1061
+ project=args.project,
1062
+ output_format=output_format,
1063
+ )
1064
+ elif args.skills_command == "info":
1065
+ _info(
1066
+ args.name,
1067
+ agent=args.agent,
1068
+ project=args.project,
1069
+ output_format=output_format,
1070
+ )
1071
+ elif args.skills_command == "delete":
1072
+ _delete(
1073
+ args.name,
1074
+ agent=args.agent,
1075
+ project=args.project,
1076
+ force=args.force,
1077
+ dry_run=args.dry_run,
1078
+ output_format=output_format,
1079
+ )
1080
+ else:
1081
+ # No subcommand provided, show skills help screen
1082
+ from docagent_cli.ui import show_skills_help
1083
+
1084
+ show_skills_help()
1085
+
1086
+
1087
+ __all__ = [
1088
+ "execute_skills_command",
1089
+ "setup_skills_parser",
1090
+ ]