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,873 @@
1
+ """Sandbox lifecycle management with provider abstraction."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import contextlib
6
+ import importlib
7
+ import importlib.util
8
+ import logging
9
+ import os
10
+ import shlex
11
+ import string
12
+ import time
13
+ from contextlib import contextmanager
14
+ from pathlib import Path
15
+ from typing import TYPE_CHECKING, Any
16
+
17
+ from rich.markup import escape as escape_markup
18
+
19
+ from docagent_cli.config import console, get_glyphs
20
+ from docagent_cli.integrations.sandbox_provider import (
21
+ SandboxNotFoundError,
22
+ SandboxProvider,
23
+ )
24
+
25
+ logger = logging.getLogger(__name__)
26
+
27
+ if TYPE_CHECKING:
28
+ from collections.abc import Generator
29
+ from types import ModuleType
30
+
31
+ from deepagents.backends.protocol import SandboxBackendProtocol
32
+ from langsmith.sandbox import SandboxTemplate
33
+
34
+
35
+ def _run_sandbox_setup(backend: SandboxBackendProtocol, setup_script_path: str) -> None:
36
+ """Run users setup script in sandbox with env var expansion.
37
+
38
+ Args:
39
+ backend: Sandbox backend instance
40
+ setup_script_path: Path to setup script file
41
+
42
+ Raises:
43
+ FileNotFoundError: If the setup script does not exist.
44
+ RuntimeError: If the setup script fails to execute.
45
+ """
46
+ script_path = Path(setup_script_path)
47
+ if not script_path.exists():
48
+ msg = f"Setup script not found: {setup_script_path}"
49
+ raise FileNotFoundError(msg)
50
+
51
+ console.print(
52
+ f"[dim]Running setup script: {escape_markup(setup_script_path)}...[/dim]"
53
+ )
54
+
55
+ # Read script content
56
+ script_content = script_path.read_text(encoding="utf-8")
57
+
58
+ # Expand ${VAR} syntax using local environment
59
+ template = string.Template(script_content)
60
+ expanded_script = template.safe_substitute(os.environ)
61
+
62
+ # Execute expanded script in sandbox
63
+ result = backend.execute(f"bash -c {shlex.quote(expanded_script)}")
64
+
65
+ if result.exit_code != 0:
66
+ console.print(f"[red]Setup script failed (exit {result.exit_code}):[/red]")
67
+ console.print(f"[dim]{escape_markup(result.output)}[/dim]")
68
+ msg = "Setup failed - aborting"
69
+ raise RuntimeError(msg)
70
+
71
+ console.print(f"[green]{get_glyphs().checkmark} Setup complete[/green]")
72
+
73
+
74
+ _PROVIDER_TO_WORKING_DIR = {
75
+ "agentcore": "/tmp", # noqa: S108 # AgentCore Code Interpreter working directory
76
+ "daytona": "/home/daytona",
77
+ "langsmith": "/tmp", # noqa: S108 # LangSmith sandbox working directory
78
+ "modal": "/workspace",
79
+ "runloop": "/home/user",
80
+ }
81
+ """Map of sandbox provider names to their default working directories."""
82
+
83
+
84
+ @contextmanager
85
+ def create_sandbox(
86
+ provider: str,
87
+ *,
88
+ sandbox_id: str | None = None,
89
+ setup_script_path: str | None = None,
90
+ ) -> Generator[SandboxBackendProtocol, None, None]:
91
+ """Create or connect to a sandbox of the specified provider.
92
+
93
+ This is the unified interface for sandbox creation using the
94
+ provider abstraction.
95
+
96
+ Args:
97
+ provider: Sandbox provider (`'agentcore'`, `'daytona'`, `'langsmith'`,
98
+ `'modal'`, `'runloop'`)
99
+ sandbox_id: Optional existing sandbox ID to reuse
100
+ setup_script_path: Optional path to setup script to run after sandbox starts
101
+
102
+ Yields:
103
+ `SandboxBackendProtocol` instance
104
+ """
105
+ # Get provider instance
106
+ provider_obj = _get_provider(provider)
107
+
108
+ # Determine if we should cleanup (only cleanup if we created it)
109
+ should_cleanup = sandbox_id is None
110
+
111
+ # Create or connect to sandbox
112
+ console.print(f"[yellow]Starting {provider} sandbox...[/yellow]")
113
+ backend = provider_obj.get_or_create(sandbox_id=sandbox_id)
114
+ glyphs = get_glyphs()
115
+ console.print(
116
+ f"[green]{glyphs.checkmark} {provider.capitalize()} sandbox ready: "
117
+ f"{backend.id}[/green]"
118
+ )
119
+
120
+ # Run setup script if provided
121
+ if setup_script_path:
122
+ _run_sandbox_setup(backend, setup_script_path)
123
+
124
+ try:
125
+ yield backend
126
+ finally:
127
+ if should_cleanup:
128
+ try:
129
+ console.print(
130
+ f"[dim]Terminating {provider} sandbox {backend.id}...[/dim]"
131
+ )
132
+ provider_obj.delete(sandbox_id=backend.id)
133
+ glyphs = get_glyphs()
134
+ console.print(
135
+ f"[dim]{glyphs.checkmark} {provider.capitalize()} sandbox "
136
+ f"{backend.id} terminated[/dim]"
137
+ )
138
+ except Exception as e: # noqa: BLE001 # Cleanup errors should not mask the original sandbox failure
139
+ warning = get_glyphs().warning
140
+ console.print(
141
+ f"[yellow]{warning} Cleanup failed for {provider} sandbox "
142
+ f"{backend.id}: {e}[/yellow]"
143
+ )
144
+
145
+
146
+ def _get_available_sandbox_types() -> list[str]:
147
+ """Get list of available sandbox provider types (internal).
148
+
149
+ Returns:
150
+ List of available sandbox provider type names
151
+ """
152
+ return sorted(_PROVIDER_TO_WORKING_DIR.keys())
153
+
154
+
155
+ def get_default_working_dir(provider: str) -> str:
156
+ """Get the default working directory for a given sandbox provider.
157
+
158
+ Args:
159
+ provider: Sandbox provider name (`'agentcore'`, `'daytona'`, `'langsmith'`,
160
+ `'modal'`, `'runloop'`)
161
+
162
+ Returns:
163
+ Default working directory path as string
164
+
165
+ Raises:
166
+ ValueError: If provider is unknown
167
+ """
168
+ if provider in _PROVIDER_TO_WORKING_DIR:
169
+ return _PROVIDER_TO_WORKING_DIR[provider]
170
+ msg = f"Unknown sandbox provider: {provider}"
171
+ raise ValueError(msg)
172
+
173
+
174
+ # ---------------------------------------------------------------------------
175
+ # Provider implementations
176
+ # ---------------------------------------------------------------------------
177
+
178
+
179
+ def _import_provider_module(
180
+ module_name: str,
181
+ *,
182
+ provider: str,
183
+ package: str,
184
+ ) -> ModuleType:
185
+ """Import an optional provider module with a provider-specific error message.
186
+
187
+ Args:
188
+ module_name: Python module name to import.
189
+ provider: Sandbox provider name (e.g. `'daytona'`).
190
+ package: PyPI package name exposed by the CLI extra.
191
+
192
+ Returns:
193
+ The imported module object.
194
+
195
+ Raises:
196
+ ImportError: If the optional dependency is not installed.
197
+ """
198
+ try:
199
+ return importlib.import_module(module_name)
200
+ except ImportError as exc:
201
+ msg = (
202
+ f"The '{provider}' sandbox provider requires the '{package}' package. "
203
+ f"Install it with: pip install 'docagent-cli[{provider}]'"
204
+ )
205
+ raise ImportError(msg) from exc
206
+
207
+
208
+ _LANGSMITH_DEFAULT_TEMPLATE = "docagent-cli"
209
+ """Default LangSmith sandbox template name used when no template is specified."""
210
+
211
+ _LANGSMITH_DEFAULT_IMAGE = "python:3"
212
+ """Default Docker image for LangSmith sandboxes when no image is provided."""
213
+
214
+
215
+ class _LangSmithProvider(SandboxProvider):
216
+ """LangSmith sandbox provider implementation.
217
+
218
+ Manages LangSmith sandbox lifecycle using the LangSmith SDK.
219
+ """
220
+
221
+ def __init__(self, api_key: str | None = None) -> None:
222
+ """Initialize LangSmith provider.
223
+
224
+ Args:
225
+ api_key: LangSmith API key (defaults to `LANGSMITH_SANDBOX_API_KEY`,
226
+ then `LANGSMITH_API_KEY` env var).
227
+
228
+ Raises:
229
+ ValueError: If no LangSmith API key is found.
230
+ """
231
+ from langsmith.sandbox import SandboxClient
232
+
233
+ from docagent_cli.model_config import resolve_env_var
234
+
235
+ self._api_key = (
236
+ api_key
237
+ or resolve_env_var("LANGSMITH_SANDBOX_API_KEY")
238
+ or resolve_env_var("LANGSMITH_API_KEY")
239
+ )
240
+ if not self._api_key:
241
+ msg = (
242
+ "No LangSmith sandbox API key found. Set "
243
+ "LANGSMITH_SANDBOX_API_KEY or LANGSMITH_API_KEY "
244
+ "(or the DEEPAGENTS_CLI_-prefixed equivalents)."
245
+ )
246
+ raise ValueError(msg)
247
+ self._client: SandboxClient = SandboxClient(api_key=self._api_key)
248
+
249
+ def get_or_create(
250
+ self,
251
+ *,
252
+ sandbox_id: str | None = None,
253
+ timeout: int = 180,
254
+ template: str | None = None,
255
+ template_image: str | None = None,
256
+ **kwargs: Any,
257
+ ) -> SandboxBackendProtocol:
258
+ """Get existing or create new LangSmith sandbox.
259
+
260
+ Args:
261
+ sandbox_id: Optional existing sandbox name to reuse
262
+ timeout: Timeout in seconds for sandbox startup
263
+ template: Template name for the sandbox
264
+ template_image: Docker image for the template
265
+ **kwargs: Additional LangSmith-specific parameters
266
+
267
+ Returns:
268
+ `LangSmithSandbox` instance
269
+
270
+ Raises:
271
+ RuntimeError: If sandbox connection or startup fails
272
+ TypeError: If unsupported keyword arguments are provided
273
+ """
274
+ from deepagents.backends.langsmith import LangSmithSandbox
275
+
276
+ if kwargs:
277
+ msg = f"Received unsupported arguments: {list(kwargs.keys())}"
278
+ raise TypeError(msg)
279
+ if sandbox_id:
280
+ # Connect to existing sandbox by name
281
+ try:
282
+ sandbox = self._client.get_sandbox(name=sandbox_id)
283
+ except Exception as e:
284
+ msg = f"Failed to connect to existing sandbox '{sandbox_id}': {e}"
285
+ raise RuntimeError(msg) from e
286
+ return LangSmithSandbox(sandbox)
287
+
288
+ resolved_template_name, resolved_image_name = self._resolve_template(
289
+ template, template_image
290
+ )
291
+
292
+ # Create new sandbox - ensure template exists first
293
+ self._ensure_template(resolved_template_name, resolved_image_name)
294
+
295
+ try:
296
+ sandbox = self._client.create_sandbox(
297
+ template_name=resolved_template_name, timeout=timeout
298
+ )
299
+ except Exception as e:
300
+ msg = (
301
+ f"Failed to create sandbox from template "
302
+ f"'{resolved_template_name}': {e}"
303
+ )
304
+ raise RuntimeError(msg) from e
305
+
306
+ # Verify sandbox is ready by polling
307
+ for _ in range(timeout // 2):
308
+ try:
309
+ result = sandbox.run("echo ready", timeout=5)
310
+ if result.exit_code == 0:
311
+ break
312
+ except Exception: # noqa: S110, BLE001 # Sandbox not ready yet, continue polling
313
+ pass
314
+ time.sleep(2)
315
+ else:
316
+ # Cleanup on failure
317
+ with contextlib.suppress(Exception):
318
+ self._client.delete_sandbox(sandbox.name)
319
+ msg = f"LangSmith sandbox failed to start within {timeout} seconds"
320
+ raise RuntimeError(msg)
321
+
322
+ return LangSmithSandbox(sandbox)
323
+
324
+ def delete(self, *, sandbox_id: str, **kwargs: Any) -> None: # noqa: ARG002 # Required by SandboxFactory interface
325
+ """Delete a LangSmith sandbox.
326
+
327
+ Args:
328
+ sandbox_id: Sandbox name to delete
329
+ **kwargs: Additional parameters
330
+ """
331
+ self._client.delete_sandbox(sandbox_id)
332
+
333
+ @staticmethod
334
+ def _resolve_template(
335
+ template: SandboxTemplate | str | None,
336
+ template_image: str | None = None,
337
+ ) -> tuple[str, str]:
338
+ """Resolve template name and image from kwargs.
339
+
340
+ Returns:
341
+ Tuple of `(template_name, template_image)`.
342
+
343
+ Always returns values, using defaults if not provided.
344
+ """
345
+ resolved_image = template_image or _LANGSMITH_DEFAULT_IMAGE
346
+ if template is None:
347
+ return _LANGSMITH_DEFAULT_TEMPLATE, resolved_image
348
+ if isinstance(template, str):
349
+ return template, resolved_image
350
+ # SandboxTemplate object - extract image if not provided
351
+ if template_image is None and template.image:
352
+ resolved_image = template.image
353
+ return template.name, resolved_image
354
+
355
+ def _ensure_template(
356
+ self,
357
+ template_name: str,
358
+ template_image: str,
359
+ ) -> None:
360
+ """Ensure template exists, creating it if needed.
361
+
362
+ Raises:
363
+ RuntimeError: If template check or creation fails
364
+ """
365
+ from langsmith.sandbox import ResourceNotFoundError
366
+
367
+ try:
368
+ self._client.get_template(template_name)
369
+ except ResourceNotFoundError as e:
370
+ if e.resource_type != "template":
371
+ msg = f"Unexpected resource not found: {e}"
372
+ raise RuntimeError(msg) from e
373
+ # Template doesn't exist, create it
374
+ try:
375
+ self._client.create_template(name=template_name, image=template_image)
376
+ except Exception as create_err:
377
+ msg = f"Failed to create template '{template_name}': {create_err}"
378
+ raise RuntimeError(msg) from create_err
379
+ except Exception as e:
380
+ msg = f"Failed to check template '{template_name}': {e}"
381
+ raise RuntimeError(msg) from e
382
+
383
+
384
+ class _DaytonaProvider(SandboxProvider):
385
+ """Daytona sandbox provider — lifecycle management for Daytona sandboxes."""
386
+
387
+ def __init__(self) -> None:
388
+ daytona_module = _import_provider_module(
389
+ "daytona",
390
+ provider="daytona",
391
+ package="langchain-daytona",
392
+ )
393
+
394
+ from docagent_cli.model_config import resolve_env_var
395
+
396
+ api_key = resolve_env_var("DAYTONA_API_KEY")
397
+ if not api_key:
398
+ msg = (
399
+ "No Daytona API key found. Set DAYTONA_API_KEY "
400
+ "or DEEPAGENTS_CLI_DAYTONA_API_KEY."
401
+ )
402
+ raise ValueError(msg)
403
+ self._client = daytona_module.Daytona(
404
+ daytona_module.DaytonaConfig(
405
+ api_key=api_key,
406
+ api_url=resolve_env_var("DAYTONA_API_URL"),
407
+ )
408
+ )
409
+
410
+ def get_or_create(
411
+ self,
412
+ *,
413
+ sandbox_id: str | None = None,
414
+ timeout: int = 180,
415
+ **kwargs: Any, # noqa: ARG002
416
+ ) -> SandboxBackendProtocol:
417
+ """Get or create a Daytona sandbox.
418
+
419
+ Args:
420
+ sandbox_id: Not supported yet — must be None.
421
+ timeout: Seconds to wait for startup.
422
+ **kwargs: Unused.
423
+
424
+ Returns:
425
+ `DaytonaSandbox` instance.
426
+
427
+ Raises:
428
+ NotImplementedError: If `sandbox_id` is provided.
429
+ RuntimeError: If the sandbox fails to start.
430
+ """
431
+ daytona_backend = _import_provider_module(
432
+ "langchain_daytona",
433
+ provider="daytona",
434
+ package="langchain-daytona",
435
+ )
436
+
437
+ if sandbox_id:
438
+ msg = (
439
+ "Connecting to existing Daytona sandbox by ID not yet supported. "
440
+ "Create a new sandbox by omitting sandbox_id parameter."
441
+ )
442
+ raise NotImplementedError(msg)
443
+
444
+ sandbox = self._client.create()
445
+ last_exc: Exception | None = None
446
+ for _ in range(timeout // 2):
447
+ try:
448
+ result = sandbox.process.exec("echo ready", timeout=5)
449
+ if result.exit_code == 0:
450
+ break
451
+ except Exception as exc: # noqa: BLE001 # Transient failures expected during readiness polling
452
+ last_exc = exc
453
+ time.sleep(2)
454
+ else:
455
+ with contextlib.suppress(Exception): # Best-effort cleanup
456
+ sandbox.delete()
457
+ detail = f" Last error: {last_exc}" if last_exc else ""
458
+ msg = f"Daytona sandbox failed to start within {timeout} seconds.{detail}"
459
+ raise RuntimeError(msg)
460
+
461
+ return daytona_backend.DaytonaSandbox(sandbox=sandbox)
462
+
463
+ def delete(self, *, sandbox_id: str, **kwargs: Any) -> None: # noqa: ARG002
464
+ """Delete a Daytona sandbox by id."""
465
+ sandbox = self._client.get(sandbox_id)
466
+ self._client.delete(sandbox)
467
+
468
+
469
+ class _ModalProvider(SandboxProvider):
470
+ """Modal sandbox provider — lifecycle management for Modal sandboxes."""
471
+
472
+ def __init__(self) -> None:
473
+ self._modal = _import_provider_module(
474
+ "modal",
475
+ provider="modal",
476
+ package="langchain-modal",
477
+ )
478
+
479
+ from docagent_cli.model_config import resolve_env_var
480
+
481
+ token_id = resolve_env_var("MODAL_TOKEN_ID")
482
+ token_secret = resolve_env_var("MODAL_TOKEN_SECRET")
483
+ if token_id and token_secret:
484
+ try:
485
+ self._client = self._modal.Client.from_credentials(
486
+ token_id, token_secret
487
+ )
488
+ except Exception as exc:
489
+ msg = (
490
+ "Failed to authenticate with Modal using "
491
+ "MODAL_TOKEN_ID / MODAL_TOKEN_SECRET "
492
+ "(or the DEEPAGENTS_CLI_-prefixed equivalents). "
493
+ "Verify your credentials are valid."
494
+ )
495
+ raise ValueError(msg) from exc
496
+ elif token_id or token_secret:
497
+ logger.warning(
498
+ "Only one of MODAL_TOKEN_ID / MODAL_TOKEN_SECRET is set; "
499
+ "both are required for explicit credential auth. "
500
+ "Falling back to default Modal authentication.",
501
+ )
502
+ self._client = None
503
+ else:
504
+ self._client = None
505
+
506
+ lookup_kwargs: dict[str, Any] = {
507
+ "name": "docagent-sandbox",
508
+ "create_if_missing": True,
509
+ }
510
+ if self._client is not None:
511
+ lookup_kwargs["client"] = self._client
512
+ self._app = self._modal.App.lookup(**lookup_kwargs)
513
+
514
+ def get_or_create(
515
+ self,
516
+ *,
517
+ sandbox_id: str | None = None,
518
+ timeout: int = 180,
519
+ **kwargs: Any, # noqa: ARG002
520
+ ) -> SandboxBackendProtocol:
521
+ """Get or create a Modal sandbox.
522
+
523
+ Args:
524
+ sandbox_id: Existing sandbox ID, or None to create.
525
+ timeout: Seconds to wait for startup.
526
+ **kwargs: Unused.
527
+
528
+ Returns:
529
+ `ModalSandbox` instance.
530
+
531
+ Raises:
532
+ RuntimeError: If the sandbox fails to start.
533
+ """
534
+ modal_backend = _import_provider_module(
535
+ "langchain_modal",
536
+ provider="modal",
537
+ package="langchain-modal",
538
+ )
539
+
540
+ client_kwargs: dict[str, Any] = {}
541
+ if self._client is not None:
542
+ client_kwargs["client"] = self._client
543
+
544
+ if sandbox_id:
545
+ sandbox = self._modal.Sandbox.from_id(
546
+ sandbox_id=sandbox_id,
547
+ app=self._app,
548
+ **client_kwargs,
549
+ )
550
+ else:
551
+ sandbox = self._modal.Sandbox.create(
552
+ app=self._app, workdir="/workspace", **client_kwargs
553
+ )
554
+ last_exc: Exception | None = None
555
+ for _ in range(timeout // 2):
556
+ if sandbox.poll() is not None:
557
+ msg = "Modal sandbox terminated unexpectedly during startup"
558
+ raise RuntimeError(msg)
559
+ try:
560
+ process = sandbox.exec("echo", "ready", timeout=5)
561
+ process.wait()
562
+ if process.returncode == 0:
563
+ break
564
+ except Exception as exc: # noqa: BLE001 # Transient failures expected during readiness polling
565
+ last_exc = exc
566
+ time.sleep(2)
567
+ else:
568
+ sandbox.terminate()
569
+ detail = f" Last error: {last_exc}" if last_exc else ""
570
+ msg = f"Modal sandbox failed to start within {timeout} seconds.{detail}"
571
+ raise RuntimeError(msg)
572
+
573
+ return modal_backend.ModalSandbox(sandbox=sandbox)
574
+
575
+ def delete(self, *, sandbox_id: str, **kwargs: Any) -> None: # noqa: ARG002
576
+ """Terminate a Modal sandbox by id."""
577
+ del_kwargs: dict[str, Any] = {"sandbox_id": sandbox_id, "app": self._app}
578
+ if self._client is not None:
579
+ del_kwargs["client"] = self._client
580
+ sandbox = self._modal.Sandbox.from_id(**del_kwargs)
581
+ sandbox.terminate()
582
+
583
+
584
+ class _RunloopProvider(SandboxProvider):
585
+ """Runloop sandbox provider — lifecycle management for Runloop devboxes."""
586
+
587
+ def __init__(self) -> None:
588
+ runloop_module = _import_provider_module(
589
+ "runloop_api_client",
590
+ provider="runloop",
591
+ package="langchain-runloop",
592
+ )
593
+
594
+ from docagent_cli.model_config import resolve_env_var
595
+
596
+ api_key = resolve_env_var("RUNLOOP_API_KEY")
597
+ if not api_key:
598
+ msg = (
599
+ "No Runloop API key found. Set RUNLOOP_API_KEY "
600
+ "or DEEPAGENTS_CLI_RUNLOOP_API_KEY."
601
+ )
602
+ raise ValueError(msg)
603
+ self._client = runloop_module.Runloop(bearer_token=api_key)
604
+
605
+ def get_or_create(
606
+ self,
607
+ *,
608
+ sandbox_id: str | None = None,
609
+ timeout: int = 180,
610
+ **kwargs: Any, # noqa: ARG002
611
+ ) -> SandboxBackendProtocol:
612
+ """Get or create a Runloop devbox.
613
+
614
+ Args:
615
+ sandbox_id: Existing devbox ID, or None to create.
616
+ timeout: Seconds to wait for startup.
617
+ **kwargs: Unused.
618
+
619
+ Returns:
620
+ `RunloopSandbox` instance.
621
+
622
+ Raises:
623
+ RuntimeError: If the devbox fails to start.
624
+ SandboxNotFoundError: If `sandbox_id` does not exist.
625
+ """
626
+ runloop_backend = _import_provider_module(
627
+ "langchain_runloop",
628
+ provider="runloop",
629
+ package="langchain-runloop",
630
+ )
631
+ runloop_sdk = _import_provider_module(
632
+ "runloop_api_client.sdk",
633
+ provider="runloop",
634
+ package="langchain-runloop",
635
+ )
636
+
637
+ if sandbox_id:
638
+ try:
639
+ self._client.devboxes.retrieve(id=sandbox_id)
640
+ except KeyError as e:
641
+ raise SandboxNotFoundError(sandbox_id) from e
642
+ else:
643
+ view = self._client.devboxes.create()
644
+ sandbox_id = view.id
645
+ for _ in range(timeout // 2):
646
+ status = self._client.devboxes.retrieve(id=sandbox_id)
647
+ if status.status == "running":
648
+ break
649
+ time.sleep(2)
650
+ else:
651
+ self._client.devboxes.shutdown(id=sandbox_id)
652
+ msg = f"Devbox failed to start within {timeout} seconds"
653
+ raise RuntimeError(msg)
654
+
655
+ devbox = runloop_sdk.Devbox(self._client, sandbox_id)
656
+ return runloop_backend.RunloopSandbox(devbox=devbox)
657
+
658
+ def delete(self, *, sandbox_id: str, **kwargs: Any) -> None: # noqa: ARG002
659
+ """Shut down a Runloop devbox by id."""
660
+ self._client.devboxes.shutdown(id=sandbox_id)
661
+
662
+
663
+ class _AgentCoreProvider(SandboxProvider):
664
+ """AgentCore Code Interpreter sandbox provider.
665
+
666
+ Manages AgentCore session lifecycle. Sessions cannot be reconnected after
667
+ the CLI exits — the `sandbox_id` parameter is not supported.
668
+ """
669
+
670
+ def __init__(self, region: str | None = None) -> None:
671
+ """Initialize AgentCore provider.
672
+
673
+ Args:
674
+ region: AWS region (defaults to `AWS_REGION` /
675
+ `AWS_DEFAULT_REGION` / `us-west-2`).
676
+
677
+ Raises:
678
+ ValueError: If boto3 is installed and AWS credentials cannot
679
+ be resolved.
680
+ """
681
+ self._region = region or os.environ.get(
682
+ "AWS_REGION", os.environ.get("AWS_DEFAULT_REGION", "us-west-2")
683
+ )
684
+
685
+ # Validate AWS credentials early for a clear error message.
686
+ try:
687
+ import boto3 # ty: ignore[unresolved-import]
688
+
689
+ session = boto3.Session()
690
+ credentials = session.get_credentials()
691
+ if credentials is None:
692
+ msg = (
693
+ "AWS credentials not found. Configure via "
694
+ "AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY/AWS_SESSION_TOKEN, "
695
+ "~/.aws/credentials, or an IAM role."
696
+ )
697
+ raise ValueError(msg) # noqa: TRY301 # intentional raise for early credential validation
698
+ except ImportError:
699
+ logger.debug("boto3 not installed; skipping credential pre-check")
700
+ except ValueError:
701
+ raise
702
+ except Exception:
703
+ logger.warning(
704
+ "AWS credential pre-validation failed — the session may "
705
+ "fail to start. Check your AWS configuration.",
706
+ exc_info=True,
707
+ )
708
+
709
+ self._active_interpreters: dict[str, Any] = {}
710
+
711
+ def get_or_create(
712
+ self,
713
+ *,
714
+ sandbox_id: str | None = None,
715
+ **kwargs: Any, # noqa: ARG002 # required by SandboxProvider interface
716
+ ) -> SandboxBackendProtocol:
717
+ """Create a new AgentCore Code Interpreter session.
718
+
719
+ Args:
720
+ sandbox_id: Not supported — raises `NotImplementedError`
721
+ if provided.
722
+ **kwargs: Additional parameters (unused).
723
+
724
+ Returns:
725
+ `AgentCoreSandbox` instance wrapping the started interpreter.
726
+
727
+ Raises:
728
+ NotImplementedError: If `sandbox_id` is provided.
729
+ """
730
+ if sandbox_id:
731
+ msg = (
732
+ "AgentCore does not support reconnecting to existing sessions. "
733
+ "Remove the --sandbox-id option."
734
+ )
735
+ raise NotImplementedError(msg)
736
+
737
+ agentcore_module = _import_provider_module(
738
+ "bedrock_agentcore.tools.code_interpreter_client",
739
+ provider="agentcore",
740
+ package="langchain-agentcore-codeinterpreter",
741
+ )
742
+ agentcore_backend = _import_provider_module(
743
+ "langchain_agentcore_codeinterpreter",
744
+ provider="agentcore",
745
+ package="langchain-agentcore-codeinterpreter",
746
+ )
747
+
748
+ interpreter = agentcore_module.CodeInterpreter(
749
+ region=self._region,
750
+ integration_source="docagent-cli",
751
+ )
752
+ try:
753
+ interpreter.start()
754
+ except Exception:
755
+ with contextlib.suppress(Exception):
756
+ interpreter.stop()
757
+ raise
758
+
759
+ backend = agentcore_backend.AgentCoreSandbox(interpreter=interpreter)
760
+ self._active_interpreters[backend.id] = interpreter
761
+ return backend
762
+
763
+ def delete(self, *, sandbox_id: str, **kwargs: Any) -> None: # noqa: ARG002 # required by SandboxProvider interface
764
+ """Stop an AgentCore session.
765
+
766
+ Args:
767
+ sandbox_id: Session ID to stop.
768
+ **kwargs: Additional parameters (unused).
769
+ """
770
+ interpreter = self._active_interpreters.pop(sandbox_id, None)
771
+ if interpreter:
772
+ try:
773
+ interpreter.stop()
774
+ logger.info("AgentCore session %s stopped", sandbox_id)
775
+ except Exception:
776
+ logger.warning(
777
+ "Failed to stop AgentCore session %s — the session may "
778
+ "still be running and incurring costs. Check the AWS "
779
+ "console to verify.",
780
+ sandbox_id,
781
+ exc_info=True,
782
+ )
783
+ else:
784
+ logger.info(
785
+ "AgentCore session %s not tracked (may have already expired)",
786
+ sandbox_id,
787
+ )
788
+
789
+
790
+ def _get_provider(provider_name: str) -> SandboxProvider:
791
+ """Get a `SandboxProvider` instance for the specified provider (internal).
792
+
793
+ Args:
794
+ provider_name: Name of the provider (`'agentcore'`, `'daytona'`, `'langsmith'`,
795
+ `'modal'`, `'runloop'`)
796
+
797
+ Returns:
798
+ `SandboxProvider` instance
799
+
800
+ Raises:
801
+ ValueError: If `provider_name` is unknown.
802
+ """
803
+ if provider_name == "agentcore":
804
+ return _AgentCoreProvider()
805
+ if provider_name == "daytona":
806
+ return _DaytonaProvider()
807
+ if provider_name == "langsmith":
808
+ return _LangSmithProvider()
809
+ if provider_name == "modal":
810
+ return _ModalProvider()
811
+ if provider_name == "runloop":
812
+ return _RunloopProvider()
813
+ msg = (
814
+ f"Unknown sandbox provider: {provider_name}. "
815
+ f"Available providers: {', '.join(_get_available_sandbox_types())}"
816
+ )
817
+ raise ValueError(msg)
818
+
819
+
820
+ def verify_sandbox_deps(provider: str) -> None:
821
+ """Check that the required packages for a sandbox provider are installed.
822
+
823
+ Uses `importlib.util.find_spec` for a lightweight check with no actual
824
+ imports. Call this in the CLI process *before* spawning the server
825
+ subprocess so users get a clear, actionable error instead of an opaque
826
+ server crash.
827
+
828
+ Args:
829
+ provider: Sandbox provider name (e.g. `'daytona'`).
830
+
831
+ Raises:
832
+ ImportError: If the provider's backend package is not installed.
833
+ """
834
+ if not provider or provider in {"none", "langsmith"}:
835
+ return
836
+
837
+ # Map provider name → (backend module, pip extra).
838
+ # Only the backend module is checked because the underlying SDK is a
839
+ # transitive dependency of the backend package.
840
+ backend_modules: dict[str, tuple[str, str]] = {
841
+ "agentcore": ("langchain_agentcore_codeinterpreter", "agentcore"),
842
+ "daytona": ("langchain_daytona", "daytona"),
843
+ "modal": ("langchain_modal", "modal"),
844
+ "runloop": ("langchain_runloop", "runloop"),
845
+ }
846
+
847
+ entry = backend_modules.get(provider)
848
+ if entry is None:
849
+ logger.debug(
850
+ "No backend_modules entry for provider %r; skipping pre-flight check",
851
+ provider,
852
+ )
853
+ return
854
+
855
+ module_name, extra = entry
856
+ try:
857
+ found = importlib.util.find_spec(module_name) is not None
858
+ except (ImportError, ValueError):
859
+ found = False
860
+
861
+ if not found:
862
+ msg = (
863
+ f"Missing dependencies for '{provider}' sandbox. "
864
+ f"Install with: pip install 'docagent-cli[{extra}]'"
865
+ )
866
+ raise ImportError(msg)
867
+
868
+
869
+ __all__ = [
870
+ "create_sandbox",
871
+ "get_default_working_dir",
872
+ "verify_sandbox_deps",
873
+ ]