devrev-Python-SDK 2.8.1__tar.gz → 2.10.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.1 → devrev_python_sdk-2.10.0}/PKG-INFO +18 -1
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/README.md +17 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/services/articles.md +19 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/changelog.md +15 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/mcp/tools-reference.md +3 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/pyproject.toml +1 -1
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/articles.py +71 -2
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/tools/articles.py +43 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/mcp/conftest.py +2 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/mcp/test_tools_articles.py +200 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/test_articles_unified.py +326 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.augment/agents/bug-fixer.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.augment/agents/builder.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.augment/agents/documentation.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.augment/agents/foreman.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.augment/agents/pr-review-boss.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.augment/agents/release-manager.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.augment/agents/simplifier.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.augment/agents/tester.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.augment/commands/foreman-work.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.augment/commands/release-prepare.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.augment/commands/review-start.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.augment/commands/simplify-code.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.augment/rules/code-quality.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.augment/rules/data-modeling.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.augment/rules/devrev-sdk.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.augment/rules/git-workflow.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.augment/rules/pull-requests.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.augment/rules/python-development.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.augment/rules/security.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.augment/rules/testing.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.dockerignore +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.env.sample +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.github/ISSUE_TEMPLATE/article-artifact-simplification.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.github/ISSUE_TEMPLATE/question.yml +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.github/dependabot.yml +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.github/pull_request_template.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.github/workflows/api-check.yml +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.github/workflows/ci.yml +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.github/workflows/claude-code-review.yml +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.github/workflows/claude.yml +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.github/workflows/deploy.yml +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.github/workflows/docs.yml +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.github/workflows/integration-tests.yml +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.github/workflows/release.yml +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.github/workflows/sync-openapi.yml +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.gitignore +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/.pre-commit-config.yaml +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/CLAUDE.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/CODE_OF_CONDUCT.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/CONTRIBUTING.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/DEPRECATIONS.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/Dockerfile +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/KNOWN_ISSUES.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/OPENAPI_SPEC_DISCREPANCIES.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/SECURITY.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/augment-mcp-config-remote.json +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/augment-mcp-config.json +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/augment-settings.json +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/benchmarks/README.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/benchmarks/bench_http_client.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/benchmarks/bench_models.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/benchmarks/bench_pagination.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/benchmarks/conftest.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/context7.json +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/deploy/README.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/deploy/audit-logging-setup.sh +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/deploy/cloudbuild.yaml +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/deploy/monitoring/README.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/deploy/monitoring/alert-policies.yaml +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/deploy/monitoring/dashboard.json +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/deploy/monitoring/validate-config.sh +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/deploy/service.yaml +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docker-compose.yml +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/beta/brands.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/beta/engagements.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/beta/incidents.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/beta/index.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/beta/question-answers.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/beta/recommendations.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/beta/search.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/beta/uoms.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/beta-api-differences.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/client.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/config.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/exceptions.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/index.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/models/accounts.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/models/base.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/models/index.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/models/users.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/models/works.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/services/accounts.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/services/code-changes.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/services/conversations.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/services/dev-users.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/services/groups.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/services/index.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/services/links.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/services/parts.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/services/rev-users.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/services/slas.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/services/tags.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/services/timeline-entries.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/services/webhooks.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/api/services/works.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/examples/advanced.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/examples/basic.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/examples/beta-features.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/examples/index.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/examples/integrations.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/getting-started/authentication.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/getting-started/index.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/getting-started/installation.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/getting-started/quickstart.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/guides/beta-api.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/guides/compatibility.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/guides/configuration.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/guides/error-handling.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/guides/github-actions-setup.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/guides/index.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/guides/logging.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/guides/pagination.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/guides/sync-vs-async.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/guides/testing.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/guides/version-support.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/guides/write-integration-testing-strategy.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/hooks/copy_llms.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/index.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/mcp/deployment.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/mcp/index.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/mcp/quickstart.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/docs/stylesheets/extra.css +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/examples/README.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/examples/basic/README.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/examples/basic/async_example.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/examples/basic/create_work.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/examples/basic/error_handling.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/examples/basic/list_accounts.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/examples/basic/pagination.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/examples/basic/search_users.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/examples/integrations/cloud_functions/README.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/examples/integrations/cloud_functions/main.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/examples/integrations/cloud_functions/requirements.txt +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/examples/integrations/fastapi/README.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/examples/integrations/fastapi/main.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/examples/integrations/fastapi/requirements.txt +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/examples/integrations/flask/README.md +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/examples/integrations/flask/app.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/examples/integrations/flask/requirements.txt +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/llms-ctx-full.txt +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/llms-ctx.txt +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/llms-mcp.txt +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/llms.txt +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/mkdocs.yml +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/openapi-beta.yaml +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/openapi-public.yaml +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/openapi-spec-corrections.yaml +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/scripts/build_ai_docs.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/scripts/setup-github-secrets.sh +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/__init__.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/client.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/config.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/exceptions.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/__init__.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/accounts.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/articles.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/artifacts.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/base.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/brands.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/code_changes.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/conversations.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/dev_users.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/engagements.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/groups.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/incidents.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/links.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/notifications.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/parts.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/preferences.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/question_answers.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/recommendations.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/rev_users.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/search.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/slas.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/sync.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/tags.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/tasks.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/timeline_entries.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/timeline_events.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/track_events.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/uoms.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/webhooks.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/widgets.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/models/works.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/py.typed +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/__init__.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/accounts.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/artifacts.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/base.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/brands.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/code_changes.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/conversations.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/dev_users.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/engagements.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/groups.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/incidents.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/links.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/notifications.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/parts.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/preferences.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/question_answers.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/recommendations.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/rev_users.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/search.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/slas.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/tags.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/timeline_entries.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/track_events.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/uoms.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/webhooks.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/services/works.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/utils/__init__.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/utils/content_converter.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/utils/deprecation.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/utils/http.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/utils/logging.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev/utils/pagination.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/__init__.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/__main__.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/config.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/middleware/__init__.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/middleware/audit.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/middleware/auth.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/middleware/health.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/middleware/rate_limit.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/prompts/__init__.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/prompts/escalation.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/prompts/investigate.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/prompts/response.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/prompts/summarize.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/prompts/triage.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/resources/__init__.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/resources/account.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/resources/article.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/resources/conversation.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/resources/part.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/resources/server_info.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/resources/ticket.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/resources/user.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/server.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/tools/__init__.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/tools/accounts.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/tools/conversations.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/tools/engagements.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/tools/groups.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/tools/incidents.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/tools/links.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/tools/parts.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/tools/recommendations.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/tools/search.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/tools/server_info.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/tools/slas.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/tools/tags.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/tools/timeline.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/tools/users.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/tools/works.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/utils/__init__.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/utils/errors.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/utils/formatting.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/src/devrev_mcp/utils/pagination.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/__init__.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/conftest.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/integration/__init__.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/integration/conftest.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/integration/test_accounts_e2e.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/integration/test_all_readonly_endpoints.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/integration/test_articles_lifecycle.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/integration/test_backwards_compatibility.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/integration/test_contacts_e2e.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/integration/test_core_services_phase1.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/integration/test_extended_services_phase2.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/integration/test_get_endpoints.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/integration/test_issues_e2e.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/integration/test_kb_articles_e2e.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/integration/test_mcp_articles.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/integration/test_ping.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/integration/test_question_answers_e2e.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/integration/test_readonly_endpoints.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/integration/test_specialized_services_phase3.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/integration/test_tickets_e2e.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/integration/test_write_operations.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/integration/utils/__init__.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/integration/utils/cleanup.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/integration/utils/constants.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/integration/utils/data_manager.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/performance/__init__.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/performance/test_articles_performance.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/__init__.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/mcp/__init__.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/mcp/test_audit.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/mcp/test_config.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/mcp/test_phase4_transport.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/mcp/test_prompts.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/mcp/test_resources.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/mcp/test_server_info.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/mcp/test_tools_accounts.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/mcp/test_tools_conversations.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/mcp/test_tools_engagements.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/mcp/test_tools_groups.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/mcp/test_tools_incidents.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/mcp/test_tools_links.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/mcp/test_tools_parts.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/mcp/test_tools_recommendations.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/mcp/test_tools_search.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/mcp/test_tools_slas.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/mcp/test_tools_tags.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/mcp/test_tools_timeline.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/mcp/test_tools_users.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/mcp/test_tools_works.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/mcp/test_utils.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/models/__init__.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/models/test_user_state_regression.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/services/__init__.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/services/conftest.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/services/test_articles.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/services/test_async_services.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/services/test_brands.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/services/test_code_changes.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/services/test_conversations.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/services/test_engagements.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/services/test_groups.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/services/test_incidents.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/services/test_links.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/services/test_notifications.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/services/test_parts.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/services/test_preferences.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/services/test_question_answers.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/services/test_recommendations.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/services/test_search.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/services/test_slas.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/services/test_tags.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/services/test_timeline_entries.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/services/test_track_events.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/services/test_uoms.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/services/test_webhooks.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/services/test_works.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/test_artifacts.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/test_backward_compatibility.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/test_base_service.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/test_client.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/test_config.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/test_content_converter.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/test_deprecation.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/test_error_handling.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/test_exceptions.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/test_http.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/test_logging.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/tests/unit/test_pagination.py +0 -0
- {devrev_python_sdk-2.8.1 → devrev_python_sdk-2.10.0}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: devrev-Python-SDK
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.10.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
|
|
@@ -517,6 +517,7 @@ article = client.articles.create_with_content(
|
|
|
517
517
|
owned_by=["don:identity:dvrv-us-1:devo/1:devu/1"],
|
|
518
518
|
description="Quick start guide for new users", # Optional metadata
|
|
519
519
|
status=ArticleStatus.PUBLISHED,
|
|
520
|
+
applies_to_parts=["don:core:dvrv-us-1:devo/1:part/123"], # Optional: associate with parts
|
|
520
521
|
)
|
|
521
522
|
|
|
522
523
|
# Get article with content
|
|
@@ -538,6 +539,22 @@ client.articles.update_with_content(
|
|
|
538
539
|
status=ArticleStatus.ARCHIVED,
|
|
539
540
|
)
|
|
540
541
|
|
|
542
|
+
# Update with part associations
|
|
543
|
+
client.articles.update_with_content(
|
|
544
|
+
id=article.id,
|
|
545
|
+
applies_to_parts=["don:core:dvrv-us-1:devo/1:part/123", "don:core:dvrv-us-1:devo/1:part/456"],
|
|
546
|
+
)
|
|
547
|
+
|
|
548
|
+
# Update access level and tags
|
|
549
|
+
from devrev.models.articles import ArticleAccessLevel
|
|
550
|
+
from devrev.models.base import SetTagWithValue
|
|
551
|
+
|
|
552
|
+
client.articles.update_with_content(
|
|
553
|
+
id=article.id,
|
|
554
|
+
access_level=ArticleAccessLevel.INTERNAL, # internal, external, private, public
|
|
555
|
+
tags=[SetTagWithValue(id="don:core:dvrv-us-1:devo/1:tag/123")],
|
|
556
|
+
)
|
|
557
|
+
|
|
541
558
|
# List published articles (metadata only)
|
|
542
559
|
published = client.articles.list(limit=20)
|
|
543
560
|
for article in published:
|
|
@@ -442,6 +442,7 @@ article = client.articles.create_with_content(
|
|
|
442
442
|
owned_by=["don:identity:dvrv-us-1:devo/1:devu/1"],
|
|
443
443
|
description="Quick start guide for new users", # Optional metadata
|
|
444
444
|
status=ArticleStatus.PUBLISHED,
|
|
445
|
+
applies_to_parts=["don:core:dvrv-us-1:devo/1:part/123"], # Optional: associate with parts
|
|
445
446
|
)
|
|
446
447
|
|
|
447
448
|
# Get article with content
|
|
@@ -463,6 +464,22 @@ client.articles.update_with_content(
|
|
|
463
464
|
status=ArticleStatus.ARCHIVED,
|
|
464
465
|
)
|
|
465
466
|
|
|
467
|
+
# Update with part associations
|
|
468
|
+
client.articles.update_with_content(
|
|
469
|
+
id=article.id,
|
|
470
|
+
applies_to_parts=["don:core:dvrv-us-1:devo/1:part/123", "don:core:dvrv-us-1:devo/1:part/456"],
|
|
471
|
+
)
|
|
472
|
+
|
|
473
|
+
# Update access level and tags
|
|
474
|
+
from devrev.models.articles import ArticleAccessLevel
|
|
475
|
+
from devrev.models.base import SetTagWithValue
|
|
476
|
+
|
|
477
|
+
client.articles.update_with_content(
|
|
478
|
+
id=article.id,
|
|
479
|
+
access_level=ArticleAccessLevel.INTERNAL, # internal, external, private, public
|
|
480
|
+
tags=[SetTagWithValue(id="don:core:dvrv-us-1:devo/1:tag/123")],
|
|
481
|
+
)
|
|
482
|
+
|
|
466
483
|
# List published articles (metadata only)
|
|
467
484
|
published = client.articles.list(limit=20)
|
|
468
485
|
for article in published:
|
|
@@ -93,6 +93,9 @@ article = client.articles.create_with_content(
|
|
|
93
93
|
description="Short summary for search/listing", # Optional metadata
|
|
94
94
|
status=ArticleStatus.PUBLISHED, # Optional: draft, published, archived
|
|
95
95
|
content_format="text/html", # Optional: default is text/html
|
|
96
|
+
applies_to_parts=["don:core:dvrv-us-1:devo/1:part/123"], # Optional: associate with parts
|
|
97
|
+
scope=1, # Optional: 1=internal, 2=external (API default is external)
|
|
98
|
+
tags=[SetTagWithValue(id="don:core:dvrv-us-1:devo/1:tag/123")], # Optional: apply tags
|
|
96
99
|
)
|
|
97
100
|
print(f"Created article with content: {article.id}")
|
|
98
101
|
```
|
|
@@ -181,6 +184,22 @@ updated_article = client.articles.update_with_content(
|
|
|
181
184
|
id="don:core:dvrv-us-1:devo/1:article/123",
|
|
182
185
|
content="<h1>New Content</h1>",
|
|
183
186
|
)
|
|
187
|
+
|
|
188
|
+
# Update with part associations
|
|
189
|
+
updated_article = client.articles.update_with_content(
|
|
190
|
+
id="don:core:dvrv-us-1:devo/1:article/123",
|
|
191
|
+
applies_to_parts=["don:core:dvrv-us-1:devo/1:part/123", "don:core:dvrv-us-1:devo/1:part/456"],
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
# Update access level and tags
|
|
195
|
+
from devrev.models.articles import ArticleAccessLevel
|
|
196
|
+
from devrev.models.base import SetTagWithValue
|
|
197
|
+
|
|
198
|
+
updated_article = client.articles.update_with_content(
|
|
199
|
+
id="don:core:dvrv-us-1:devo/1:article/123",
|
|
200
|
+
access_level=ArticleAccessLevel.INTERNAL, # Change to internal visibility
|
|
201
|
+
tags=[SetTagWithValue(id="don:core:dvrv-us-1:devo/1:tag/123")], # Apply tags
|
|
202
|
+
)
|
|
184
203
|
```
|
|
185
204
|
|
|
186
205
|
### Async Usage
|
|
@@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.10.0] - 2026-03-09
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Article Scope and Tags** (#173) — Added visibility and tagging parameters to MCP article tools:
|
|
15
|
+
- `devrev_articles_create`: Added `scope` (1=internal, 2=external) and `tags` (list of tag IDs) parameters
|
|
16
|
+
- `devrev_articles_update`: Added `access_level` (internal, external, private, public) and `tags` parameters
|
|
17
|
+
- SDK `update_with_content`: Added `access_level` and `tags` parameters for both sync and async methods
|
|
18
|
+
|
|
19
|
+
## [2.9.0] - 2026-03-09
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- **Article Part Association** (#171) — Added `applies_to_parts` parameter to MCP `articles_create` and `articles_update` tools, and SDK `update_with_content` method for native article-to-part association
|
|
24
|
+
|
|
10
25
|
## [2.8.1] - 2026-03-06
|
|
11
26
|
|
|
12
27
|
### Fixed
|
|
@@ -56,6 +56,9 @@ Tools are the primary way AI assistants interact with DevRev. Each tool maps to
|
|
|
56
56
|
- **Unified Content Management**: Create and update articles with automatic artifact handling
|
|
57
57
|
- **Optional Content Loading**: Use `include_content=true` in `get` to fetch article body
|
|
58
58
|
- **Clear Parameters**: `content` for article body, `description` for metadata summary
|
|
59
|
+
- **Part Association**: Use `applies_to_parts` to natively associate articles with products, capabilities, features, or enhancements
|
|
60
|
+
- **Visibility Control**: Use `scope` (1=internal, 2=external) on create or `access_level` (internal, external, private, public) on update
|
|
61
|
+
- **Tagging**: Apply tags using the `tags` parameter (list of tag IDs)
|
|
59
62
|
|
|
60
63
|
### Conversations
|
|
61
64
|
|
|
@@ -9,6 +9,7 @@ from collections.abc import Sequence
|
|
|
9
9
|
from devrev.exceptions import DevRevError
|
|
10
10
|
from devrev.models.articles import (
|
|
11
11
|
Article,
|
|
12
|
+
ArticleAccessLevel,
|
|
12
13
|
ArticlesCountRequest,
|
|
13
14
|
ArticlesCountResponse,
|
|
14
15
|
ArticlesCreateRequest,
|
|
@@ -21,6 +22,8 @@ from devrev.models.articles import (
|
|
|
21
22
|
ArticlesListResponse,
|
|
22
23
|
ArticleStatus,
|
|
23
24
|
ArticlesUpdateRequest,
|
|
25
|
+
ArticlesUpdateRequestAppliesToParts,
|
|
26
|
+
ArticlesUpdateRequestTags,
|
|
24
27
|
ArticlesUpdateResponse,
|
|
25
28
|
ArticleType,
|
|
26
29
|
ArticleWithContent,
|
|
@@ -437,6 +440,9 @@ class ArticlesService(BaseService):
|
|
|
437
440
|
content: str | None = None,
|
|
438
441
|
description: str | None = None,
|
|
439
442
|
status: ArticleStatus | None = None,
|
|
443
|
+
applies_to_parts: builtins.list[str] | None = None,
|
|
444
|
+
access_level: ArticleAccessLevel | None = None,
|
|
445
|
+
tags: builtins.list[SetTagWithValue] | None = None,
|
|
440
446
|
) -> Article:
|
|
441
447
|
"""Update article metadata and/or content.
|
|
442
448
|
|
|
@@ -451,6 +457,9 @@ class ArticlesService(BaseService):
|
|
|
451
457
|
content: Optional new article body content
|
|
452
458
|
description: Optional new metadata description
|
|
453
459
|
status: Optional new status
|
|
460
|
+
applies_to_parts: Optional list of part IDs to associate with
|
|
461
|
+
access_level: Optional access level (internal, external, private, public)
|
|
462
|
+
tags: Optional list of tags to apply (list of SetTagWithValue objects)
|
|
454
463
|
|
|
455
464
|
Returns:
|
|
456
465
|
Updated article
|
|
@@ -478,6 +487,18 @@ class ArticlesService(BaseService):
|
|
|
478
487
|
... title="New Title",
|
|
479
488
|
... content="<html>New content...</html>"
|
|
480
489
|
... )
|
|
490
|
+
>>>
|
|
491
|
+
>>> # Update applies_to_parts
|
|
492
|
+
>>> article = client.articles.update_with_content(
|
|
493
|
+
... "ART-123",
|
|
494
|
+
... applies_to_parts=["don:core:...:capability/6"]
|
|
495
|
+
... )
|
|
496
|
+
>>>
|
|
497
|
+
>>> # Update access level to internal
|
|
498
|
+
>>> article = client.articles.update_with_content(
|
|
499
|
+
... "ART-123",
|
|
500
|
+
... access_level=ArticleAccessLevel.INTERNAL
|
|
501
|
+
... )
|
|
481
502
|
"""
|
|
482
503
|
if not self._parent_client:
|
|
483
504
|
raise DevRevError(
|
|
@@ -489,13 +510,34 @@ class ArticlesService(BaseService):
|
|
|
489
510
|
if content is not None:
|
|
490
511
|
self.update_content(id, content)
|
|
491
512
|
|
|
513
|
+
# Build applies_to_parts wrapper if provided
|
|
514
|
+
applies_to_parts_req = None
|
|
515
|
+
if applies_to_parts is not None:
|
|
516
|
+
applies_to_parts_req = ArticlesUpdateRequestAppliesToParts(set=applies_to_parts)
|
|
517
|
+
|
|
518
|
+
# Build tags wrapper if provided
|
|
519
|
+
tags_req = None
|
|
520
|
+
if tags is not None:
|
|
521
|
+
tags_req = ArticlesUpdateRequestTags(set=tags)
|
|
522
|
+
|
|
492
523
|
# Update metadata if any metadata fields provided
|
|
493
|
-
|
|
524
|
+
has_metadata = (
|
|
525
|
+
title is not None
|
|
526
|
+
or description is not None
|
|
527
|
+
or status is not None
|
|
528
|
+
or applies_to_parts is not None
|
|
529
|
+
or access_level is not None
|
|
530
|
+
or tags is not None
|
|
531
|
+
)
|
|
532
|
+
if has_metadata:
|
|
494
533
|
update_req = ArticlesUpdateRequest(
|
|
495
534
|
id=id,
|
|
496
535
|
title=title,
|
|
497
536
|
description=description,
|
|
498
537
|
status=status,
|
|
538
|
+
applies_to_parts=applies_to_parts_req,
|
|
539
|
+
access_level=access_level,
|
|
540
|
+
tags=tags_req,
|
|
499
541
|
)
|
|
500
542
|
return self.update(update_req)
|
|
501
543
|
|
|
@@ -822,6 +864,9 @@ class AsyncArticlesService(AsyncBaseService):
|
|
|
822
864
|
content: str | None = None,
|
|
823
865
|
description: str | None = None,
|
|
824
866
|
status: ArticleStatus | None = None,
|
|
867
|
+
applies_to_parts: builtins.list[str] | None = None,
|
|
868
|
+
access_level: ArticleAccessLevel | None = None,
|
|
869
|
+
tags: builtins.list[SetTagWithValue] | None = None,
|
|
825
870
|
) -> Article:
|
|
826
871
|
"""Update article metadata and/or content (async).
|
|
827
872
|
|
|
@@ -836,6 +881,9 @@ class AsyncArticlesService(AsyncBaseService):
|
|
|
836
881
|
content: Optional new article body content
|
|
837
882
|
description: Optional new metadata description
|
|
838
883
|
status: Optional new status
|
|
884
|
+
applies_to_parts: Optional list of part IDs to associate with
|
|
885
|
+
access_level: Optional access level (internal, external, private, public)
|
|
886
|
+
tags: Optional list of tags to apply (list of SetTagWithValue objects)
|
|
839
887
|
|
|
840
888
|
Returns:
|
|
841
889
|
Updated article
|
|
@@ -853,13 +901,34 @@ class AsyncArticlesService(AsyncBaseService):
|
|
|
853
901
|
if content is not None:
|
|
854
902
|
await self.update_content(id, content)
|
|
855
903
|
|
|
904
|
+
# Build applies_to_parts wrapper if provided
|
|
905
|
+
applies_to_parts_req = None
|
|
906
|
+
if applies_to_parts is not None:
|
|
907
|
+
applies_to_parts_req = ArticlesUpdateRequestAppliesToParts(set=applies_to_parts)
|
|
908
|
+
|
|
909
|
+
# Build tags wrapper if provided
|
|
910
|
+
tags_req = None
|
|
911
|
+
if tags is not None:
|
|
912
|
+
tags_req = ArticlesUpdateRequestTags(set=tags)
|
|
913
|
+
|
|
856
914
|
# Update metadata if any metadata fields provided
|
|
857
|
-
|
|
915
|
+
has_metadata = (
|
|
916
|
+
title is not None
|
|
917
|
+
or description is not None
|
|
918
|
+
or status is not None
|
|
919
|
+
or applies_to_parts is not None
|
|
920
|
+
or access_level is not None
|
|
921
|
+
or tags is not None
|
|
922
|
+
)
|
|
923
|
+
if has_metadata:
|
|
858
924
|
update_req = ArticlesUpdateRequest(
|
|
859
925
|
id=id,
|
|
860
926
|
title=title,
|
|
861
927
|
description=description,
|
|
862
928
|
status=status,
|
|
929
|
+
applies_to_parts=applies_to_parts_req,
|
|
930
|
+
access_level=access_level,
|
|
931
|
+
tags=tags_req,
|
|
863
932
|
)
|
|
864
933
|
return await self.update(update_req)
|
|
865
934
|
|
|
@@ -12,11 +12,13 @@ from mcp.server.fastmcp import Context
|
|
|
12
12
|
|
|
13
13
|
from devrev.exceptions import DevRevError
|
|
14
14
|
from devrev.models.articles import (
|
|
15
|
+
ArticleAccessLevel,
|
|
15
16
|
ArticlesDeleteRequest,
|
|
16
17
|
ArticlesGetRequest,
|
|
17
18
|
ArticlesListRequest,
|
|
18
19
|
ArticleStatus,
|
|
19
20
|
)
|
|
21
|
+
from devrev.models.base import SetTagWithValue
|
|
20
22
|
from devrev_mcp.server import _config, mcp
|
|
21
23
|
from devrev_mcp.utils.errors import format_devrev_error
|
|
22
24
|
from devrev_mcp.utils.formatting import serialize_model, serialize_models
|
|
@@ -102,6 +104,9 @@ if _config.enable_destructive_tools:
|
|
|
102
104
|
description: str | None = None,
|
|
103
105
|
status: str | None = None,
|
|
104
106
|
content_format: str = "text/html",
|
|
107
|
+
applies_to_parts: list[str] | None = None,
|
|
108
|
+
scope: int | None = None,
|
|
109
|
+
tags: list[str] | None = None,
|
|
105
110
|
) -> dict[str, Any]:
|
|
106
111
|
"""Create a new article with content.
|
|
107
112
|
|
|
@@ -113,6 +118,10 @@ if _config.enable_destructive_tools:
|
|
|
113
118
|
description: Optional short metadata description (NOT the article body).
|
|
114
119
|
status: Optional article status (draft, published, archived).
|
|
115
120
|
content_format: Content MIME type (default: text/html).
|
|
121
|
+
applies_to_parts: Optional list of part IDs (products, capabilities,
|
|
122
|
+
features, enhancements) to associate the article with.
|
|
123
|
+
scope: Optional visibility scope (1=internal, 2=external).
|
|
124
|
+
tags: Optional list of tag IDs to apply to the article.
|
|
116
125
|
|
|
117
126
|
Returns:
|
|
118
127
|
Dictionary containing the created article details.
|
|
@@ -132,6 +141,9 @@ if _config.enable_destructive_tools:
|
|
|
132
141
|
f"Valid statuses: {', '.join(s.name for s in ArticleStatus)}"
|
|
133
142
|
) from e
|
|
134
143
|
|
|
144
|
+
# Convert tag IDs to SetTagWithValue objects
|
|
145
|
+
tags_list = [SetTagWithValue(id=tag_id) for tag_id in tags] if tags is not None else None
|
|
146
|
+
|
|
135
147
|
article = await app.get_client().articles.create_with_content(
|
|
136
148
|
title=title,
|
|
137
149
|
content=content,
|
|
@@ -139,6 +151,9 @@ if _config.enable_destructive_tools:
|
|
|
139
151
|
description=description,
|
|
140
152
|
status=article_status,
|
|
141
153
|
content_format=content_format,
|
|
154
|
+
applies_to_parts=applies_to_parts,
|
|
155
|
+
scope=scope,
|
|
156
|
+
tags=tags_list,
|
|
142
157
|
)
|
|
143
158
|
return serialize_model(article)
|
|
144
159
|
except DevRevError as e:
|
|
@@ -152,6 +167,9 @@ if _config.enable_destructive_tools:
|
|
|
152
167
|
content: str | None = None,
|
|
153
168
|
description: str | None = None,
|
|
154
169
|
status: str | None = None,
|
|
170
|
+
applies_to_parts: list[str] | None = None,
|
|
171
|
+
access_level: str | None = None,
|
|
172
|
+
tags: list[str] | None = None,
|
|
155
173
|
) -> dict[str, Any]:
|
|
156
174
|
"""Update an existing article in DevRev.
|
|
157
175
|
|
|
@@ -162,6 +180,14 @@ if _config.enable_destructive_tools:
|
|
|
162
180
|
content: Optional new article body content.
|
|
163
181
|
description: Optional new metadata description (NOT the article body).
|
|
164
182
|
status: Optional new status (draft, published, archived).
|
|
183
|
+
applies_to_parts: Optional list of part IDs (products, capabilities,
|
|
184
|
+
features, enhancements) to associate the article with.
|
|
185
|
+
Pass an empty list to remove all associations.
|
|
186
|
+
access_level: Optional access level (internal, external, private, public).
|
|
187
|
+
Note: For updates, use ``access_level`` (string enum). For creation,
|
|
188
|
+
use the ``scope`` parameter (integer: 1=internal, 2=external).
|
|
189
|
+
tags: Optional list of tag IDs to apply to the article.
|
|
190
|
+
Pass an empty list to remove all tags.
|
|
165
191
|
|
|
166
192
|
Returns:
|
|
167
193
|
Dictionary containing the updated article details.
|
|
@@ -181,12 +207,29 @@ if _config.enable_destructive_tools:
|
|
|
181
207
|
f"Valid statuses: {', '.join(s.name for s in ArticleStatus)}"
|
|
182
208
|
) from e
|
|
183
209
|
|
|
210
|
+
# Convert access_level string to ArticleAccessLevel enum
|
|
211
|
+
article_access_level = None
|
|
212
|
+
if access_level:
|
|
213
|
+
try:
|
|
214
|
+
article_access_level = ArticleAccessLevel[access_level.upper()]
|
|
215
|
+
except KeyError as e:
|
|
216
|
+
raise RuntimeError(
|
|
217
|
+
f"Invalid access level: {e.args[0]}. "
|
|
218
|
+
f"Valid levels: {', '.join(a.name for a in ArticleAccessLevel)}"
|
|
219
|
+
) from e
|
|
220
|
+
|
|
221
|
+
# Convert tag IDs to SetTagWithValue objects
|
|
222
|
+
tags_list = [SetTagWithValue(id=tag_id) for tag_id in tags] if tags is not None else None
|
|
223
|
+
|
|
184
224
|
article = await app.get_client().articles.update_with_content(
|
|
185
225
|
id=id,
|
|
186
226
|
title=title,
|
|
187
227
|
content=content,
|
|
188
228
|
description=description,
|
|
189
229
|
status=article_status,
|
|
230
|
+
applies_to_parts=applies_to_parts,
|
|
231
|
+
access_level=article_access_level,
|
|
232
|
+
tags=tags_list,
|
|
190
233
|
)
|
|
191
234
|
return serialize_model(article)
|
|
192
235
|
except DevRevError as e:
|
|
@@ -110,7 +110,9 @@ def mock_client():
|
|
|
110
110
|
client.articles.list = AsyncMock()
|
|
111
111
|
client.articles.get = AsyncMock()
|
|
112
112
|
client.articles.create = AsyncMock()
|
|
113
|
+
client.articles.create_with_content = AsyncMock()
|
|
113
114
|
client.articles.update = AsyncMock()
|
|
115
|
+
client.articles.update_with_content = AsyncMock()
|
|
114
116
|
client.articles.delete = AsyncMock()
|
|
115
117
|
client.articles.count = AsyncMock()
|
|
116
118
|
|
|
@@ -154,6 +154,81 @@ class TestArticlesCreateTool:
|
|
|
154
154
|
owned_by=["don:identity:dvrv-us-1:devo/test:devu/1"],
|
|
155
155
|
)
|
|
156
156
|
|
|
157
|
+
@pytest.mark.asyncio
|
|
158
|
+
async def test_create_with_applies_to_parts(self, mock_ctx, mock_client):
|
|
159
|
+
"""Test creating an article with applies_to_parts."""
|
|
160
|
+
mock_article = _make_mock_article(
|
|
161
|
+
title="Article with Parts",
|
|
162
|
+
description="Content with parts",
|
|
163
|
+
)
|
|
164
|
+
mock_client.articles.create_with_content.return_value = mock_article
|
|
165
|
+
|
|
166
|
+
result = await devrev_articles_create(
|
|
167
|
+
mock_ctx,
|
|
168
|
+
title="Article with Parts",
|
|
169
|
+
content="Content with parts",
|
|
170
|
+
owned_by=["don:identity:dvrv-us-1:devo/test:devu/1"],
|
|
171
|
+
applies_to_parts=[
|
|
172
|
+
"don:core:dvrv-us-1:devo/1:product/1",
|
|
173
|
+
"don:core:dvrv-us-1:devo/1:capability/2",
|
|
174
|
+
],
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
assert result["title"] == "Article with Parts"
|
|
178
|
+
# Verify applies_to_parts was passed to SDK
|
|
179
|
+
call_args = mock_client.articles.create_with_content.call_args
|
|
180
|
+
assert call_args[1]["applies_to_parts"] == [
|
|
181
|
+
"don:core:dvrv-us-1:devo/1:product/1",
|
|
182
|
+
"don:core:dvrv-us-1:devo/1:capability/2",
|
|
183
|
+
]
|
|
184
|
+
|
|
185
|
+
@pytest.mark.asyncio
|
|
186
|
+
async def test_create_with_scope(self, mock_ctx, mock_client):
|
|
187
|
+
"""Test creating an article with scope (internal)."""
|
|
188
|
+
mock_article = _make_mock_article(
|
|
189
|
+
title="Internal Article",
|
|
190
|
+
description="Internal content",
|
|
191
|
+
)
|
|
192
|
+
mock_client.articles.create_with_content.return_value = mock_article
|
|
193
|
+
|
|
194
|
+
result = await devrev_articles_create(
|
|
195
|
+
mock_ctx,
|
|
196
|
+
title="Internal Article",
|
|
197
|
+
content="Internal content",
|
|
198
|
+
owned_by=["don:identity:dvrv-us-1:devo/test:devu/1"],
|
|
199
|
+
scope=1, # 1 = internal
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
assert result["title"] == "Internal Article"
|
|
203
|
+
# Verify scope was passed to SDK
|
|
204
|
+
call_args = mock_client.articles.create_with_content.call_args
|
|
205
|
+
assert call_args[1]["scope"] == 1
|
|
206
|
+
|
|
207
|
+
@pytest.mark.asyncio
|
|
208
|
+
async def test_create_with_tags(self, mock_ctx, mock_client):
|
|
209
|
+
"""Test creating an article with tags."""
|
|
210
|
+
mock_article = _make_mock_article(
|
|
211
|
+
title="Tagged Article",
|
|
212
|
+
description="Content with tags",
|
|
213
|
+
)
|
|
214
|
+
mock_client.articles.create_with_content.return_value = mock_article
|
|
215
|
+
|
|
216
|
+
result = await devrev_articles_create(
|
|
217
|
+
mock_ctx,
|
|
218
|
+
title="Tagged Article",
|
|
219
|
+
content="Content with tags",
|
|
220
|
+
owned_by=["don:identity:dvrv-us-1:devo/test:devu/1"],
|
|
221
|
+
tags=["don:core:dvrv-us-1:devo/1:tag/1", "don:core:dvrv-us-1:devo/1:tag/2"],
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
assert result["title"] == "Tagged Article"
|
|
225
|
+
# Verify tags were converted to SetTagWithValue and passed to SDK
|
|
226
|
+
call_args = mock_client.articles.create_with_content.call_args
|
|
227
|
+
tags_arg = call_args[1]["tags"]
|
|
228
|
+
assert len(tags_arg) == 2
|
|
229
|
+
assert tags_arg[0].id == "don:core:dvrv-us-1:devo/1:tag/1"
|
|
230
|
+
assert tags_arg[1].id == "don:core:dvrv-us-1:devo/1:tag/2"
|
|
231
|
+
|
|
157
232
|
|
|
158
233
|
class TestArticlesUpdateTool:
|
|
159
234
|
"""Tests for devrev_articles_update tool."""
|
|
@@ -186,6 +261,131 @@ class TestArticlesUpdateTool:
|
|
|
186
261
|
with pytest.raises(RuntimeError, match="Article not found"):
|
|
187
262
|
await devrev_articles_update(mock_ctx, id="nonexistent", title="New")
|
|
188
263
|
|
|
264
|
+
@pytest.mark.asyncio
|
|
265
|
+
async def test_update_with_applies_to_parts(self, mock_ctx, mock_client):
|
|
266
|
+
"""Test updating an article with applies_to_parts."""
|
|
267
|
+
mock_article = _make_mock_article(
|
|
268
|
+
id="article-1",
|
|
269
|
+
title="Updated Article",
|
|
270
|
+
status="published",
|
|
271
|
+
)
|
|
272
|
+
mock_client.articles.update_with_content.return_value = mock_article
|
|
273
|
+
|
|
274
|
+
result = await devrev_articles_update(
|
|
275
|
+
mock_ctx,
|
|
276
|
+
id="article-1",
|
|
277
|
+
title="Updated Article",
|
|
278
|
+
applies_to_parts=["don:core:dvrv-us-1:devo/1:feature/3"],
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
assert result["title"] == "Updated Article"
|
|
282
|
+
# Verify applies_to_parts was passed to SDK
|
|
283
|
+
call_args = mock_client.articles.update_with_content.call_args
|
|
284
|
+
assert call_args[1]["applies_to_parts"] == ["don:core:dvrv-us-1:devo/1:feature/3"]
|
|
285
|
+
|
|
286
|
+
@pytest.mark.asyncio
|
|
287
|
+
async def test_update_with_access_level(self, mock_ctx, mock_client):
|
|
288
|
+
"""Test updating an article with access_level."""
|
|
289
|
+
from devrev.models.articles import ArticleAccessLevel
|
|
290
|
+
|
|
291
|
+
mock_article = _make_mock_article(
|
|
292
|
+
id="article-1",
|
|
293
|
+
title="Internal Article",
|
|
294
|
+
status="published",
|
|
295
|
+
)
|
|
296
|
+
mock_client.articles.update_with_content.return_value = mock_article
|
|
297
|
+
|
|
298
|
+
result = await devrev_articles_update(
|
|
299
|
+
mock_ctx,
|
|
300
|
+
id="article-1",
|
|
301
|
+
access_level="internal",
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
assert result["title"] == "Internal Article"
|
|
305
|
+
# Verify access_level was converted to enum and passed to SDK
|
|
306
|
+
call_args = mock_client.articles.update_with_content.call_args
|
|
307
|
+
assert call_args[1]["access_level"] == ArticleAccessLevel.INTERNAL
|
|
308
|
+
|
|
309
|
+
@pytest.mark.asyncio
|
|
310
|
+
async def test_update_with_tags(self, mock_ctx, mock_client):
|
|
311
|
+
"""Test updating an article with tags."""
|
|
312
|
+
mock_article = _make_mock_article(
|
|
313
|
+
id="article-1",
|
|
314
|
+
title="Tagged Article",
|
|
315
|
+
status="published",
|
|
316
|
+
)
|
|
317
|
+
mock_client.articles.update_with_content.return_value = mock_article
|
|
318
|
+
|
|
319
|
+
result = await devrev_articles_update(
|
|
320
|
+
mock_ctx,
|
|
321
|
+
id="article-1",
|
|
322
|
+
tags=["don:core:dvrv-us-1:devo/1:tag/1"],
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
assert result["title"] == "Tagged Article"
|
|
326
|
+
# Verify tags were converted to SetTagWithValue and passed to SDK
|
|
327
|
+
call_args = mock_client.articles.update_with_content.call_args
|
|
328
|
+
tags_arg = call_args[1]["tags"]
|
|
329
|
+
assert len(tags_arg) == 1
|
|
330
|
+
assert tags_arg[0].id == "don:core:dvrv-us-1:devo/1:tag/1"
|
|
331
|
+
|
|
332
|
+
@pytest.mark.asyncio
|
|
333
|
+
async def test_update_with_invalid_access_level(self, mock_ctx, mock_client):
|
|
334
|
+
"""Test updating an article with invalid access_level raises error."""
|
|
335
|
+
with pytest.raises(RuntimeError, match="Invalid access level"):
|
|
336
|
+
await devrev_articles_update(
|
|
337
|
+
mock_ctx,
|
|
338
|
+
id="article-1",
|
|
339
|
+
access_level="invalid_level",
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
@pytest.mark.asyncio
|
|
343
|
+
async def test_update_with_empty_tags_removes_all(self, mock_ctx, mock_client):
|
|
344
|
+
"""Test updating with empty tags list removes all tags."""
|
|
345
|
+
mock_article = _make_mock_article(
|
|
346
|
+
id="article-1",
|
|
347
|
+
title="No Tags Article",
|
|
348
|
+
status="published",
|
|
349
|
+
)
|
|
350
|
+
mock_client.articles.update_with_content.return_value = mock_article
|
|
351
|
+
|
|
352
|
+
result = await devrev_articles_update(
|
|
353
|
+
mock_ctx,
|
|
354
|
+
id="article-1",
|
|
355
|
+
tags=[],
|
|
356
|
+
)
|
|
357
|
+
|
|
358
|
+
assert result["title"] == "No Tags Article"
|
|
359
|
+
# Verify empty list is passed (not None) to clear tags
|
|
360
|
+
call_args = mock_client.articles.update_with_content.call_args
|
|
361
|
+
tags_arg = call_args[1]["tags"]
|
|
362
|
+
assert tags_arg is not None
|
|
363
|
+
assert tags_arg == []
|
|
364
|
+
|
|
365
|
+
@pytest.mark.asyncio
|
|
366
|
+
async def test_create_with_empty_tags(self, mock_ctx, mock_client):
|
|
367
|
+
"""Test creating with empty tags list passes empty list (not None)."""
|
|
368
|
+
mock_article = _make_mock_article(
|
|
369
|
+
title="No Tags Article",
|
|
370
|
+
description="Content without tags",
|
|
371
|
+
)
|
|
372
|
+
mock_client.articles.create_with_content.return_value = mock_article
|
|
373
|
+
|
|
374
|
+
result = await devrev_articles_create(
|
|
375
|
+
mock_ctx,
|
|
376
|
+
title="No Tags Article",
|
|
377
|
+
content="Content without tags",
|
|
378
|
+
owned_by=["don:identity:dvrv-us-1:devo/test:devu/1"],
|
|
379
|
+
tags=[],
|
|
380
|
+
)
|
|
381
|
+
|
|
382
|
+
assert result["title"] == "No Tags Article"
|
|
383
|
+
# Verify empty list is passed (not None)
|
|
384
|
+
call_args = mock_client.articles.create_with_content.call_args
|
|
385
|
+
tags_arg = call_args[1]["tags"]
|
|
386
|
+
assert tags_arg is not None
|
|
387
|
+
assert tags_arg == []
|
|
388
|
+
|
|
189
389
|
|
|
190
390
|
class TestArticlesDeleteTool:
|
|
191
391
|
"""Tests for devrev_articles_delete tool."""
|