devrev-Python-SDK 2.7.0__tar.gz → 2.8.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.
- devrev_python_sdk-2.8.0/.github/ISSUE_TEMPLATE/article-artifact-simplification.md +582 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/PKG-INFO +28 -12
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/README.md +27 -11
- devrev_python_sdk-2.8.0/docs/api/services/articles.md +208 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/services/index.md +28 -1
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/changelog.md +18 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/mcp/tools-reference.md +8 -3
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/pyproject.toml +1 -1
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/client.py +15 -2
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/__init__.py +33 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/articles.py +16 -0
- devrev_python_sdk-2.8.0/src/devrev/models/artifacts.py +125 -0
- devrev_python_sdk-2.8.0/src/devrev/services/articles.py +693 -0
- devrev_python_sdk-2.8.0/src/devrev/services/artifacts.py +403 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/services/base.py +13 -2
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/tools/articles.py +32 -17
- devrev_python_sdk-2.8.0/tests/integration/test_articles_lifecycle.py +555 -0
- devrev_python_sdk-2.8.0/tests/integration/test_mcp_articles.py +355 -0
- devrev_python_sdk-2.8.0/tests/performance/__init__.py +1 -0
- devrev_python_sdk-2.8.0/tests/performance/test_articles_performance.py +476 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/mcp/test_tools_articles.py +2 -0
- devrev_python_sdk-2.8.0/tests/unit/test_articles_unified.py +1428 -0
- devrev_python_sdk-2.8.0/tests/unit/test_artifacts.py +639 -0
- devrev_python_sdk-2.8.0/tests/unit/test_backward_compatibility.py +313 -0
- devrev_python_sdk-2.8.0/tests/unit/test_error_handling.py +365 -0
- devrev_python_sdk-2.7.0/docs/api/services/articles.md +0 -59
- devrev_python_sdk-2.7.0/src/devrev/services/articles.py +0 -130
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.augment/agents/bug-fixer.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.augment/agents/builder.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.augment/agents/documentation.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.augment/agents/foreman.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.augment/agents/pr-review-boss.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.augment/agents/release-manager.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.augment/agents/simplifier.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.augment/agents/tester.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.augment/commands/foreman-work.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.augment/commands/release-prepare.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.augment/commands/review-start.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.augment/commands/simplify-code.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.augment/rules/code-quality.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.augment/rules/data-modeling.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.augment/rules/devrev-sdk.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.augment/rules/git-workflow.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.augment/rules/pull-requests.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.augment/rules/python-development.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.augment/rules/security.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.augment/rules/testing.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.dockerignore +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.env.sample +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.github/ISSUE_TEMPLATE/question.yml +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.github/dependabot.yml +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.github/pull_request_template.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.github/workflows/api-check.yml +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.github/workflows/ci.yml +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.github/workflows/claude-code-review.yml +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.github/workflows/claude.yml +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.github/workflows/deploy.yml +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.github/workflows/docs.yml +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.github/workflows/integration-tests.yml +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.github/workflows/release.yml +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.github/workflows/sync-openapi.yml +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.gitignore +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/.pre-commit-config.yaml +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/CODE_OF_CONDUCT.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/CONTRIBUTING.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/DEPRECATIONS.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/Dockerfile +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/KNOWN_ISSUES.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/OPENAPI_SPEC_DISCREPANCIES.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/SECURITY.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/augment-mcp-config-remote.json +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/augment-mcp-config.json +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/augment-settings.json +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/benchmarks/README.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/benchmarks/bench_http_client.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/benchmarks/bench_models.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/benchmarks/bench_pagination.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/benchmarks/conftest.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/context7.json +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/deploy/README.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/deploy/audit-logging-setup.sh +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/deploy/cloudbuild.yaml +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/deploy/monitoring/README.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/deploy/monitoring/alert-policies.yaml +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/deploy/monitoring/dashboard.json +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/deploy/monitoring/validate-config.sh +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/deploy/service.yaml +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docker-compose.yml +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/beta/brands.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/beta/engagements.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/beta/incidents.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/beta/index.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/beta/question-answers.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/beta/recommendations.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/beta/search.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/beta/uoms.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/beta-api-differences.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/client.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/config.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/exceptions.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/index.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/models/accounts.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/models/base.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/models/index.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/models/users.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/models/works.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/services/accounts.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/services/code-changes.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/services/conversations.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/services/dev-users.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/services/groups.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/services/links.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/services/parts.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/services/rev-users.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/services/slas.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/services/tags.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/services/timeline-entries.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/services/webhooks.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/api/services/works.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/examples/advanced.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/examples/basic.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/examples/beta-features.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/examples/index.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/examples/integrations.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/getting-started/authentication.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/getting-started/index.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/getting-started/installation.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/getting-started/quickstart.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/guides/beta-api.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/guides/compatibility.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/guides/configuration.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/guides/error-handling.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/guides/github-actions-setup.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/guides/index.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/guides/logging.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/guides/pagination.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/guides/sync-vs-async.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/guides/testing.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/guides/version-support.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/guides/write-integration-testing-strategy.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/hooks/copy_llms.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/index.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/mcp/deployment.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/mcp/index.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/mcp/quickstart.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/docs/stylesheets/extra.css +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/examples/README.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/examples/basic/README.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/examples/basic/async_example.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/examples/basic/create_work.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/examples/basic/error_handling.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/examples/basic/list_accounts.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/examples/basic/pagination.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/examples/basic/search_users.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/examples/integrations/cloud_functions/README.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/examples/integrations/cloud_functions/main.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/examples/integrations/cloud_functions/requirements.txt +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/examples/integrations/fastapi/README.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/examples/integrations/fastapi/main.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/examples/integrations/fastapi/requirements.txt +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/examples/integrations/flask/README.md +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/examples/integrations/flask/app.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/examples/integrations/flask/requirements.txt +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/llms-ctx-full.txt +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/llms-ctx.txt +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/llms-mcp.txt +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/llms.txt +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/mkdocs.yml +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/openapi-beta.yaml +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/openapi-public.yaml +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/openapi-spec-corrections.yaml +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/scripts/build_ai_docs.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/scripts/setup-github-secrets.sh +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/__init__.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/config.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/exceptions.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/accounts.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/base.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/brands.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/code_changes.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/conversations.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/dev_users.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/engagements.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/groups.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/incidents.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/links.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/notifications.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/parts.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/preferences.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/question_answers.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/recommendations.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/rev_users.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/search.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/slas.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/sync.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/tags.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/tasks.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/timeline_entries.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/timeline_events.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/track_events.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/uoms.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/webhooks.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/widgets.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/models/works.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/py.typed +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/services/__init__.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/services/accounts.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/services/brands.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/services/code_changes.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/services/conversations.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/services/dev_users.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/services/engagements.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/services/groups.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/services/incidents.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/services/links.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/services/notifications.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/services/parts.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/services/preferences.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/services/question_answers.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/services/recommendations.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/services/rev_users.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/services/search.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/services/slas.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/services/tags.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/services/timeline_entries.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/services/track_events.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/services/uoms.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/services/webhooks.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/services/works.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/utils/__init__.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/utils/deprecation.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/utils/http.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/utils/logging.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev/utils/pagination.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/__init__.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/__main__.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/config.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/middleware/__init__.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/middleware/audit.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/middleware/auth.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/middleware/health.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/middleware/rate_limit.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/prompts/__init__.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/prompts/escalation.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/prompts/investigate.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/prompts/response.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/prompts/summarize.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/prompts/triage.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/resources/__init__.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/resources/account.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/resources/article.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/resources/conversation.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/resources/part.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/resources/server_info.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/resources/ticket.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/resources/user.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/server.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/tools/__init__.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/tools/accounts.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/tools/conversations.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/tools/engagements.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/tools/groups.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/tools/incidents.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/tools/links.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/tools/parts.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/tools/recommendations.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/tools/search.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/tools/server_info.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/tools/slas.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/tools/tags.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/tools/timeline.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/tools/users.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/tools/works.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/utils/__init__.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/utils/errors.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/utils/formatting.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/src/devrev_mcp/utils/pagination.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/__init__.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/conftest.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/integration/__init__.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/integration/conftest.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/integration/test_accounts_e2e.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/integration/test_all_readonly_endpoints.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/integration/test_backwards_compatibility.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/integration/test_contacts_e2e.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/integration/test_core_services_phase1.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/integration/test_extended_services_phase2.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/integration/test_get_endpoints.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/integration/test_issues_e2e.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/integration/test_kb_articles_e2e.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/integration/test_ping.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/integration/test_question_answers_e2e.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/integration/test_readonly_endpoints.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/integration/test_specialized_services_phase3.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/integration/test_tickets_e2e.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/integration/test_write_operations.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/integration/utils/__init__.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/integration/utils/cleanup.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/integration/utils/constants.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/integration/utils/data_manager.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/__init__.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/mcp/__init__.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/mcp/conftest.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/mcp/test_audit.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/mcp/test_config.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/mcp/test_phase4_transport.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/mcp/test_prompts.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/mcp/test_resources.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/mcp/test_server_info.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/mcp/test_tools_accounts.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/mcp/test_tools_conversations.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/mcp/test_tools_engagements.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/mcp/test_tools_groups.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/mcp/test_tools_incidents.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/mcp/test_tools_links.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/mcp/test_tools_parts.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/mcp/test_tools_recommendations.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/mcp/test_tools_search.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/mcp/test_tools_slas.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/mcp/test_tools_tags.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/mcp/test_tools_timeline.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/mcp/test_tools_users.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/mcp/test_tools_works.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/mcp/test_utils.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/models/__init__.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/models/test_user_state_regression.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/services/__init__.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/services/conftest.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/services/test_articles.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/services/test_async_services.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/services/test_brands.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/services/test_code_changes.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/services/test_conversations.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/services/test_engagements.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/services/test_groups.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/services/test_incidents.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/services/test_links.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/services/test_notifications.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/services/test_parts.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/services/test_preferences.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/services/test_question_answers.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/services/test_recommendations.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/services/test_search.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/services/test_slas.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/services/test_tags.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/services/test_timeline_entries.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/services/test_track_events.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/services/test_uoms.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/services/test_webhooks.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/services/test_works.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/test_base_service.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/test_client.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/test_config.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/test_deprecation.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/test_exceptions.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/test_http.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/test_logging.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/tests/unit/test_pagination.py +0 -0
- {devrev_python_sdk-2.7.0 → devrev_python_sdk-2.8.0}/uv.lock +0 -0
|
@@ -0,0 +1,582 @@
|
|
|
1
|
+
# Simplify DevRev Article & Artifact Management in SDK and MCP Tools
|
|
2
|
+
|
|
3
|
+
## Problem Statement
|
|
4
|
+
|
|
5
|
+
The DevRev API separates articles into two entities that must be managed separately:
|
|
6
|
+
- **Articles** – contain metadata and a "description" field (which is NOT the article's main content)
|
|
7
|
+
- **Artifacts** – store the actual body/content of an article
|
|
8
|
+
|
|
9
|
+
Currently, the SDK methods are thin wrappers that directly mirror these individual API endpoints, forcing consumers to understand and manage both entities separately. This creates unnecessary complexity for common operations like creating, reading, updating, and deleting articles with their content.
|
|
10
|
+
|
|
11
|
+
### Example of Current Complexity
|
|
12
|
+
|
|
13
|
+
To create an article with content today:
|
|
14
|
+
```python
|
|
15
|
+
# 1. Prepare artifact
|
|
16
|
+
prepare_req = ArtifactPrepareRequest(
|
|
17
|
+
file_name="article.html",
|
|
18
|
+
file_type="text/html",
|
|
19
|
+
configuration_set="article_media"
|
|
20
|
+
)
|
|
21
|
+
prepare_resp = client.artifacts.prepare(prepare_req)
|
|
22
|
+
|
|
23
|
+
# 2. Upload content to S3
|
|
24
|
+
import httpx
|
|
25
|
+
form_data = {item.key: item.value for item in prepare_resp.form_data}
|
|
26
|
+
httpx.post(prepare_resp.url, data=form_data, files={"file": content})
|
|
27
|
+
|
|
28
|
+
# 3. Create article with artifact reference
|
|
29
|
+
article_req = ArticlesCreateRequest(
|
|
30
|
+
title="My Article",
|
|
31
|
+
owned_by=["DEVU-123"],
|
|
32
|
+
resource={"content_artifact": prepare_resp.id}
|
|
33
|
+
)
|
|
34
|
+
article = client.articles.create(article_req)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
This should be as simple as:
|
|
38
|
+
```python
|
|
39
|
+
article = client.articles.create_with_content(
|
|
40
|
+
title="My Article",
|
|
41
|
+
content="<html>...</html>",
|
|
42
|
+
owned_by=["DEVU-123"]
|
|
43
|
+
)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Goal
|
|
47
|
+
|
|
48
|
+
Refactor the SDK and the related MCP tools to provide a **unified, higher-level abstraction** for article management that hides the article/artifact separation from the consumer, while preserving access to all underlying functionality.
|
|
49
|
+
|
|
50
|
+
## User Impact
|
|
51
|
+
|
|
52
|
+
**Who Benefits:**
|
|
53
|
+
- SDK users who need to create/manage articles with content
|
|
54
|
+
- MCP tool users (AI agents) working with articles
|
|
55
|
+
- New developers integrating DevRev article functionality
|
|
56
|
+
- Technical writers managing documentation
|
|
57
|
+
|
|
58
|
+
**Time Savings:**
|
|
59
|
+
- Current: 15-20 lines of code + error handling for article creation
|
|
60
|
+
- New: 3-5 lines of code with automatic error handling
|
|
61
|
+
- Estimated 70% reduction in integration time
|
|
62
|
+
|
|
63
|
+
**Pain Points Addressed:**
|
|
64
|
+
- No need to understand artifact lifecycle
|
|
65
|
+
- No manual S3 upload handling
|
|
66
|
+
- No artifact ID management
|
|
67
|
+
- Automatic rollback on failures
|
|
68
|
+
- Clear separation of content vs metadata
|
|
69
|
+
|
|
70
|
+
## Investigation Findings
|
|
71
|
+
|
|
72
|
+
### API Architecture Discovery
|
|
73
|
+
|
|
74
|
+
Based on OpenAPI spec analysis:
|
|
75
|
+
|
|
76
|
+
**Articles API** (`/articles.*`)
|
|
77
|
+
- Manages article metadata (title, status, description)
|
|
78
|
+
- `resource` field contains artifact references:
|
|
79
|
+
- `content_artifact` - ID of artifact containing article body
|
|
80
|
+
- `attachments` - IDs of attachment artifacts
|
|
81
|
+
- `artifacts` - (deprecated) legacy references
|
|
82
|
+
- `description` field is SHORT metadata, NOT article content
|
|
83
|
+
|
|
84
|
+
**Artifacts API** (`/artifacts.*`)
|
|
85
|
+
- Manages file storage (S3-style)
|
|
86
|
+
- `artifacts.prepare` - creates artifact + upload URL
|
|
87
|
+
- `artifacts.get` - retrieves metadata
|
|
88
|
+
- `artifacts.list` - lists artifacts for parent
|
|
89
|
+
- `artifacts.locate` - gets download URL
|
|
90
|
+
- `artifact-configuration-set` enum includes `article_media` for article content
|
|
91
|
+
|
|
92
|
+
**Complete Workflow:**
|
|
93
|
+
1. `artifacts.prepare` with `configuration_set: article_media`
|
|
94
|
+
2. Upload content to returned S3 URL
|
|
95
|
+
3. `articles.create` with `resource.content_artifact` = artifact ID
|
|
96
|
+
4. To update: `artifacts.versions.prepare` for new version
|
|
97
|
+
5. To read: `artifacts.locate` → fetch from URL
|
|
98
|
+
|
|
99
|
+
### Current State
|
|
100
|
+
|
|
101
|
+
**SDK:**
|
|
102
|
+
- ✅ ArticlesService with basic CRUD
|
|
103
|
+
- ❌ No ArtifactsService
|
|
104
|
+
- ❌ No unified methods
|
|
105
|
+
|
|
106
|
+
**MCP Tools:**
|
|
107
|
+
- ✅ Basic article operations
|
|
108
|
+
- ❌ Misleading `description` parameter (users think it's content)
|
|
109
|
+
- ❌ No artifact operations
|
|
110
|
+
|
|
111
|
+
## Proposed Solution
|
|
112
|
+
|
|
113
|
+
### 1. Artifacts Service Foundation
|
|
114
|
+
|
|
115
|
+
Create complete artifact management:
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
class ArtifactsService(BaseService):
|
|
119
|
+
def prepare(self, request: ArtifactPrepareRequest) -> ArtifactPrepareResponse
|
|
120
|
+
def upload(self, prepare_response: ArtifactPrepareResponse, content: bytes | str) -> str
|
|
121
|
+
def get(self, request: ArtifactGetRequest) -> Artifact
|
|
122
|
+
def locate(self, request: ArtifactLocateRequest) -> str
|
|
123
|
+
def download(self, artifact_id: str, version: str | None = None) -> bytes
|
|
124
|
+
def list_for_parent(self, parent_id: str) -> list[Artifact]
|
|
125
|
+
def prepare_version(self, request: ArtifactVersionsPrepareRequest) -> ArtifactVersionsPrepareResponse
|
|
126
|
+
def delete_version(self, request: ArtifactVersionsDeleteRequest) -> None
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### 2. Unified Article Methods
|
|
130
|
+
|
|
131
|
+
Add high-level methods to ArticlesService:
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
class ArticlesService(BaseService):
|
|
135
|
+
# Existing methods remain unchanged
|
|
136
|
+
def create(self, request: ArticlesCreateRequest) -> Article
|
|
137
|
+
def get(self, request: ArticlesGetRequest) -> Article
|
|
138
|
+
# ...
|
|
139
|
+
|
|
140
|
+
# NEW unified methods
|
|
141
|
+
def create_with_content(
|
|
142
|
+
self,
|
|
143
|
+
title: str,
|
|
144
|
+
content: str,
|
|
145
|
+
*,
|
|
146
|
+
owned_by: list[str],
|
|
147
|
+
description: str | None = None,
|
|
148
|
+
status: ArticleStatus | None = None,
|
|
149
|
+
content_format: str = "text/plain",
|
|
150
|
+
**kwargs
|
|
151
|
+
) -> Article:
|
|
152
|
+
"""Create article with content in a single operation."""
|
|
153
|
+
|
|
154
|
+
def get_with_content(self, id: str) -> ArticleWithContent:
|
|
155
|
+
"""Get article with its content in a single call."""
|
|
156
|
+
|
|
157
|
+
def update_content(
|
|
158
|
+
self,
|
|
159
|
+
id: str,
|
|
160
|
+
content: str,
|
|
161
|
+
content_format: str | None = None
|
|
162
|
+
) -> Article:
|
|
163
|
+
"""Update article content by creating new artifact version."""
|
|
164
|
+
|
|
165
|
+
def update_with_content(
|
|
166
|
+
self,
|
|
167
|
+
id: str,
|
|
168
|
+
*,
|
|
169
|
+
title: str | None = None,
|
|
170
|
+
content: str | None = None,
|
|
171
|
+
description: str | None = None,
|
|
172
|
+
status: ArticleStatus | None = None,
|
|
173
|
+
**kwargs
|
|
174
|
+
) -> Article:
|
|
175
|
+
"""Update article metadata and/or content."""
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### 3. New Models
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
class ArticleWithContent(DevRevResponseModel):
|
|
182
|
+
"""Article with its content loaded."""
|
|
183
|
+
article: Article
|
|
184
|
+
content: str
|
|
185
|
+
content_format: str
|
|
186
|
+
content_version: str | None
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### 4. MCP Tool Updates
|
|
190
|
+
|
|
191
|
+
Update tools to use unified methods:
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
@mcp.tool()
|
|
195
|
+
async def devrev_articles_create(
|
|
196
|
+
ctx: Context,
|
|
197
|
+
title: str,
|
|
198
|
+
content: str, # Changed from 'description' to 'content'
|
|
199
|
+
owned_by: list[str],
|
|
200
|
+
description: str | None = None, # Optional metadata
|
|
201
|
+
status: str | None = None,
|
|
202
|
+
content_format: str = "text/html"
|
|
203
|
+
) -> dict[str, Any]:
|
|
204
|
+
"""Create a new article with content.
|
|
205
|
+
|
|
206
|
+
Args:
|
|
207
|
+
title: Article title
|
|
208
|
+
content: The article body content (HTML, markdown, or plain text)
|
|
209
|
+
owned_by: List of dev user IDs
|
|
210
|
+
description: Optional short metadata description
|
|
211
|
+
status: Optional article status (draft, published, archived)
|
|
212
|
+
content_format: Content MIME type
|
|
213
|
+
"""
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Error Handling Strategy
|
|
217
|
+
|
|
218
|
+
### Atomic Operations
|
|
219
|
+
All unified methods implement atomic operations with automatic rollback:
|
|
220
|
+
|
|
221
|
+
1. **create_with_content** - If artifact upload fails, no article is created
|
|
222
|
+
2. **update_content** - If new version upload fails, article reference unchanged
|
|
223
|
+
3. **Cleanup** - Failed uploads automatically delete orphaned artifacts
|
|
224
|
+
|
|
225
|
+
### Error Scenarios
|
|
226
|
+
|
|
227
|
+
| Scenario | Behavior | User Experience |
|
|
228
|
+
|----------|----------|-----------------|
|
|
229
|
+
| Artifact prepare fails | Raise DevRevError before upload | Clear error message |
|
|
230
|
+
| Upload to S3 fails | Delete artifact, raise error | No orphaned artifacts |
|
|
231
|
+
| Article create fails | Delete uploaded artifact | Complete rollback |
|
|
232
|
+
| Network timeout | Retry with exponential backoff | Automatic recovery |
|
|
233
|
+
| Invalid content format | Validate before upload | Fast failure |
|
|
234
|
+
|
|
235
|
+
### Retry Strategy
|
|
236
|
+
- Network errors: 3 retries with exponential backoff
|
|
237
|
+
- Rate limits: Automatic retry with proper delays
|
|
238
|
+
- Server errors (5xx): Retry with backoff
|
|
239
|
+
- Client errors (4xx): No retry, immediate failure
|
|
240
|
+
|
|
241
|
+
## Performance Considerations
|
|
242
|
+
|
|
243
|
+
### Optimization Strategies
|
|
244
|
+
|
|
245
|
+
1. **Lazy Loading**
|
|
246
|
+
- `get()` returns metadata only (fast)
|
|
247
|
+
- `get_with_content()` fetches content only when needed
|
|
248
|
+
- Explicit opt-in for content loading
|
|
249
|
+
|
|
250
|
+
2. **Caching**
|
|
251
|
+
- Cache artifact download URLs (valid for 15 minutes)
|
|
252
|
+
- Optional local content caching
|
|
253
|
+
- Respect HTTP cache headers from S3
|
|
254
|
+
|
|
255
|
+
3. **Bulk Operations** (Future Enhancement)
|
|
256
|
+
```python
|
|
257
|
+
# Efficient batch creation
|
|
258
|
+
articles = client.articles.bulk_create_with_content([
|
|
259
|
+
{"title": "Article 1", "content": "..."},
|
|
260
|
+
{"title": "Article 2", "content": "..."},
|
|
261
|
+
])
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
4. **Streaming Support** (Future Enhancement)
|
|
265
|
+
- Large content streaming for articles >10MB
|
|
266
|
+
- Progress callbacks for uploads
|
|
267
|
+
- Chunked uploads for reliability
|
|
268
|
+
|
|
269
|
+
### Benchmarks (Target)
|
|
270
|
+
- `create_with_content()`: <2s for typical article (50KB)
|
|
271
|
+
- `get_with_content()`: <1s for cached content
|
|
272
|
+
- `update_content()`: <1.5s for version update
|
|
273
|
+
- Overhead vs manual: <200ms
|
|
274
|
+
|
|
275
|
+
## Implementation Plan
|
|
276
|
+
|
|
277
|
+
### Phase 1: Artifact Service Foundation ✅
|
|
278
|
+
- [x] Create artifact models (`src/devrev/models/artifacts.py`)
|
|
279
|
+
- [x] Create `ArtifactsService` class (`src/devrev/services/artifacts.py`)
|
|
280
|
+
- [x] Implement basic artifact operations (prepare, upload, get, locate, download)
|
|
281
|
+
- [x] Update client to expose `client.artifacts`
|
|
282
|
+
- [x] Add `ArticleWithContent` model
|
|
283
|
+
- [ ] Add tests for artifact service
|
|
284
|
+
|
|
285
|
+
### Phase 2: Unified Article Methods ✅
|
|
286
|
+
**Architectural Decision**: Option 2 (Store client reference in service) ✅
|
|
287
|
+
|
|
288
|
+
**Implementation Complete:**
|
|
289
|
+
```python
|
|
290
|
+
class BaseService:
|
|
291
|
+
def __init__(self, http_client, parent_client=None):
|
|
292
|
+
self._http = http_client
|
|
293
|
+
self._parent_client = parent_client
|
|
294
|
+
|
|
295
|
+
class ArticlesService(BaseService):
|
|
296
|
+
def create_with_content(...):
|
|
297
|
+
# Accesses self._parent_client.artifacts
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
**Tasks:**
|
|
301
|
+
- [x] Decide on architectural approach (Option 2 selected)
|
|
302
|
+
- [x] Modify BaseService to accept parent_client parameter
|
|
303
|
+
- [x] Update client initialization to pass parent_client=self
|
|
304
|
+
- [x] Implement `create_with_content` in ArticlesService (sync + async)
|
|
305
|
+
- [x] Implement `get_with_content` in ArticlesService (sync + async)
|
|
306
|
+
- [x] Implement `update_content` in ArticlesService (sync + async)
|
|
307
|
+
- [x] Implement `update_with_content` in ArticlesService (sync + async)
|
|
308
|
+
- [x] Add `resource` field to Article model
|
|
309
|
+
- [ ] Add tests for unified methods
|
|
310
|
+
|
|
311
|
+
### Phase 3: MCP Tool Updates ✅
|
|
312
|
+
- [x] Update `devrev_articles_create` to use `create_with_content`
|
|
313
|
+
- Changed `description` param to `content` (article body)
|
|
314
|
+
- Added `description` as optional metadata
|
|
315
|
+
- Added `content_format` parameter
|
|
316
|
+
- [x] Update `devrev_articles_get` to support `include_content` parameter
|
|
317
|
+
- `include_content=False` → metadata only
|
|
318
|
+
- `include_content=True` → full ArticleWithContent
|
|
319
|
+
- [x] Update `devrev_articles_update` to support content updates
|
|
320
|
+
- Added `content` parameter for body updates
|
|
321
|
+
- Uses `update_with_content()` method
|
|
322
|
+
- [x] Update tool docstrings to clarify content vs description
|
|
323
|
+
- [ ] Add integration tests for MCP tools
|
|
324
|
+
|
|
325
|
+
### Phase 4: Documentation ✅
|
|
326
|
+
- [x] Update SDK documentation with unified examples
|
|
327
|
+
- [x] docs/api/services/articles.md - Added comprehensive examples
|
|
328
|
+
- [x] docs/api/services/index.md - Added unified article management section
|
|
329
|
+
- [x] README.md - Updated article examples with unified methods
|
|
330
|
+
- [x] docs/mcp/tools-reference.md - Updated article tools descriptions
|
|
331
|
+
- [x] docs/changelog.md - Added unreleased section documenting changes
|
|
332
|
+
- [x] Add migration guide for existing users (included in issue template)
|
|
333
|
+
- [x] Update MCP tool descriptions
|
|
334
|
+
- [x] Add examples showing both high-level and low-level usage
|
|
335
|
+
|
|
336
|
+
## Migration Guide Preview
|
|
337
|
+
|
|
338
|
+
### Before (Current SDK)
|
|
339
|
+
```python
|
|
340
|
+
from devrev import DevRevClient
|
|
341
|
+
from devrev.models import ArticlesCreateRequest, ArtifactPrepareRequest
|
|
342
|
+
import httpx
|
|
343
|
+
|
|
344
|
+
client = DevRevClient(api_token="...")
|
|
345
|
+
|
|
346
|
+
# 1. Prepare artifact
|
|
347
|
+
prepare_req = ArtifactPrepareRequest(
|
|
348
|
+
file_name="guide.html",
|
|
349
|
+
file_type="text/html",
|
|
350
|
+
configuration_set="article_media"
|
|
351
|
+
)
|
|
352
|
+
prepare_resp = client.artifacts.prepare(prepare_req)
|
|
353
|
+
|
|
354
|
+
# 2. Upload to S3
|
|
355
|
+
form_data = {item.key: item.value for item in prepare_resp.form_data}
|
|
356
|
+
httpx.post(prepare_resp.url, data=form_data, files={"file": content})
|
|
357
|
+
|
|
358
|
+
# 3. Create article
|
|
359
|
+
article_req = ArticlesCreateRequest(
|
|
360
|
+
title="User Guide",
|
|
361
|
+
owned_by=["DEVU-123"],
|
|
362
|
+
resource={"content_artifact": prepare_resp.id}
|
|
363
|
+
)
|
|
364
|
+
article = client.articles.create(article_req)
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### After (Unified SDK)
|
|
368
|
+
```python
|
|
369
|
+
from devrev import DevRevClient
|
|
370
|
+
|
|
371
|
+
client = DevRevClient(api_token="...")
|
|
372
|
+
|
|
373
|
+
# Single unified call
|
|
374
|
+
article = client.articles.create_with_content(
|
|
375
|
+
title="User Guide",
|
|
376
|
+
content="<html>...</html>",
|
|
377
|
+
owned_by=["DEVU-123"],
|
|
378
|
+
content_format="text/html"
|
|
379
|
+
)
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### MCP Tool Changes
|
|
383
|
+
|
|
384
|
+
**Before:**
|
|
385
|
+
```python
|
|
386
|
+
# Misleading - 'description' sounds like metadata but was used for content
|
|
387
|
+
devrev_articles_create(
|
|
388
|
+
title="API Guide",
|
|
389
|
+
description="<html>...</html>", # Confusing parameter name
|
|
390
|
+
owned_by=["DEVU-123"]
|
|
391
|
+
)
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
**After:**
|
|
395
|
+
```python
|
|
396
|
+
# Clear separation of content vs metadata
|
|
397
|
+
devrev_articles_create(
|
|
398
|
+
title="API Guide",
|
|
399
|
+
content="<html>...</html>", # Clear: this is the article body
|
|
400
|
+
description="A guide for API usage", # Clear: this is metadata
|
|
401
|
+
owned_by=["DEVU-123"]
|
|
402
|
+
)
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
## API Compatibility Matrix
|
|
406
|
+
|
|
407
|
+
| Feature | SDK Version | API Version | Breaking Change |
|
|
408
|
+
|---------|-------------|-------------|-----------------|
|
|
409
|
+
| Existing `articles.create()` | All | Public/Beta | ✅ No change |
|
|
410
|
+
| Existing `articles.get()` | All | Public/Beta | ✅ No change |
|
|
411
|
+
| `ArtifactsService` | 2.7.0+ | Public/Beta | ➕ New |
|
|
412
|
+
| `create_with_content()` | 2.8.0+ | Public/Beta | ➕ New |
|
|
413
|
+
| `get_with_content()` | 2.8.0+ | Public/Beta | ➕ New |
|
|
414
|
+
| `update_content()` | 2.8.0+ | Public/Beta | ➕ New |
|
|
415
|
+
| MCP `content` parameter | 2.8.0+ | Public/Beta | ⚠️ Signature change |
|
|
416
|
+
|
|
417
|
+
**Upgrade Path:**
|
|
418
|
+
- SDK 2.6.x → 2.7.x: Add artifacts service (no breaking changes)
|
|
419
|
+
- SDK 2.7.x → 2.8.x: Add unified methods (no breaking changes)
|
|
420
|
+
- MCP tools 2.8.x: Update to use `content` parameter (may affect existing AI workflows)
|
|
421
|
+
|
|
422
|
+
## Security Considerations
|
|
423
|
+
|
|
424
|
+
### Input Validation
|
|
425
|
+
- **Content Size Limits**: Enforce max article size (configurable, default 10MB)
|
|
426
|
+
- **Content Type Validation**: Whitelist allowed MIME types
|
|
427
|
+
- **HTML Sanitization**: Optional HTML sanitization for user-generated content
|
|
428
|
+
- **Injection Prevention**: Validate artifact IDs match expected format
|
|
429
|
+
|
|
430
|
+
### Access Control
|
|
431
|
+
- Respect existing DevRev RBAC for articles and artifacts
|
|
432
|
+
- Validate ownership before allowing content updates
|
|
433
|
+
- Audit logging for all content operations
|
|
434
|
+
|
|
435
|
+
### Data Protection
|
|
436
|
+
- Content encrypted in transit (HTTPS to S3)
|
|
437
|
+
- S3 URLs are signed and time-limited (15-minute expiry)
|
|
438
|
+
- No credentials in error messages or logs
|
|
439
|
+
- Sensitive content redaction in debug logs
|
|
440
|
+
|
|
441
|
+
### Artifact Cleanup
|
|
442
|
+
- Orphaned artifact detection and cleanup
|
|
443
|
+
- Automatic deletion of artifacts when parent article deleted
|
|
444
|
+
- Version retention policies (keep last N versions)
|
|
445
|
+
|
|
446
|
+
## Testing Strategy
|
|
447
|
+
|
|
448
|
+
### Unit Tests
|
|
449
|
+
- [ ] Each artifact method (prepare, upload, get, locate, download)
|
|
450
|
+
- [ ] Each unified article method (create_with_content, get_with_content, update_content)
|
|
451
|
+
- [ ] Model validation (all request/response models)
|
|
452
|
+
- [ ] Error handling for each failure scenario
|
|
453
|
+
- [ ] Async versions of all methods
|
|
454
|
+
|
|
455
|
+
### Integration Tests
|
|
456
|
+
- [ ] Full article+artifact lifecycle (create → read → update → delete)
|
|
457
|
+
- [ ] Multi-version artifact updates
|
|
458
|
+
- [ ] Large content handling (>1MB)
|
|
459
|
+
- [ ] Network failure recovery
|
|
460
|
+
- [ ] Concurrent operations (race conditions)
|
|
461
|
+
|
|
462
|
+
### Performance Tests
|
|
463
|
+
- [ ] Benchmark create_with_content vs manual workflow
|
|
464
|
+
- [ ] Large content upload performance (5MB, 10MB)
|
|
465
|
+
- [ ] Bulk operation performance
|
|
466
|
+
- [ ] Cache effectiveness
|
|
467
|
+
|
|
468
|
+
### Backward Compatibility Tests
|
|
469
|
+
- [ ] All existing SDK tests pass without modification
|
|
470
|
+
- [ ] Existing code examples still work
|
|
471
|
+
- [ ] API contract unchanged for existing methods
|
|
472
|
+
- [ ] MCP tools with old signatures still function (deprecation warnings)
|
|
473
|
+
|
|
474
|
+
### MCP Integration Tests
|
|
475
|
+
- [ ] AI agent workflows with new tools
|
|
476
|
+
- [ ] Content vs description parameter handling
|
|
477
|
+
- [ ] Error messages clear for AI interpretation
|
|
478
|
+
- [ ] Tool schema validation
|
|
479
|
+
|
|
480
|
+
## Breaking Changes Assessment
|
|
481
|
+
|
|
482
|
+
**No breaking changes** - all existing methods remain unchanged:
|
|
483
|
+
- ✅ Existing `articles.create(request)` still works
|
|
484
|
+
- ✅ Existing `articles.get(request)` still works
|
|
485
|
+
- ✅ New methods are additions, not replacements
|
|
486
|
+
- ✅ MCP tools will have enhanced signatures but maintain compatibility where possible
|
|
487
|
+
|
|
488
|
+
## Success Criteria
|
|
489
|
+
|
|
490
|
+
- [ ] SDK provides unified `create_with_content`, `get_with_content`, `update_content` methods
|
|
491
|
+
- [ ] MCP tools use `content` parameter for article body (not `description`)
|
|
492
|
+
- [ ] All existing tests pass
|
|
493
|
+
- [ ] New tests cover unified methods and artifact operations
|
|
494
|
+
- [ ] Documentation clearly explains content vs description
|
|
495
|
+
- [ ] Migration guide helps users adopt new methods
|
|
496
|
+
- [ ] No breaking changes to existing API
|
|
497
|
+
|
|
498
|
+
## Related Files
|
|
499
|
+
|
|
500
|
+
- `src/devrev/models/artifacts.py` - Artifact models ✅
|
|
501
|
+
- `src/devrev/services/artifacts.py` - Artifacts service ✅
|
|
502
|
+
- `src/devrev/services/articles.py` - Articles service (needs unified methods)
|
|
503
|
+
- `src/devrev/models/articles.py` - Article models (added ArticleWithContent ✅)
|
|
504
|
+
- `src/devrev/client.py` - Client integration ✅
|
|
505
|
+
- `src/devrev_mcp/tools/articles.py` - MCP tools (needs updates)
|
|
506
|
+
- `tests/unit/test_artifacts.py` - Artifact tests (to create)
|
|
507
|
+
- `tests/unit/test_articles_unified.py` - Unified method tests (to create)
|
|
508
|
+
- `docs/api/services/articles.md` - Documentation (needs updates)
|
|
509
|
+
|
|
510
|
+
## Rollout Strategy
|
|
511
|
+
|
|
512
|
+
### Week 1: Foundation (Phase 1)
|
|
513
|
+
- ✅ Create and test `ArtifactsService`
|
|
514
|
+
- ✅ Add `ArticleWithContent` model
|
|
515
|
+
- ✅ Integration with client
|
|
516
|
+
- [ ] Complete unit tests for artifacts
|
|
517
|
+
- Release as SDK 2.7.0 (non-breaking, adds artifact support)
|
|
518
|
+
|
|
519
|
+
### Week 2: Unified Methods (Phase 2)
|
|
520
|
+
- [ ] Implement `create_with_content()`
|
|
521
|
+
- [ ] Implement `get_with_content()`
|
|
522
|
+
- [ ] Implement `update_content()`
|
|
523
|
+
- [ ] Complete unit and integration tests
|
|
524
|
+
- Release as SDK 2.8.0-beta1 (non-breaking, adds unified methods)
|
|
525
|
+
|
|
526
|
+
### Week 3: MCP Tools + Documentation (Phases 3-4)
|
|
527
|
+
- [ ] Update MCP tools with `content` parameter
|
|
528
|
+
- [ ] Add deprecation warnings for old usage
|
|
529
|
+
- [ ] Write migration guide
|
|
530
|
+
- [ ] Update all documentation
|
|
531
|
+
- Release as SDK 2.8.0-beta2
|
|
532
|
+
|
|
533
|
+
### Week 4: Final Testing + Release
|
|
534
|
+
- [ ] Community beta testing
|
|
535
|
+
- [ ] Performance benchmarking
|
|
536
|
+
- [ ] Address feedback
|
|
537
|
+
- [ ] Final documentation review
|
|
538
|
+
- Release as SDK 2.8.0 (stable)
|
|
539
|
+
|
|
540
|
+
## FAQ
|
|
541
|
+
|
|
542
|
+
**Q: Will this break my existing code?**
|
|
543
|
+
A: No. All existing methods remain unchanged. New unified methods are additions.
|
|
544
|
+
|
|
545
|
+
**Q: Can I still use the low-level artifact methods?**
|
|
546
|
+
A: Yes. Both `client.artifacts` and unified methods will be available.
|
|
547
|
+
|
|
548
|
+
**Q: What happens if I call `create_with_content()` and it fails?**
|
|
549
|
+
A: Automatic rollback ensures no orphaned artifacts. You'll get a clear error message.
|
|
550
|
+
|
|
551
|
+
**Q: How do I migrate from `description` to `content` in MCP tools?**
|
|
552
|
+
A: The migration guide provides before/after examples. Old usage will show deprecation warnings.
|
|
553
|
+
|
|
554
|
+
**Q: What content formats are supported?**
|
|
555
|
+
A: Any format - text/plain, text/html, text/markdown. Specify via `content_format` parameter.
|
|
556
|
+
|
|
557
|
+
**Q: Is there a size limit for article content?**
|
|
558
|
+
A: Default limit is 10MB. Configurable via SDK settings.
|
|
559
|
+
|
|
560
|
+
**Q: How do I handle large articles (>10MB)?**
|
|
561
|
+
A: Use the low-level `artifacts.prepare()` + `upload()` for more control. Streaming support coming in future release.
|
|
562
|
+
|
|
563
|
+
**Q: Can I version article content?**
|
|
564
|
+
A: Yes. The `update_content()` method creates a new artifact version automatically.
|
|
565
|
+
|
|
566
|
+
**Q: What if I need to attach multiple files to an article?**
|
|
567
|
+
A: Use the `resource.attachments` field with multiple artifact IDs. Unified helper method for attachments planned for future release.
|
|
568
|
+
|
|
569
|
+
**Q: How does this affect the DevRev MCP server?**
|
|
570
|
+
A: MCP tools will use the new unified methods, making article operations simpler for AI agents.
|
|
571
|
+
|
|
572
|
+
## Progress Tracking
|
|
573
|
+
|
|
574
|
+
**Overall: 90% Complete** ⬆️
|
|
575
|
+
|
|
576
|
+
✅ Phase 1: Artifact Service Foundation (100%)
|
|
577
|
+
✅ Phase 2: Unified Article Methods (100%) 🎉
|
|
578
|
+
✅ Phase 3: MCP Tool Updates (100%) 🎉
|
|
579
|
+
✅ Phase 4: Documentation (100%) 🎉
|
|
580
|
+
⏳ Phase 5: Testing (0%)
|
|
581
|
+
|
|
582
|
+
**Documentation Complete!** All SDK docs, MCP docs, README, and changelog have been updated with unified method examples.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: devrev-Python-SDK
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.8.0
|
|
4
4
|
Summary: A modern, type-safe Python SDK for the DevRev API
|
|
5
5
|
Project-URL: Homepage, https://github.com/mgmonteleone/py-dev-rev
|
|
6
6
|
Project-URL: Documentation, https://github.com/mgmonteleone/py-dev-rev
|
|
@@ -505,24 +505,40 @@ export_result = client.works.export(
|
|
|
505
505
|
### Articles and Knowledge Base
|
|
506
506
|
|
|
507
507
|
```python
|
|
508
|
-
|
|
509
|
-
|
|
508
|
+
from devrev.models.articles import ArticleStatus
|
|
509
|
+
|
|
510
|
+
# Create an article with content (recommended - automatic artifact handling)
|
|
511
|
+
article = client.articles.create_with_content(
|
|
510
512
|
title="Getting Started Guide",
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
description="
|
|
513
|
+
content="<h1>Welcome</h1><p>This guide will help you get started...</p>",
|
|
514
|
+
owned_by=["don:identity:dvrv-us-1:devo/1:devu/1"],
|
|
515
|
+
description="Quick start guide for new users", # Optional metadata
|
|
516
|
+
status=ArticleStatus.PUBLISHED,
|
|
514
517
|
)
|
|
515
518
|
|
|
516
|
-
#
|
|
517
|
-
|
|
518
|
-
|
|
519
|
+
# Get article with content
|
|
520
|
+
article_with_content = client.articles.get_with_content(article.id)
|
|
521
|
+
print(f"Title: {article_with_content.article.title}")
|
|
522
|
+
print(f"Content: {article_with_content.content[:100]}...")
|
|
523
|
+
|
|
524
|
+
# Update article content
|
|
525
|
+
client.articles.update_content(
|
|
526
|
+
id=article.id,
|
|
527
|
+
content="<h1>Updated Welcome</h1><p>Updated guide...</p>",
|
|
519
528
|
)
|
|
520
529
|
|
|
521
|
-
# Update
|
|
522
|
-
client.articles.
|
|
530
|
+
# Update both metadata and content
|
|
531
|
+
client.articles.update_with_content(
|
|
523
532
|
id=article.id,
|
|
524
|
-
|
|
533
|
+
title="Updated Getting Started Guide",
|
|
534
|
+
content="<h1>New Content</h1>",
|
|
535
|
+
status=ArticleStatus.ARCHIVED,
|
|
525
536
|
)
|
|
537
|
+
|
|
538
|
+
# List published articles (metadata only)
|
|
539
|
+
published = client.articles.list(limit=20)
|
|
540
|
+
for article in published:
|
|
541
|
+
print(f"{article.title} - {article.status}")
|
|
526
542
|
```
|
|
527
543
|
|
|
528
544
|
### Webhooks
|
|
@@ -433,24 +433,40 @@ export_result = client.works.export(
|
|
|
433
433
|
### Articles and Knowledge Base
|
|
434
434
|
|
|
435
435
|
```python
|
|
436
|
-
|
|
437
|
-
|
|
436
|
+
from devrev.models.articles import ArticleStatus
|
|
437
|
+
|
|
438
|
+
# Create an article with content (recommended - automatic artifact handling)
|
|
439
|
+
article = client.articles.create_with_content(
|
|
438
440
|
title="Getting Started Guide",
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
description="
|
|
441
|
+
content="<h1>Welcome</h1><p>This guide will help you get started...</p>",
|
|
442
|
+
owned_by=["don:identity:dvrv-us-1:devo/1:devu/1"],
|
|
443
|
+
description="Quick start guide for new users", # Optional metadata
|
|
444
|
+
status=ArticleStatus.PUBLISHED,
|
|
442
445
|
)
|
|
443
446
|
|
|
444
|
-
#
|
|
445
|
-
|
|
446
|
-
|
|
447
|
+
# Get article with content
|
|
448
|
+
article_with_content = client.articles.get_with_content(article.id)
|
|
449
|
+
print(f"Title: {article_with_content.article.title}")
|
|
450
|
+
print(f"Content: {article_with_content.content[:100]}...")
|
|
451
|
+
|
|
452
|
+
# Update article content
|
|
453
|
+
client.articles.update_content(
|
|
454
|
+
id=article.id,
|
|
455
|
+
content="<h1>Updated Welcome</h1><p>Updated guide...</p>",
|
|
447
456
|
)
|
|
448
457
|
|
|
449
|
-
# Update
|
|
450
|
-
client.articles.
|
|
458
|
+
# Update both metadata and content
|
|
459
|
+
client.articles.update_with_content(
|
|
451
460
|
id=article.id,
|
|
452
|
-
|
|
461
|
+
title="Updated Getting Started Guide",
|
|
462
|
+
content="<h1>New Content</h1>",
|
|
463
|
+
status=ArticleStatus.ARCHIVED,
|
|
453
464
|
)
|
|
465
|
+
|
|
466
|
+
# List published articles (metadata only)
|
|
467
|
+
published = client.articles.list(limit=20)
|
|
468
|
+
for article in published:
|
|
469
|
+
print(f"{article.title} - {article.status}")
|
|
454
470
|
```
|
|
455
471
|
|
|
456
472
|
### Webhooks
|