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.
- {better_notion-1.5.5 → better_notion-1.7.0}/PKG-INFO +1 -1
- better_notion-1.7.0/better_notion/_cli/docs/__init__.py +20 -0
- better_notion-1.7.0/better_notion/_cli/docs/base.py +212 -0
- better_notion-1.7.0/better_notion/_cli/docs/formatters.py +128 -0
- better_notion-1.7.0/better_notion/_cli/docs/registry.py +82 -0
- better_notion-1.7.0/better_notion/_cli/main.py +316 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/response.py +64 -8
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/plugins/official/agents.py +294 -0
- better_notion-1.7.0/better_notion/plugins/official/agents_schema.py +860 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/pyproject.toml +1 -1
- better_notion-1.7.0/tests/test_metadata.py +157 -0
- better_notion-1.7.0/tests/test_schema_command.py +178 -0
- better_notion-1.5.5/better_notion/_cli/main.py +0 -149
- {better_notion-1.5.5 → better_notion-1.7.0}/.gitignore +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/LICENSE +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/README.md +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/client.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/collections/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/collections/blocks.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/collections/comments.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/collections/databases.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/collections/pages.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/collections/users.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/entities/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/entities/block.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/entities/comment.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/entities/database.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/entities/page.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/entities/user.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/errors.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/oauth.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/properties/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/properties/base.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/properties/checkbox.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/properties/date.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/properties/email.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/properties/number.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/properties/phone.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/properties/rich_text.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/properties/select.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/properties/title.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/properties/url.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/utils/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_api/utils/pagination.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/async_typer.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/commands/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/commands/auth.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/commands/blocks.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/commands/comments.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/commands/config.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/commands/databases.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/commands/pages.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/commands/plugins.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/commands/search.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/commands/update.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/commands/users.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/commands/workspace.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/config.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/display.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/errors.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/markdown.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_cli/utils/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/base/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/base/entity.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/cache/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/cache/cache.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/client.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/managers/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/managers/block_manager.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/managers/comment_manager.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/managers/database_manager.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/managers/page_manager.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/managers/user_manager.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/block.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/audio.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/bookmark.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/breadcrumb.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/bullet.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/callout.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/code.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/column.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/column_list.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/divider.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/embed.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/equation.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/file.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/heading.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/image.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/numbered.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/paragraph.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/pdf.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/quote.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/synced_block.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/table.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/table_row.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/template.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/todo.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/toggle.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/blocks/video.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/comment.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/database.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/page.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/models/user.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/parents/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/plugins.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/properties/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/properties/formula.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/properties/parsers.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/properties/relation.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/query/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/query/database_query.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/_sdk/query/filter_translator.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/plugins/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/plugins/base.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/plugins/loader.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/plugins/official/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/plugins/official/agents_cli.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/plugins/official/agents_sdk/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/plugins/official/agents_sdk/managers.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/plugins/official/agents_sdk/models.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/plugins/official/agents_sdk/plugin.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/plugins/official/productivity.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/plugins/state.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/utils/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/utils/agents/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/utils/agents/auth.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/utils/agents/dependency_resolver.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/utils/agents/metadata.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/utils/agents/project_context.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/utils/agents/rbac.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/utils/agents/schemas.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/utils/agents/state_machine.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/utils/agents/workspace.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/utils/helpers.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/utils/retry.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/better_notion/utils/validators.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/base/test_entity.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/cache/test_cache.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/models/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/models/blocks/test_advanced_blocks.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/models/test_block.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/models/test_database.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/models/test_database_bug.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/models/test_page.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/models/test_user.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/properties/test_formula.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/properties/test_parsers.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/properties/test_relation.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/query/test_database_query.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/query/test_filter_translator.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/test_client.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/_sdk/test_comment.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/agents/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/agents/test_auth.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/agents/test_dependency_resolver.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/agents/test_plugin.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/agents/test_project_context.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/agents/test_rbac.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/agents/test_schemas.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/agents/test_state_machine.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/agents/test_workspace.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/cli/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/cli/test_async_typer.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/cli/test_config.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/cli/test_display.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/cli/test_errors.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/cli/test_main.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/cli/test_pages_commands.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/cli/test_response.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/cli/test_update.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/conftest.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/integration/conftest.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/integration/test_blocks.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/integration/test_databases.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/integration/test_pages.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/integration/test_search.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/integration/test_users.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/plugins/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/plugins/test_agents_cli.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/plugins/test_agents_sdk_integration.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/plugins/test_agents_sdk_managers.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/plugins/test_agents_sdk_models.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/plugins/test_base.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/plugins/test_loader.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/plugins/test_marketplace.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/plugins/test_plugin_commands_state.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/plugins/test_productivity_plugin.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/plugins/test_state.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/sdk/__init__.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/sdk/test_plugin_system.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/unit/test_client.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/unit/test_collections.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/unit/test_entities.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/unit/test_errors.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/unit/test_helpers.py +0 -0
- {better_notion-1.5.5 → better_notion-1.7.0}/tests/unit/test_properties.py +0 -0
- {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.
|
|
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")
|