better-notion 1.5.5__tar.gz → 1.7.0__tar.gz

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 (203) hide show
  1. {better_notion-1.5.5 → better_notion-1.7.0}/PKG-INFO +1 -1
  2. better_notion-1.7.0/better_notion/_cli/docs/__init__.py +20 -0
  3. better_notion-1.7.0/better_notion/_cli/docs/base.py +212 -0
  4. better_notion-1.7.0/better_notion/_cli/docs/formatters.py +128 -0
  5. better_notion-1.7.0/better_notion/_cli/docs/registry.py +82 -0
  6. better_notion-1.7.0/better_notion/_cli/main.py +316 -0
  7. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/response.py +64 -8
  8. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/plugins/official/agents.py +294 -0
  9. better_notion-1.7.0/better_notion/plugins/official/agents_schema.py +860 -0
  10. {better_notion-1.5.5 → better_notion-1.7.0}/pyproject.toml +1 -1
  11. better_notion-1.7.0/tests/test_metadata.py +157 -0
  12. better_notion-1.7.0/tests/test_schema_command.py +178 -0
  13. better_notion-1.5.5/better_notion/_cli/main.py +0 -149
  14. {better_notion-1.5.5 → better_notion-1.7.0}/.gitignore +0 -0
  15. {better_notion-1.5.5 → better_notion-1.7.0}/LICENSE +0 -0
  16. {better_notion-1.5.5 → better_notion-1.7.0}/README.md +0 -0
  17. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/__init__.py +0 -0
  18. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/__init__.py +0 -0
  19. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/client.py +0 -0
  20. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/collections/__init__.py +0 -0
  21. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/collections/blocks.py +0 -0
  22. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/collections/comments.py +0 -0
  23. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/collections/databases.py +0 -0
  24. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/collections/pages.py +0 -0
  25. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/collections/users.py +0 -0
  26. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/entities/__init__.py +0 -0
  27. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/entities/block.py +0 -0
  28. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/entities/comment.py +0 -0
  29. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/entities/database.py +0 -0
  30. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/entities/page.py +0 -0
  31. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/entities/user.py +0 -0
  32. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/errors.py +0 -0
  33. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/oauth.py +0 -0
  34. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/properties/__init__.py +0 -0
  35. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/properties/base.py +0 -0
  36. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/properties/checkbox.py +0 -0
  37. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/properties/date.py +0 -0
  38. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/properties/email.py +0 -0
  39. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/properties/number.py +0 -0
  40. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/properties/phone.py +0 -0
  41. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/properties/rich_text.py +0 -0
  42. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/properties/select.py +0 -0
  43. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/properties/title.py +0 -0
  44. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/properties/url.py +0 -0
  45. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/utils/__init__.py +0 -0
  46. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/utils/pagination.py +0 -0
  47. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/__init__.py +0 -0
  48. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/async_typer.py +0 -0
  49. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/commands/__init__.py +0 -0
  50. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/commands/auth.py +0 -0
  51. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/commands/blocks.py +0 -0
  52. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/commands/comments.py +0 -0
  53. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/commands/config.py +0 -0
  54. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/commands/databases.py +0 -0
  55. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/commands/pages.py +0 -0
  56. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/commands/plugins.py +0 -0
  57. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/commands/search.py +0 -0
  58. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/commands/update.py +0 -0
  59. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/commands/users.py +0 -0
  60. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/commands/workspace.py +0 -0
  61. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/config.py +0 -0
  62. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/display.py +0 -0
  63. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/errors.py +0 -0
  64. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/markdown.py +0 -0
  65. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/utils/__init__.py +0 -0
  66. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/__init__.py +0 -0
  67. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/base/__init__.py +0 -0
  68. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/base/entity.py +0 -0
  69. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/cache/__init__.py +0 -0
  70. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/cache/cache.py +0 -0
  71. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/client.py +0 -0
  72. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/managers/__init__.py +0 -0
  73. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/managers/block_manager.py +0 -0
  74. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/managers/comment_manager.py +0 -0
  75. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/managers/database_manager.py +0 -0
  76. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/managers/page_manager.py +0 -0
  77. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/managers/user_manager.py +0 -0
  78. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/__init__.py +0 -0
  79. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/block.py +0 -0
  80. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/__init__.py +0 -0
  81. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/audio.py +0 -0
  82. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/bookmark.py +0 -0
  83. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/breadcrumb.py +0 -0
  84. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/bullet.py +0 -0
  85. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/callout.py +0 -0
  86. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/code.py +0 -0
  87. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/column.py +0 -0
  88. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/column_list.py +0 -0
  89. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/divider.py +0 -0
  90. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/embed.py +0 -0
  91. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/equation.py +0 -0
  92. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/file.py +0 -0
  93. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/heading.py +0 -0
  94. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/image.py +0 -0
  95. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/numbered.py +0 -0
  96. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/paragraph.py +0 -0
  97. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/pdf.py +0 -0
  98. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/quote.py +0 -0
  99. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/synced_block.py +0 -0
  100. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/table.py +0 -0
  101. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/table_row.py +0 -0
  102. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/template.py +0 -0
  103. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/todo.py +0 -0
  104. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/toggle.py +0 -0
  105. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/video.py +0 -0
  106. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/comment.py +0 -0
  107. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/database.py +0 -0
  108. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/page.py +0 -0
  109. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/user.py +0 -0
  110. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/parents/__init__.py +0 -0
  111. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/plugins.py +0 -0
  112. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/properties/__init__.py +0 -0
  113. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/properties/formula.py +0 -0
  114. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/properties/parsers.py +0 -0
  115. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/properties/relation.py +0 -0
  116. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/query/__init__.py +0 -0
  117. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/query/database_query.py +0 -0
  118. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/query/filter_translator.py +0 -0
  119. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/plugins/__init__.py +0 -0
  120. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/plugins/base.py +0 -0
  121. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/plugins/loader.py +0 -0
  122. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/plugins/official/__init__.py +0 -0
  123. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/plugins/official/agents_cli.py +0 -0
  124. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/plugins/official/agents_sdk/__init__.py +0 -0
  125. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/plugins/official/agents_sdk/managers.py +0 -0
  126. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/plugins/official/agents_sdk/models.py +0 -0
  127. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/plugins/official/agents_sdk/plugin.py +0 -0
  128. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/plugins/official/productivity.py +0 -0
  129. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/plugins/state.py +0 -0
  130. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/utils/__init__.py +0 -0
  131. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/utils/agents/__init__.py +0 -0
  132. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/utils/agents/auth.py +0 -0
  133. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/utils/agents/dependency_resolver.py +0 -0
  134. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/utils/agents/metadata.py +0 -0
  135. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/utils/agents/project_context.py +0 -0
  136. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/utils/agents/rbac.py +0 -0
  137. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/utils/agents/schemas.py +0 -0
  138. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/utils/agents/state_machine.py +0 -0
  139. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/utils/agents/workspace.py +0 -0
  140. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/utils/helpers.py +0 -0
  141. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/utils/retry.py +0 -0
  142. {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/utils/validators.py +0 -0
  143. {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/base/test_entity.py +0 -0
  144. {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/cache/test_cache.py +0 -0
  145. {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/models/__init__.py +0 -0
  146. {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/models/blocks/test_advanced_blocks.py +0 -0
  147. {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/models/test_block.py +0 -0
  148. {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/models/test_database.py +0 -0
  149. {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/models/test_database_bug.py +0 -0
  150. {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/models/test_page.py +0 -0
  151. {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/models/test_user.py +0 -0
  152. {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/properties/test_formula.py +0 -0
  153. {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/properties/test_parsers.py +0 -0
  154. {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/properties/test_relation.py +0 -0
  155. {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/query/test_database_query.py +0 -0
  156. {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/query/test_filter_translator.py +0 -0
  157. {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/test_client.py +0 -0
  158. {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/test_comment.py +0 -0
  159. {better_notion-1.5.5 → better_notion-1.7.0}/tests/agents/__init__.py +0 -0
  160. {better_notion-1.5.5 → better_notion-1.7.0}/tests/agents/test_auth.py +0 -0
  161. {better_notion-1.5.5 → better_notion-1.7.0}/tests/agents/test_dependency_resolver.py +0 -0
  162. {better_notion-1.5.5 → better_notion-1.7.0}/tests/agents/test_plugin.py +0 -0
  163. {better_notion-1.5.5 → better_notion-1.7.0}/tests/agents/test_project_context.py +0 -0
  164. {better_notion-1.5.5 → better_notion-1.7.0}/tests/agents/test_rbac.py +0 -0
  165. {better_notion-1.5.5 → better_notion-1.7.0}/tests/agents/test_schemas.py +0 -0
  166. {better_notion-1.5.5 → better_notion-1.7.0}/tests/agents/test_state_machine.py +0 -0
  167. {better_notion-1.5.5 → better_notion-1.7.0}/tests/agents/test_workspace.py +0 -0
  168. {better_notion-1.5.5 → better_notion-1.7.0}/tests/cli/__init__.py +0 -0
  169. {better_notion-1.5.5 → better_notion-1.7.0}/tests/cli/test_async_typer.py +0 -0
  170. {better_notion-1.5.5 → better_notion-1.7.0}/tests/cli/test_config.py +0 -0
  171. {better_notion-1.5.5 → better_notion-1.7.0}/tests/cli/test_display.py +0 -0
  172. {better_notion-1.5.5 → better_notion-1.7.0}/tests/cli/test_errors.py +0 -0
  173. {better_notion-1.5.5 → better_notion-1.7.0}/tests/cli/test_main.py +0 -0
  174. {better_notion-1.5.5 → better_notion-1.7.0}/tests/cli/test_pages_commands.py +0 -0
  175. {better_notion-1.5.5 → better_notion-1.7.0}/tests/cli/test_response.py +0 -0
  176. {better_notion-1.5.5 → better_notion-1.7.0}/tests/cli/test_update.py +0 -0
  177. {better_notion-1.5.5 → better_notion-1.7.0}/tests/conftest.py +0 -0
  178. {better_notion-1.5.5 → better_notion-1.7.0}/tests/integration/conftest.py +0 -0
  179. {better_notion-1.5.5 → better_notion-1.7.0}/tests/integration/test_blocks.py +0 -0
  180. {better_notion-1.5.5 → better_notion-1.7.0}/tests/integration/test_databases.py +0 -0
  181. {better_notion-1.5.5 → better_notion-1.7.0}/tests/integration/test_pages.py +0 -0
  182. {better_notion-1.5.5 → better_notion-1.7.0}/tests/integration/test_search.py +0 -0
  183. {better_notion-1.5.5 → better_notion-1.7.0}/tests/integration/test_users.py +0 -0
  184. {better_notion-1.5.5 → better_notion-1.7.0}/tests/plugins/__init__.py +0 -0
  185. {better_notion-1.5.5 → better_notion-1.7.0}/tests/plugins/test_agents_cli.py +0 -0
  186. {better_notion-1.5.5 → better_notion-1.7.0}/tests/plugins/test_agents_sdk_integration.py +0 -0
  187. {better_notion-1.5.5 → better_notion-1.7.0}/tests/plugins/test_agents_sdk_managers.py +0 -0
  188. {better_notion-1.5.5 → better_notion-1.7.0}/tests/plugins/test_agents_sdk_models.py +0 -0
  189. {better_notion-1.5.5 → better_notion-1.7.0}/tests/plugins/test_base.py +0 -0
  190. {better_notion-1.5.5 → better_notion-1.7.0}/tests/plugins/test_loader.py +0 -0
  191. {better_notion-1.5.5 → better_notion-1.7.0}/tests/plugins/test_marketplace.py +0 -0
  192. {better_notion-1.5.5 → better_notion-1.7.0}/tests/plugins/test_plugin_commands_state.py +0 -0
  193. {better_notion-1.5.5 → better_notion-1.7.0}/tests/plugins/test_productivity_plugin.py +0 -0
  194. {better_notion-1.5.5 → better_notion-1.7.0}/tests/plugins/test_state.py +0 -0
  195. {better_notion-1.5.5 → better_notion-1.7.0}/tests/sdk/__init__.py +0 -0
  196. {better_notion-1.5.5 → better_notion-1.7.0}/tests/sdk/test_plugin_system.py +0 -0
  197. {better_notion-1.5.5 → better_notion-1.7.0}/tests/unit/test_client.py +0 -0
  198. {better_notion-1.5.5 → better_notion-1.7.0}/tests/unit/test_collections.py +0 -0
  199. {better_notion-1.5.5 → better_notion-1.7.0}/tests/unit/test_entities.py +0 -0
  200. {better_notion-1.5.5 → better_notion-1.7.0}/tests/unit/test_errors.py +0 -0
  201. {better_notion-1.5.5 → better_notion-1.7.0}/tests/unit/test_helpers.py +0 -0
  202. {better_notion-1.5.5 → better_notion-1.7.0}/tests/unit/test_properties.py +0 -0
  203. {better_notion-1.5.5 → better_notion-1.7.0}/tests/utils/test_retry.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: better-notion
3
- Version: 1.5.5
3
+ Version: 1.7.0
4
4
  Summary: A high-level Python SDK for the Notion API with developer experience in mind.
5
5
  Project-URL: Homepage, https://github.com/nesalia-inc/better-notion
6
6
  Project-URL: Documentation, https://github.com/nesalia-inc/better-notion#readme
@@ -0,0 +1,20 @@
1
+ """Documentation system for AI agents.
2
+
3
+ This module provides infrastructure for documenting CLI commands
4
+ in a machine-readable format that AI agents can consume to understand
5
+ the system at a high level of abstraction.
6
+ """
7
+
8
+ from better_notion._cli.docs.base import (
9
+ Command,
10
+ Concept,
11
+ Schema,
12
+ Workflow,
13
+ )
14
+
15
+ __all__ = [
16
+ "Schema",
17
+ "Concept",
18
+ "Workflow",
19
+ "Command",
20
+ ]
@@ -0,0 +1,212 @@
1
+ """Base classes for documentation system.
2
+
3
+ This module provides the core data structures for documenting
4
+ CLI commands and workflows in a machine-readable format.
5
+ """
6
+
7
+ from dataclasses import dataclass, field
8
+ from typing import Any
9
+
10
+
11
+ @dataclass
12
+ class Concept:
13
+ """A concept represents a high-level idea in the system.
14
+
15
+ Concepts help AI agents understand what things are
16
+ (e.g., "workspace", "task", "version") beyond just
17
+ command syntax.
18
+
19
+ Attributes:
20
+ name: Name of the concept
21
+ description: Human-readable description
22
+ properties: Dict of concept properties and their meanings
23
+ relationships: Relationships to other concepts
24
+ """
25
+
26
+ name: str
27
+ description: str
28
+ properties: dict[str, Any] = field(default_factory=dict)
29
+ relationships: dict[str, str] = field(default_factory=dict)
30
+
31
+ def to_dict(self) -> dict[str, Any]:
32
+ """Convert to dictionary for JSON serialization."""
33
+ return {
34
+ "name": self.name,
35
+ "description": self.description,
36
+ "properties": self.properties,
37
+ "relationships": self.relationships,
38
+ }
39
+
40
+
41
+ @dataclass
42
+ class WorkflowStep:
43
+ """A single step in a workflow.
44
+
45
+ Attributes:
46
+ description: What this step does
47
+ command: Optional command to execute
48
+ purpose: Why this step is needed
49
+ """
50
+
51
+ description: str
52
+ command: str | None = None
53
+ purpose: str | None = None
54
+
55
+ def to_dict(self) -> dict[str, Any]:
56
+ """Convert to dictionary for JSON serialization."""
57
+ return {
58
+ "description": self.description,
59
+ "command": self.command,
60
+ "purpose": self.purpose,
61
+ }
62
+
63
+
64
+ @dataclass
65
+ class ErrorRecovery:
66
+ """Error recovery strategy for a command.
67
+
68
+ Attributes:
69
+ error_type: Type of error (e.g., "workspace_exists")
70
+ message: Human-readable error message
71
+ solutions: List of possible solutions with flags/actions
72
+ """
73
+
74
+ error_type: str
75
+ message: str
76
+ solutions: list[dict[str, Any]] = field(default_factory=list)
77
+
78
+ def to_dict(self) -> dict[str, Any]:
79
+ """Convert to dictionary for JSON serialization."""
80
+ return {
81
+ "error_type": self.error_type,
82
+ "message": self.message,
83
+ "solutions": self.solutions,
84
+ }
85
+
86
+
87
+ @dataclass
88
+ class Workflow:
89
+ """A workflow represents a sequence of operations.
90
+
91
+ Workflows help AI agents understand how to accomplish
92
+ high-level goals (e.g., "initialize_workspace",
93
+ "create_task").
94
+
95
+ Attributes:
96
+ name: Workflow name
97
+ description: What this workflow accomplishes
98
+ steps: List of steps in the workflow
99
+ commands: Example commands for this workflow
100
+ prerequisites: Required conditions before starting
101
+ error_recovery: Error handling strategies
102
+ """
103
+
104
+ name: str
105
+ description: str
106
+ steps: list[WorkflowStep | dict[str, Any]] = field(default_factory=list)
107
+ commands: list[str] = field(default_factory=list)
108
+ prerequisites: list[str] = field(default_factory=list)
109
+ error_recovery: dict[str, dict[str, Any]] = field(default_factory=dict)
110
+
111
+ def to_dict(self) -> dict[str, Any]:
112
+ """Convert to dictionary for JSON serialization."""
113
+ return {
114
+ "name": self.name,
115
+ "description": self.description,
116
+ "steps": [
117
+ step.to_dict() if isinstance(step, WorkflowStep) else step
118
+ for step in self.steps
119
+ ],
120
+ "commands": self.commands,
121
+ "prerequisites": self.prerequisites,
122
+ "error_recovery": self.error_recovery,
123
+ }
124
+
125
+
126
+ @dataclass
127
+ class Command:
128
+ """Documentation for a single command.
129
+
130
+ Command docs go beyond --help text to provide semantic
131
+ meaning and workflow context.
132
+
133
+ Attributes:
134
+ name: Command name
135
+ purpose: What this command does (semantic meaning)
136
+ description: Detailed description
137
+ flags: Dict of flag -> purpose
138
+ workflow: Which workflow this command belongs to
139
+ when_to_use: When this command should be used
140
+ error_recovery: Error handling strategies
141
+ subcommands: Dict of subcommand name -> subcommand documentation
142
+ """
143
+
144
+ name: str
145
+ purpose: str
146
+ description: str = ""
147
+ flags: dict[str, str] = field(default_factory=dict)
148
+ workflow: str | None = None
149
+ when_to_use: list[str] = field(default_factory=list)
150
+ error_recovery: dict[str, dict[str, Any]] = field(default_factory=dict)
151
+ subcommands: dict[str, dict[str, Any]] = field(default_factory=dict)
152
+
153
+ def to_dict(self) -> dict[str, Any]:
154
+ """Convert to dictionary for JSON serialization."""
155
+ result = {
156
+ "name": self.name,
157
+ "purpose": self.purpose,
158
+ "description": self.description,
159
+ "flags": self.flags,
160
+ "workflow": self.workflow,
161
+ "when_to_use": self.when_to_use,
162
+ "error_recovery": self.error_recovery,
163
+ }
164
+
165
+ # Add subcommands if present
166
+ if self.subcommands:
167
+ result["subcommands"] = self.subcommands
168
+
169
+ return result
170
+
171
+
172
+ @dataclass
173
+ class Schema:
174
+ """Complete schema documentation for a plugin.
175
+
176
+ A Schema provides everything an AI agent needs to understand
177
+ a plugin system at a high level.
178
+
179
+ Attributes:
180
+ name: Plugin name
181
+ version: Schema version
182
+ description: Plugin description
183
+ concepts: High-level concepts in the system
184
+ workflows: Available workflows
185
+ commands: Command documentation
186
+ best_practices: Recommended usage patterns
187
+ examples: Usage examples
188
+ """
189
+
190
+ name: str
191
+ version: str
192
+ description: str
193
+ concepts: list[Concept] = field(default_factory=list)
194
+ workflows: list[Workflow] = field(default_factory=list)
195
+ commands: dict[str, Command] = field(default_factory=dict)
196
+ best_practices: list[str] = field(default_factory=list)
197
+ examples: dict[str, str] = field(default_factory=dict)
198
+
199
+ def to_dict(self) -> dict[str, Any]:
200
+ """Convert to dictionary for JSON serialization."""
201
+ return {
202
+ "name": self.name,
203
+ "version": self.version,
204
+ "description": self.description,
205
+ "concepts": [concept.to_dict() for concept in self.concepts],
206
+ "workflows": [workflow.to_dict() for workflow in self.workflows],
207
+ "commands": {
208
+ name: command.to_dict() for name, command in self.commands.items()
209
+ },
210
+ "best_practices": self.best_practices,
211
+ "examples": self.examples,
212
+ }
@@ -0,0 +1,128 @@
1
+ """Formatters for schema documentation.
2
+
3
+ This module provides utilities to format Schema objects
4
+ into different output formats (JSON, YAML).
5
+ """
6
+
7
+ import json
8
+ from typing import Any
9
+
10
+ from better_notion._cli.docs.base import Schema
11
+
12
+
13
+ def format_schema_json(schema: Schema, *, pretty: bool = True) -> str:
14
+ """Format a Schema as JSON.
15
+
16
+ Args:
17
+ schema: Schema object to format
18
+ pretty: Whether to pretty-print with indentation
19
+
20
+ Returns:
21
+ JSON string representation of the schema
22
+ """
23
+ schema_dict = schema.to_dict()
24
+ if pretty:
25
+ return json.dumps(schema_dict, indent=2)
26
+ return json.dumps(schema_dict)
27
+
28
+
29
+ def format_schema_yaml(schema: Schema) -> str:
30
+ """Format a Schema as YAML.
31
+
32
+ Args:
33
+ schema: Schema object to format
34
+
35
+ Returns:
36
+ YAML string representation of the schema
37
+ """
38
+ try:
39
+ import yaml
40
+
41
+ return yaml.dump(schema.to_dict(), default_flow_style=False)
42
+ except ImportError:
43
+ # Fall back to JSON if pyyaml not installed
44
+ logger = __import__("logging").getLogger(__name__)
45
+ logger.warning("PyYAML not installed, falling back to JSON")
46
+ return format_schema_json(schema)
47
+
48
+
49
+ def format_schema_pretty(schema: Schema) -> str:
50
+ """Format a Schema as human-readable text with sections.
51
+
52
+ This provides a more readable format for human consumption
53
+ while maintaining machine-parsable structure.
54
+
55
+ Args:
56
+ schema: Schema object to format
57
+
58
+ Returns:
59
+ Formatted text string
60
+ """
61
+ lines = []
62
+ data = schema.to_dict()
63
+
64
+ # Header
65
+ lines.append(f"# {schema.name.upper()} SCHEMA")
66
+ lines.append(f"Version: {schema.version}")
67
+ lines.append(f"Description: {schema.description}")
68
+ lines.append("")
69
+
70
+ # Concepts
71
+ if data["concepts"]:
72
+ lines.append("## CONCEPTS")
73
+ for concept in data["concepts"]:
74
+ lines.append(f"### {concept['name']}")
75
+ lines.append(f"{concept['description']}")
76
+ if concept.get("properties"):
77
+ lines.append("**Properties:**")
78
+ for key, value in concept["properties"].items():
79
+ lines.append(f" - {key}: {value}")
80
+ if concept.get("relationships"):
81
+ lines.append("**Relationships:**")
82
+ for key, value in concept["relationships"].items():
83
+ lines.append(f" - {key}: {value}")
84
+ lines.append("")
85
+
86
+ # Workflows
87
+ if data["workflows"]:
88
+ lines.append("## WORKFLOWS")
89
+ for workflow in data["workflows"]:
90
+ lines.append(f"### {workflow['name']}")
91
+ lines.append(f"{workflow['description']}")
92
+ if workflow.get("steps"):
93
+ lines.append("**Steps:**")
94
+ for i, step in enumerate(workflow["steps"], 1):
95
+ if isinstance(step, dict):
96
+ lines.append(f" {i}. {step.get('description', step)}")
97
+ else:
98
+ lines.append(f" {i}. {step}")
99
+ if workflow.get("commands"):
100
+ lines.append("**Commands:**")
101
+ for cmd in workflow["commands"]:
102
+ lines.append(f" - {cmd}")
103
+ lines.append("")
104
+
105
+ # Commands
106
+ if data["commands"]:
107
+ lines.append("## COMMANDS")
108
+ for cmd_name, cmd in data["commands"].items():
109
+ lines.append(f"### {cmd_name}")
110
+ lines.append(f"**Purpose:** {cmd.get('purpose', 'N/A')}")
111
+ if cmd.get("flags"):
112
+ lines.append("**Flags:**")
113
+ for flag, purpose in cmd["flags"].items():
114
+ lines.append(f" - {flag}: {purpose}")
115
+ if cmd.get("when_to_use"):
116
+ lines.append("**When to use:**")
117
+ for usage in cmd["when_to_use"]:
118
+ lines.append(f" - {usage}")
119
+ lines.append("")
120
+
121
+ # Best Practices
122
+ if data.get("best_practices"):
123
+ lines.append("## BEST PRACTICES")
124
+ for practice in data["best_practices"]:
125
+ lines.append(f"- {practice}")
126
+ lines.append("")
127
+
128
+ return "\n".join(lines)
@@ -0,0 +1,82 @@
1
+ """Schema registry for plugin documentation.
2
+
3
+ This module provides a central registry where plugins can register
4
+ their documentation schemas for AI agent consumption.
5
+ """
6
+
7
+ import logging
8
+ from typing import Any
9
+
10
+ from better_notion._cli.docs.base import Schema
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ class SchemaRegistry:
16
+ """Registry for plugin documentation schemas.
17
+
18
+ This class maintains a collection of plugin schemas that
19
+ AI agents can query to understand the system.
20
+
21
+ Example:
22
+ >>> # Register a plugin schema
23
+ >>> SchemaRegistry.register("agents", AGENTS_SCHEMA)
24
+ >>>
25
+ >>> # Query for a plugin schema
26
+ >>> schema = SchemaRegistry.get("agents")
27
+ >>>
28
+ >>> # List all available schemas
29
+ >>> all_schemas = SchemaRegistry.list_all()
30
+ """
31
+
32
+ _schemas: dict[str, Schema] = {}
33
+
34
+ @classmethod
35
+ def register(cls, plugin_name: str, schema: Schema) -> None:
36
+ """Register a plugin schema.
37
+
38
+ Args:
39
+ plugin_name: Name of the plugin (e.g., "agents")
40
+ schema: Schema object containing plugin documentation
41
+ """
42
+ cls._schemas[plugin_name] = schema
43
+ logger.info(f"Registered schema for plugin: {plugin_name}")
44
+
45
+ @classmethod
46
+ def get(cls, plugin_name: str) -> Schema | None:
47
+ """Get a plugin schema by name.
48
+
49
+ Args:
50
+ plugin_name: Name of the plugin
51
+
52
+ Returns:
53
+ Schema object if found, None otherwise
54
+ """
55
+ return cls._schemas.get(plugin_name)
56
+
57
+ @classmethod
58
+ def list_all(cls) -> dict[str, Schema]:
59
+ """List all registered plugin schemas.
60
+
61
+ Returns:
62
+ Dict mapping plugin names to Schema objects
63
+ """
64
+ return cls._schemas.copy()
65
+
66
+ @classmethod
67
+ def get_all_names(cls) -> list[str]:
68
+ """Get list of all registered plugin names.
69
+
70
+ Returns:
71
+ List of plugin names
72
+ """
73
+ return list(cls._schemas.keys())
74
+
75
+ @classmethod
76
+ def clear(cls) -> None:
77
+ """Clear all registered schemas.
78
+
79
+ This is primarily useful for testing.
80
+ """
81
+ cls._schemas.clear()
82
+ logger.debug("Cleared schema registry")