affinity-sdk 2.0.4__tar.gz → 2.0.5__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.
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.github/workflows/plugin-build.yml +2 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.github/workflows/plugin-release.yml +2 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.github/workflows/release.yml +2 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/CHANGELOG.md +58 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/PKG-INFO +1 -1
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/company_cmds.py +3 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/field_cmds.py +73 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/list_cmds.py +13 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/person_cmds.py +12 -1
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/context.py +2 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/entity_search.py +5 -1
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/results.py +4 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/runner.py +3 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/models/entities.py +4 -1
- affinity_sdk-2.0.5/affinity/services/_batch_interactions.py +92 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/services/_org_reads.py +37 -1
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/services/companies.py +59 -16
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/services/persons.py +90 -13
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/services/reminders.py +12 -4
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/services/v1_only.py +16 -9
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/cli/commands.md +17 -4
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/guides/filtering.md +5 -1
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/reference/services/companies.md +23 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/reference/services/persons.md +9 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.claude-plugin/plugin.json +1 -1
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.claude-plugin/skills/pipeline-history/SKILL.md +4 -2
- affinity_sdk-2.0.5/mcp/.mcp-bash/VERSION +1 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/core.sh +3 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/tools_policy.sh +48 -11
- affinity_sdk-2.0.5/mcp/.mcp-bash/vendor.json +1 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.registry/commands.generated.json +2 -2
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/CHANGELOG.md +30 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/COMPATIBILITY +10 -2
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/Makefile +3 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/README.md +1 -0
- affinity_sdk-2.0.5/mcp/VERSION +1 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/mcp-bash.lock +2 -2
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/resources/data-model/data-model.md +4 -1
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/server.d/requirements.json +1 -1
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/server.d/server.meta.json +1 -1
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/plugins/affinity-sdk/.claude-plugin/plugin.json +1 -1
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/plugins/affinity-sdk/.claude-plugin/skills/affinity-python-sdk/SKILL.md +1 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/plugins/affinity-sdk/.claude-plugin/skills/affinity-python-sdk/references/services.md +33 -1
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/plugins/xaffinity-cli/.claude-plugin/plugin.json +1 -1
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/plugins/xaffinity-cli/hooks/pre-xaffinity.sh +2 -2
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/plugins/xaffinity-cli/hooks/session-setup.sh +1 -1
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/plugins/xaffinity-cli/skills/xaffinity-cli-usage/SKILL.md +2 -2
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/plugins/xaffinity-cli/skills/xaffinity-cli-usage/references/filtering.md +5 -1
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/plugins/xaffinity-cli/skills/xaffinity-cli-usage/references/history-and-activity.md +4 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/plugins/xaffinity-cli/skills/xaffinity-cli-usage/references/setup.md +1 -1
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/pyproject.toml +1 -1
- affinity_sdk-2.0.5/tests/cowork/cassettes/company-lists-status.cassette.json +410 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cowork/cassettes/hook-blocks-without-key.cassette.json +68 -68
- affinity_sdk-2.0.5/tests/cowork/cassettes/no-key-skill-path.cassette.json +423 -0
- affinity_sdk-2.0.5/tests/cowork/cassettes/status-history.cassette.json +469 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_entity_ls_server_filter.py +1 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_field_history_bulk.py +16 -0
- affinity_sdk-2.0.5/tests/test_cli_field_history_deleted_options.py +126 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_list_export_server_filter.py +33 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_person_get.py +2 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_file_list_batch.py +4 -11
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_reminder_list_batch.py +22 -2
- affinity_sdk-2.0.5/tests/test_services_batch_get_interaction_dates.py +126 -0
- affinity_sdk-2.0.5/tests/test_services_entity_list_entries.py +130 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_services_field_value_changes.py +9 -0
- affinity_sdk-2.0.4/mcp/.mcp-bash/VERSION +0 -1
- affinity_sdk-2.0.4/mcp/.mcp-bash/vendor.json +0 -1
- affinity_sdk-2.0.4/mcp/VERSION +0 -1
- affinity_sdk-2.0.4/tests/cowork/cassettes/company-lists-status.cassette.json +0 -410
- affinity_sdk-2.0.4/tests/cowork/cassettes/no-key-skill-path.cassette.json +0 -417
- affinity_sdk-2.0.4/tests/cowork/cassettes/status-history.cassette.json +0 -492
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.claude-plugin/marketplace.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.cursor/rules/test-data-privacy.mdc +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.editorconfig +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.env.example +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.gitattributes +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.github/CODEOWNERS +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.github/PULL_REQUEST_TEMPLATE/cli_command.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.github/PULL_REQUEST_TEMPLATE/release.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.github/dependabot.yml +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.github/labels.yml +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.github/mcp-release-install-footer.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.github/pull_request_template.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.github/release-install-footer.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.github/workflows/ci.yml +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.github/workflows/cowork-replay.yml +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.github/workflows/docs.yml +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.github/workflows/labels.yml +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.github/workflows/linkcheck.yml +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.github/workflows/openapi-validation.yml +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.github/workflows/release-detect.yml +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.github/workflows/version-check.yml +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.gitignore +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/.pre-commit-config.yaml +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/AGENTS.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/CODE_OF_CONDUCT.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/CONTRIBUTING.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/LICENSE +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/README.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/SECURITY.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/VERSIONING.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/__init__.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/_filtering/__init__.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/_filtering/dates.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/_filtering/filter_text.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/_filtering/pushdown.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/_filtering/search.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/_filtering/where.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/_internal/__init__.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/_internal/keyfile.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/api_versions.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/__init__.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/__main__.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/_update_worker.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/async_utils.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/click_compat.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/__init__.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/_entity_field.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/_entity_files_dump.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/_entity_files_read.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/_entity_files_upload.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/_list_entry_fields.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/_org_reads.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/_search_common.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/_v1_parsing.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/completion_cmd.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/config_cmds.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/discovery_cmds.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/entry_cmds.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/file_cmds.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/file_url_cmd.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/interaction_cmds.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/note_cmds.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/opportunity_cmds.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/org_cmds.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/org_read_cmds.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/query_cmd.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/relationship_strength_cmds.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/reminder_cmds.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/resolve_url_cmd.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/session_cmds.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/task_cmds.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/transcript_cmds.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/version_cmd.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/webhook_cmds.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/commands/whoami_cmd.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/config.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/confirm.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/constants.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/csv_utils.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/date_utils.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/decorators.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/errors.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/field_utils.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/formatters.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/help_json.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/interaction_utils.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/list_search.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/logging.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/main.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/mcp_limits.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/options.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/paths.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/progress.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/query/__init__.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/query/aggregates.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/query/cursor.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/query/dates.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/query/exceptions.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/query/executor.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/query/filter_text.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/query/filters.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/query/models.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/query/output.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/query/parser.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/query/planner.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/query/progress.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/query/pushdown.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/query/schema.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/render.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/resolve.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/resolvers.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/serialization.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/session_cache.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/types.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/cli/update_check.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/client.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/clients/__init__.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/clients/http.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/clients/pipeline.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/compare.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/criteria.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/downloads.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/exceptions.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/field_resolve_utils.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/field_resolver.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/filters.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/hooks.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/inbound_webhooks.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/models/__init__.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/models/discovery.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/models/interactions_v2.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/models/org.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/models/pagination.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/models/rate_limit_snapshot.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/models/relationships_v2.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/models/search.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/models/secondary.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/models/transcripts.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/models/types.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/policies.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/progress.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/py.typed +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/services/__init__.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/services/_discovery.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/services/_dropdown_options.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/services/_field_listing.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/services/_field_updates.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/services/_note_html.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/services/_search.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/services/_single_field.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/services/_v2_filters.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/services/lists.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/services/opportunities.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/services/org.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/services/rate_limits.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/services/search.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/services/tasks.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/services/transcripts.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/services/webhooks.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/affinity/types.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/codecov.yml +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/cli-development-guide.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/ai-integrations/index.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/changelog.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/cli/index.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/cli/scripting.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/cli-reference.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/examples.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/getting-started.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/glossary.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/guides/affinity-official-mcp-comparison.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/guides/api-versions-and-routing.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/guides/api-versions.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/guides/authentication.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/guides/claude-code-plugins.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/guides/configuration.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/guides/csv-export.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/guides/datetime-handling.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/guides/debugging-hooks.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/guides/errors-and-retries.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/guides/field-types-and-values.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/guides/field-values.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/guides/ids-and-types.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/guides/migrating-to-2.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/guides/models.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/guides/opportunity-associations.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/guides/pagination.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/guides/performance.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/guides/query-command.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/guides/rate-limits.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/guides/sync-vs-async.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/guides/webhooks.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/index.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/mcp/index.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/reference/api-coverage.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/reference/client.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/reference/exceptions.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/reference/filters.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/reference/models.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/reference/query-language.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/reference/services/lists.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/reference/services/opportunities.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/reference/services/reminders.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/reference/services/tasks.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/reference/services/teams-users.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/reference/services/transcripts.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/reference/services/v1/auth.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/reference/services/v1/field-values.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/reference/services/v1/fields.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/reference/services/v1/files.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/reference/services/v1/interactions.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/reference/services/v1/notes.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/reference/services/v1/relationships.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/reference/services/webhooks.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/reference/types.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/docs/public/troubleshooting.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/examples/advanced_usage.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/examples/async_lifecycle.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/examples/basic_usage.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/examples/filter_builder.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/examples/hooks_debugging.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/examples/list_management.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/examples/resolve_helpers.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/examples/task_polling.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.claude-plugin/.gitignore +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.claude-plugin/skills/affinity-mcp-workflows/SKILL.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.claude-plugin/skills/query-language/SKILL.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.claude-plugin/skills/query-language/references/filter-operators.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.claude-plugin/skills/query-language/references/include-expand.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.claude-plugin/skills/query-language/references/output-formats.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.claude-plugin/skills/query-language/references/quantifiers.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.claude-plugin/xaffinity-mcp.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.gitignore +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/bin/mcp-bash +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/handlers/completion.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/handlers/lifecycle.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/handlers/logging.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/handlers/ping.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/handlers/prompts.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/handlers/resources.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/handlers/roots.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/handlers/tools.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/auth.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/capabilities.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/cli/common.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/cli/health.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/completion.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/elicitation.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/file_read.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/handler_helpers.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/hash.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/ids.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/io.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/json.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/lock.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/logging.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/meta_env.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/paginate.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/path.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/policy.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/progress-passthrough.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/progress.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/prompts.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/registry.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/require.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/resource_content.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/resource_match.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/resource_providers.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/resources.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/roots.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/rpc.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/runtime.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/spec.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/timeout.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/tools.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/ui-templates.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/ui.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/uri.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/lib/validate.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/providers/echo.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/providers/file.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/providers/git.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/providers/https.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/providers/ui.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/sdk/tool-error.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/sdk/tool-sdk.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.mcp-bash/sdk/ui-sdk.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.registry/mcp-commands.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.registry/prompts.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.registry/resource-templates.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.registry/resources.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/.registry/ui-resources.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/completions/entity-name.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/completions/list-name.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/completions/status-value.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/docs/DEBUGGING.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/icon.svg +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/lib/cache.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/lib/cli-detect.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/lib/cli-gateway.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/lib/common.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/lib/entity-types.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/lib/field-resolution.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/mcp-publisher.lock +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/mcpb.conf +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/prompts/change-status/change-status.completion.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/prompts/change-status/change-status.meta.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/prompts/change-status/change-status.txt +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/prompts/interaction-brief/interaction-brief.meta.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/prompts/interaction-brief/interaction-brief.txt +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/prompts/log-call/log-call.meta.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/prompts/log-call/log-call.txt +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/prompts/log-interaction-and-update-workflow/log-interaction-and-update-workflow.meta.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/prompts/log-interaction-and-update-workflow/log-interaction-and-update-workflow.txt +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/prompts/log-message/log-message.meta.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/prompts/log-message/log-message.txt +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/prompts/pipeline-review/pipeline-review.completion.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/prompts/pipeline-review/pipeline-review.meta.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/prompts/pipeline-review/pipeline-review.txt +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/prompts/prepare-briefing/prepare-briefing.meta.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/prompts/prepare-briefing/prepare-briefing.txt +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/prompts/warm-intro/warm-intro.meta.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/prompts/warm-intro/warm-intro.txt +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/providers/xaffinity.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/resources/data-model/data-model.meta.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/resources/field-catalogs/field-catalogs.meta.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/resources/field-catalogs/field-catalogs.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/resources/interaction-enums/interaction-enums.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/resources/interaction-enums/interaction-enums.meta.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/resources/me/me.meta.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/resources/me/me.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/resources/me-person-id/me-person-id.meta.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/resources/me-person-id/me-person-id.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/resources/query-guide/query-guide.meta.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/resources/query-guide/query-guide.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/resources/saved-views/saved-views.meta.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/resources/saved-views/saved-views.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/resources/workflow-config/workflow-config.meta.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/resources/workflow-config/workflow-config.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/resources/workflows-guide/workflows-guide.meta.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/resources/workflows-guide/workflows-guide.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/resources/xaffinity-field-catalogs.completion.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/resources/xaffinity-saved-views.completion.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/resources/xaffinity-workflow-config.completion.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/server.d/env.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/server.d/health-checks.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/server.d/policy.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/server.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/test/README.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/test/run.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/test/test_env_update_check.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/test-progress.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/tools/discover-commands/tool.meta.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/tools/discover-commands/tool.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/tools/execute-read-command/tool.meta.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/tools/execute-read-command/tool.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/tools/execute-write-command/tool.meta.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/tools/execute-write-command/tool.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/tools/get-entity-dossier/tool.meta.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/tools/get-entity-dossier/tool.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/tools/get-file-url/tool.meta.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/tools/get-file-url/tool.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/tools/query/tool.meta.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/tools/query/tool.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/tools/read-xaffinity-resource/tool.meta.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/tools/read-xaffinity-resource/tool.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/user-config.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/xaffinity-mcp-env.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mcp/xaffinity-mcp.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/mkdocs.yml +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/plugins/xaffinity-cli/hooks/guard-env-read.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/plugins/xaffinity-cli/hooks/hooks.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/plugins/xaffinity-cli/skills/xaffinity-cli-usage/references/files-and-writes.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/plugins/xaffinity-cli/skills/xaffinity-cli-usage/references/interactions.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/plugins/xaffinity-cli/skills/xaffinity-cli-usage/references/query-guide.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cli/query/test_cursor.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cli/test_company_create_dedup.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cli/test_company_ls_filter_rejection.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cli/test_formatters.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cli/test_output_formats_integration.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cli/test_person_create_dedup.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cli/test_person_ls_filter_rejection.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cli/test_query_filter_rejection.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cli/test_query_list_entry_relationships.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cli/test_query_list_export_parity.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cli/test_query_output_flattening.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cli/test_query_output_truncation.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cli/test_query_unreplied.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/conftest.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cowork/.cowork-redact.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cowork/README.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cowork/fixtures/workdir-key/README.txt +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cowork/fixtures/workdir-key/xaffinity-test-key +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cowork/fixtures/workdir-nokey/README.txt +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cowork/image/Dockerfile +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cowork/image/fakeaff/build_fixtures.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cowork/image/fakeaff/fixtures.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cowork/image/fakeaff/server.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cowork/image/xaffinity-wrapper.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cowork/privacy-allow.txt +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cowork/record.sh +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cowork/scenarios/company-lists-status.yaml +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cowork/scenarios/hook-blocks-without-key.yaml +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cowork/scenarios/no-key-skill-path.yaml +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cowork/scenarios/status-history.yaml +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cowork/sessions/no-key.yaml +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/cowork/sessions/with-key.yaml +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/field_write_mocks.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/fixtures/openapi/mini_openapi.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/fixtures/webhooks/field_value_updated.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/fixtures/webhooks/list_entry_created.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/fixtures/webhooks/organization_created.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/fixtures/webhooks/organization_merged.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/fixtures/webhooks/person_created.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/fixtures/webhooks/unknown_event.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/integration/README.md +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/integration/conftest.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/integration/setup_query_parity_data.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/integration/test_cli_writes.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/integration/test_query_parity_integration.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/integration/test_sdk_reads.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/integration/test_sdk_writes.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/integration/test_sdk_writes_runner.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/mcp/__init__.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/mcp/test_query_cursor.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/skill-evals/xaffinity-cli-usage-evals/evals.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/spec_guard.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_affinity_client_wrapper_additional_coverage.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_api_coverage.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_api_key_file_formats.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_api_key_resolution.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_api_version.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_api_version_per_operation.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_async_file_download_streaming.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_batch_get.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_api_version.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_column_limiting.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_command_context.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_commands_must_fix.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_company_cmds_coverage.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_company_get.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_config_cmds.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_context_coverage.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_csv_export.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_date_params.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_date_utils.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_datetime_formatting.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_datetime_header_offsets.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_domain_linkification.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_dotenv_resolution.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_dropdown_field_writes.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_enriched_field_writes.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_entity_field_writes.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_entity_files_dump.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_entry_field.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_entry_field_batch_writes.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_entry_field_multi_value_limits.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_error_hints.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_error_rendering.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_field_history.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_field_options_and_transcripts.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_field_utils.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_field_utils_coverage.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_field_utils_set_phase.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_field_value_humanization.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_file_url.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_files_ls.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_files_read.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_get_interaction_dates.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_help_json.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_interaction_date_chunking.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_interaction_utils.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_json_safety.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_list_cmds_coverage.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_list_expand_interactions.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_list_export_entity_scope.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_list_export_field_refresh.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_list_export_filter_safety.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_list_export_truncation_meta.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_missing_coverage.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_multi_value_truncation_warnings.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_no_network_commands.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_notes_writes.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_opportunity_cmds.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_opportunity_cmds_coverage.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_org.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_page_size_validation.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_pager_logic.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_person_cmds_coverage.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_plugin_manifest.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_pre_xaffinity_hook.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_progress_manager.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_query_aggregates.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_query_cmd.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_query_cmd_coverage.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_query_dates.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_query_executor.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_query_expand_interactions.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_query_filters.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_query_integration.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_query_must_fix.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_query_parser.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_query_planner.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_query_review_fixes.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_query_safety.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_query_schema.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_query_server_filter.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_rate_limit_rendering.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_rate_limit_throttle.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_reminders.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_render_coverage.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_resolve_coverage.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_resolve_url_parsing.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_result_summary.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_safe_field_writes.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_search.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_serialization.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_session_cache.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_session_setup_hook.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_set_phase_atomicity.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_types.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_unreplied.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_update_check.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_v1_only_cmds.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_v1_parsing.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_webhooks.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_cli_write_ops.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_client.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_companies_create_dedup.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_companies_filter_rejection.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_compare.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_duplicates_connections.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_env_helpers.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_exceptions_coverage.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_field_resolver.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_field_service_caching.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_field_types_c4.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_field_value_type.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_field_values_get_value.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_file_batch_get.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_file_download_streaming.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_file_upload_helpers_and_validation.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_files_upload_returning_files.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_files_v2.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_filters.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_generate_mcp_command_registry.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_get_fields_filter_includes.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_get_fields_pagination.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_get_first.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_hidden_field_values.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_hooks.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_http_client_additional_coverage.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_http_client_remaining_coverage.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_inbound_webhooks.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_integration_smoke.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_interaction_date_validation.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_interactions_and_files_regressions.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_isodatetime.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_list_entries_server_filter.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_list_entry_membership_and_opportunities.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_list_term.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_lists_v2_writes.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_mcp_bundle_env_and_completions.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_mcp_cli_version_check.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_mcp_entity_dossier.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_mcp_gateway_limits.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_mcp_history_bulk_gateway.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_mcp_limits.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_mcp_must_fix.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_mcp_query_cli_error.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_mcp_read_truncation.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_mcp_resource_scripts.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_models.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_models_v2_2026_fields.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_multi_value_limits.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_new_features.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_notes_v2.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_notes_v2_writes.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_opportunities_filter_rejection.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_org_reads.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_pagination_iterators.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_persons_create_dedup.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_persons_filter_rejection.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_public_api.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_query_pushdown.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_rate_limit_v2.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_raw_pipeline_hook_events.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_readonly_factory.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_reminders_v2.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_requirements_additional.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_review_fixes_sdk_cli.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_sdk_interaction_dates.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_sdk_must_fix.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_search.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_search_v2.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_service_get_parameter_combinations.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_services_companies_coverage_gaps.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_services_dropdown_options.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_services_entity_field_updates.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_services_list_entries_filter_paths.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_services_lists_additional_coverage.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_services_lists_coverage_gaps.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_services_opportunities_additional_coverage.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_services_opportunities_coverage_gaps.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_services_opportunities_tasks_additional_coverage.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_services_pages_cursor_guard.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_services_persons_companies_additional_coverage.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_services_rate_limits_coverage_gaps.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_services_v1_only_async.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_services_v1_only_coverage_gaps.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_single_field_v2.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_small_modules_coverage.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_spec_guard.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_teams_users_feedback.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_transport_and_readonly_mode.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_v1_association_parsing.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_v1_only_services_additional_coverage.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_v1_only_services_more_coverage.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_v2_request_bodies.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_validate_openapi_tool.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/test_webhooks_v2.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/unit/__init__.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tests/unit/test_exceptions.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tools/__init__.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tools/api_coverage.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tools/api_coverage.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tools/api_coverage_v1_snapshot.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tools/check_cli_patterns.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tools/generate_mcp_command_registry.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tools/generate_release_notes.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tools/generate_requirements_mapping.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tools/openapi_snapshots/2024-01-01.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tools/openapi_snapshots/2026-07-15.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tools/openapi_snapshots/2026-09-17.json +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tools/search_golden.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tools/sync_mcp_bundle_env.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tools/sync_mcp_registry.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tools/sync_mcp_version.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tools/validate_mcp_registry_metadata.py +0 -0
- {affinity_sdk-2.0.4 → affinity_sdk-2.0.5}/tools/validate_openapi_models.py +0 -0
|
@@ -5,6 +5,64 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.0.5] - 2026-10-14
|
|
9
|
+
|
|
10
|
+
**Exception to semantic versioning** (as 2.0.2–2.0.4): two fixes change what a call returns or
|
|
11
|
+
what the CLI prints. Each is marked **Behavior change**.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- **Behavior change. CLI: deleted dropdown options in `field history` and `field history-bulk`
|
|
16
|
+
(`--json`).** Affinity sends an option deleted since as its bare text ("Reach Out") and a live
|
|
17
|
+
one as `{id, text, rank, color}`; the CLI passed both through, so one field's history mixed
|
|
18
|
+
strings and objects. A deleted option is now `{"id": null, "text": "Reach Out", "deleted":
|
|
19
|
+
true}`, so every dropdown value has a `text`. Text fields keep their string values; live
|
|
20
|
+
options are unchanged. When a value is plain text the CLI reads the field's metadata (one call)
|
|
21
|
+
to tell a dropdown from a text field (`history-bulk --list-id` already has it). Table and CSV
|
|
22
|
+
output show the text, as before.
|
|
23
|
+
- **Behavior change. SDK: `on_error="skip"` leaves failed records out of
|
|
24
|
+
`AsyncReminderService.list_batch` and `AsyncFileService.list_batch`.** A failed request used
|
|
25
|
+
to leave its ids in the result with empty or partial lists, which looked like "no reminders" /
|
|
26
|
+
"no files"; one failed reminders request (50 ids) silently hid them all. They are now absent
|
|
27
|
+
from the result, as with every other `on_error="skip"` method: a requested id with no key
|
|
28
|
+
failed.
|
|
29
|
+
- SDK: `field_value_changes.iter_all()` reads 10,000 changes per call by default (was 100), the
|
|
30
|
+
V1 maximum: a 16,000-change history takes 3 calls instead of 161 (paging ends on an empty
|
|
31
|
+
page). Pass `page_size` for smaller
|
|
32
|
+
pages.
|
|
33
|
+
- SDK: `AsyncCompanyService.batch_get` / `AsyncPersonService.batch_get` with
|
|
34
|
+
`with_interaction_dates` and `field_ids` / `field_types` read the fields in one call per 100
|
|
35
|
+
ids and the dates in one V1 call per record: about N + N/100 calls instead of 2N. Results are
|
|
36
|
+
the same. Under `on_error="skip"` a failed fields call falls back to one read per id of it.
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- CLI: `list export --filter`, `company ls --filter` and `person ls --filter` report how the
|
|
41
|
+
filter was split in `meta.serverFilter` (`--json`): `pushed` (conditions Affinity's search
|
|
42
|
+
applied), `local` (checked only locally, with reasons) and, on `list export` when the search
|
|
43
|
+
was refused or turned off, `fallback` (why: refused, the list's fields unreadable, or
|
|
44
|
+
`XAFFINITY_QUERY_SERVER_FILTER=0`; the whole filter then ran locally). `list export
|
|
45
|
+
--dry-run` shows it as `data.serverFilter`. A `--cursor` resume doesn't report it.
|
|
46
|
+
Like `query --include-meta`, but always present with `--json`.
|
|
47
|
+
- SDK: `persons.get_list_entries()` takes `limit` and `cursor` (it returned only the first page).
|
|
48
|
+
|
|
49
|
+
### Fixed
|
|
50
|
+
|
|
51
|
+
- SDK: `companies.get_list_entries()` and `persons.get_list_entries()` set each entry's
|
|
52
|
+
`entity_id` and `entity_type` (`ORGANIZATION` / `PERSON`); the endpoint doesn't send them, so
|
|
53
|
+
they were `None`. `entity` stays `None` there. A `cursor` from another company's or person's
|
|
54
|
+
entries raises `ValueError` instead of labelling its entries with the wrong record. CLI:
|
|
55
|
+
`company get --expand list-entries` and `person get --expand list-entries` (`--json`) now
|
|
56
|
+
show each entry's `entityId` and `entityType` (1 company, 0 person).
|
|
57
|
+
- SDK: the `ListEntry` docstring said it always contains the entity; it says where `entity` is
|
|
58
|
+
filled.
|
|
59
|
+
- Docs: filtered-run cursors start with `xsearch2:` (the CLI page, filtering guide, CLI skill
|
|
60
|
+
and MCP data model said `xsearch1:`). The `field changes` docs say a deleted dropdown option is
|
|
61
|
+
`{"referenceType": "deleted-entity", "displayValue": ...}`. The companies and persons pages
|
|
62
|
+
say what reading interaction dates for many records costs, and the companies page and
|
|
63
|
+
`batch_get` docstring point to the relationship-intelligence fields for last / next meeting
|
|
64
|
+
dates.
|
|
65
|
+
|
|
8
66
|
## [2.0.4] - 2026-10-14
|
|
9
67
|
|
|
10
68
|
**Exception to semantic versioning** (the maintainer's call, as 2.0.2 and 2.0.3): which API key
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: affinity-sdk
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.5
|
|
4
4
|
Summary: A modern, strongly-typed Python SDK for the Affinity CRM API
|
|
5
5
|
Project-URL: Homepage, https://github.com/yaniv-golan/affinity-sdk
|
|
6
6
|
Project-URL: Documentation, https://yaniv-golan.github.io/affinity-sdk/latest/
|
|
@@ -436,6 +436,7 @@ def company_ls(
|
|
|
436
436
|
|
|
437
437
|
# --filter (or a cursor from a filtered run): Affinity's search filters on its side
|
|
438
438
|
if filter_expr is not None or is_filter_cursor(cursor):
|
|
439
|
+
server_filter: dict[str, Any] = {}
|
|
439
440
|
found, next_token = filtered_ls(
|
|
440
441
|
client.companies,
|
|
441
442
|
entity="company",
|
|
@@ -448,6 +449,7 @@ def company_ls(
|
|
|
448
449
|
max_results=max_results,
|
|
449
450
|
all_pages=all_pages,
|
|
450
451
|
warnings=warnings,
|
|
452
|
+
server_filter=server_filter,
|
|
451
453
|
)
|
|
452
454
|
return CommandOutput(
|
|
453
455
|
data={"companies": found},
|
|
@@ -457,6 +459,7 @@ def company_ls(
|
|
|
457
459
|
if next_token
|
|
458
460
|
else None
|
|
459
461
|
),
|
|
462
|
+
server_filter=server_filter or None,
|
|
460
463
|
api_called=True,
|
|
461
464
|
)
|
|
462
465
|
|
|
@@ -123,6 +123,75 @@ def _field_value_change_payload(item: FieldValueChange) -> dict[str, object]:
|
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
|
|
126
|
+
_DROPDOWN_VALUE_TYPES = frozenset(
|
|
127
|
+
{"dropdown", "dropdown-multi", "ranked-dropdown", "status-dropdown"}
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def _is_dropdown(meta: FieldMetadata) -> bool:
|
|
132
|
+
"""True for a dropdown field. V1 metadata's value type 2 covers both text and dropdown
|
|
133
|
+
fields, so there a dropdown is the ranked kind (7) or a field with options."""
|
|
134
|
+
raw = getattr(meta, "value_type_raw", None)
|
|
135
|
+
if isinstance(raw, int):
|
|
136
|
+
return raw == 7 or bool(getattr(meta, "dropdown_options", None))
|
|
137
|
+
if not isinstance(raw, str):
|
|
138
|
+
value_type = getattr(meta, "value_type", None)
|
|
139
|
+
raw = getattr(value_type, "value", value_type)
|
|
140
|
+
kind = raw
|
|
141
|
+
return str(kind).lower() in _DROPDOWN_VALUE_TYPES
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _mark_deleted_options(
|
|
145
|
+
rows: list[dict[str, object]],
|
|
146
|
+
field_id: str,
|
|
147
|
+
*,
|
|
148
|
+
meta: FieldMetadata | None,
|
|
149
|
+
ctx: CLIContext,
|
|
150
|
+
warnings: list[str],
|
|
151
|
+
) -> None:
|
|
152
|
+
"""In a dropdown's history, V1 sends an option deleted since as its bare text ("Reach Out")
|
|
153
|
+
and a live one as {id, text, rank, color}. Give the deleted ones the same shape:
|
|
154
|
+
{"id": null, "text": "Reach Out", "deleted": true}, so every value has a .text.
|
|
155
|
+
|
|
156
|
+
``meta`` is the field's metadata when the caller has it (V2 list fields); otherwise V1
|
|
157
|
+
field metadata is read, only when some value is a bare string.
|
|
158
|
+
"""
|
|
159
|
+
|
|
160
|
+
def is_text(value: object) -> bool:
|
|
161
|
+
return isinstance(value, str) or (
|
|
162
|
+
isinstance(value, list) and any(isinstance(v, str) for v in value)
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
if not any(is_text(row.get("value")) for row in rows):
|
|
166
|
+
return
|
|
167
|
+
if meta is None:
|
|
168
|
+
try:
|
|
169
|
+
metas = ctx.get_client(warnings=warnings).fields.list()
|
|
170
|
+
except Exception: # the history itself was read: don't fail it over its labels
|
|
171
|
+
metas = []
|
|
172
|
+
meta = next((m for m in metas if _same_field(m.id, field_id)), None)
|
|
173
|
+
if meta is None:
|
|
174
|
+
warnings.append(
|
|
175
|
+
f"Could not read {field_id}'s type, so text values are shown as sent; in a dropdown "
|
|
176
|
+
"they are options deleted since."
|
|
177
|
+
)
|
|
178
|
+
return
|
|
179
|
+
if not _is_dropdown(meta):
|
|
180
|
+
return
|
|
181
|
+
|
|
182
|
+
def deleted(value: object) -> object:
|
|
183
|
+
if isinstance(value, str):
|
|
184
|
+
return {"id": None, "text": value, "deleted": True}
|
|
185
|
+
return value
|
|
186
|
+
|
|
187
|
+
for row in rows:
|
|
188
|
+
value = row.get("value")
|
|
189
|
+
if isinstance(value, list):
|
|
190
|
+
row["value"] = [deleted(v) for v in value]
|
|
191
|
+
else:
|
|
192
|
+
row["value"] = deleted(value)
|
|
193
|
+
|
|
194
|
+
|
|
126
195
|
def _validate_history_selector(
|
|
127
196
|
person_id: int | None,
|
|
128
197
|
company_id: int | None,
|
|
@@ -470,6 +539,7 @@ def field_history(
|
|
|
470
539
|
_refuse_if_global(ctx, warnings, field_id, "--list-entry-id")
|
|
471
540
|
|
|
472
541
|
payload = [_field_value_change_payload(item) for item in changes]
|
|
542
|
+
_mark_deleted_options(payload, field_id, meta=None, ctx=ctx, warnings=warnings)
|
|
473
543
|
|
|
474
544
|
# Build CommandContext for richer output metadata
|
|
475
545
|
# Per spec: required params are inputs, optional params are modifiers
|
|
@@ -1297,6 +1367,7 @@ def field_history_bulk(
|
|
|
1297
1367
|
# What kind of field: a list field's changes belong to list entries, a global field's to
|
|
1298
1368
|
# the company/person (they carry no list entry, so per-entry reads find none).
|
|
1299
1369
|
field_kind: str | None = None
|
|
1370
|
+
field_meta: FieldMetadata | None = None # V2 metadata, when the list's fields were read
|
|
1300
1371
|
if list_id is not None:
|
|
1301
1372
|
try:
|
|
1302
1373
|
list_fields: list[FieldMetadata] | None = client.lists.get_fields(
|
|
@@ -1332,6 +1403,7 @@ def field_history_bulk(
|
|
|
1332
1403
|
exit_code=2,
|
|
1333
1404
|
)
|
|
1334
1405
|
field_kind = kind
|
|
1406
|
+
field_meta = match
|
|
1335
1407
|
|
|
1336
1408
|
# Global field: one read per company/person, labelled with its entry on the list
|
|
1337
1409
|
entity_entry: dict[int, int] = {} # entity id -> the first entry of it on the list
|
|
@@ -1649,6 +1721,7 @@ def field_history_bulk(
|
|
|
1649
1721
|
partial = failed_count > 0
|
|
1650
1722
|
if list_entry_ids is not None and not all_changes and not async_warnings:
|
|
1651
1723
|
_refuse_if_global(ctx, warnings, field_id, "--list-entry-ids")
|
|
1724
|
+
_mark_deleted_options(all_changes, field_id, meta=field_meta, ctx=ctx, warnings=warnings)
|
|
1652
1725
|
all_changes.sort(
|
|
1653
1726
|
key=lambda r: (str(r.get("changedAt") or ""), str(r.get("id") or "").zfill(20))
|
|
1654
1727
|
)
|
|
@@ -827,12 +827,19 @@ def list_export(
|
|
|
827
827
|
|
|
828
828
|
# --filter: Affinity's search applies what it can; the whole filter still runs locally
|
|
829
829
|
list_search: ListSearch | None = None
|
|
830
|
+
# meta.serverFilter: what Affinity's search applied, what ran locally, and why not
|
|
831
|
+
server_filter: dict[str, Any] | None = None
|
|
830
832
|
if filter_expr and not saved_view:
|
|
831
833
|
if os.environ.get("XAFFINITY_QUERY_SERVER_FILTER", "1") != "0":
|
|
832
834
|
try:
|
|
833
835
|
list_search = plan_list_search(client, list_id, filter_expr)
|
|
834
836
|
except (AuthorizationError, NotFoundError, SDKValidationError) as e:
|
|
835
837
|
warnings.append(f"Filtering locally: could not read the list's fields ({e}).")
|
|
838
|
+
server_filter = {"fallback": f"could not read the list's fields ({e})"}
|
|
839
|
+
else:
|
|
840
|
+
server_filter = {"pushed": list_search.pushed, "local": list_search.local}
|
|
841
|
+
else:
|
|
842
|
+
server_filter = {"fallback": "XAFFINITY_QUERY_SERVER_FILTER=0"}
|
|
836
843
|
# Without a scope flag a locally filtered export would silently return only what
|
|
837
844
|
# matched on the first page. When Affinity applies the whole filter, page one is
|
|
838
845
|
# the first page of matches, so no flag is needed.
|
|
@@ -1018,6 +1025,8 @@ def list_export(
|
|
|
1018
1025
|
"cursor": cursor,
|
|
1019
1026
|
"csv": want_csv,
|
|
1020
1027
|
}
|
|
1028
|
+
if server_filter is not None:
|
|
1029
|
+
data["serverFilter"] = server_filter
|
|
1021
1030
|
if want_expand:
|
|
1022
1031
|
# Estimate API calls for expansion (get_size uses V1 API for accurate values)
|
|
1023
1032
|
entry_count = client.lists.get_size(list_id)
|
|
@@ -1903,6 +1912,8 @@ def list_export(
|
|
|
1903
1912
|
from ..field_utils import truncation_warnings
|
|
1904
1913
|
|
|
1905
1914
|
warnings.extend(table_iter_state.get("warnings", []))
|
|
1915
|
+
if server_filter is not None and table_iter_state.get("searchFallback"):
|
|
1916
|
+
server_filter["fallback"] = table_iter_state["searchFallback"]
|
|
1906
1917
|
warnings.extend(
|
|
1907
1918
|
truncation_warnings(
|
|
1908
1919
|
table_iter_state.get("truncatedFields", []), filtered=bool(filter_expr)
|
|
@@ -1972,6 +1983,7 @@ def list_export(
|
|
|
1972
1983
|
# to truncation, so mark truncated=True whenever the flag is set.
|
|
1973
1984
|
truncated=True if first_page_only else None,
|
|
1974
1985
|
truncation_reason="firstPageOnly" if first_page_only else None,
|
|
1986
|
+
server_filter=server_filter,
|
|
1975
1987
|
)
|
|
1976
1988
|
raise AssertionError("unreachable")
|
|
1977
1989
|
|
|
@@ -2192,6 +2204,7 @@ def _iterate_list_entries(
|
|
|
2192
2204
|
state.setdefault("warnings", []).append(
|
|
2193
2205
|
f"Affinity's search refused the filter, filtering locally: {e}"
|
|
2194
2206
|
)
|
|
2207
|
+
state["searchFallback"] = getattr(e, "message", None) or str(e)
|
|
2195
2208
|
else:
|
|
2196
2209
|
yield from _search_rows(
|
|
2197
2210
|
entries,
|
|
@@ -15,7 +15,7 @@ from rich.progress import BarColumn, Progress, SpinnerColumn, TaskID, TextColumn
|
|
|
15
15
|
|
|
16
16
|
from affinity.exceptions import DuplicateEntityError
|
|
17
17
|
from affinity.models.entities import Person, PersonCreate, PersonUpdate
|
|
18
|
-
from affinity.models.types import FieldId
|
|
18
|
+
from affinity.models.types import EntityType, FieldId
|
|
19
19
|
from affinity.types import CompanyId, FieldType, ListId, PersonId
|
|
20
20
|
|
|
21
21
|
from ..click_compat import RichCommand, RichGroup, click
|
|
@@ -308,6 +308,7 @@ def person_ls(
|
|
|
308
308
|
|
|
309
309
|
# --filter (or a cursor from a filtered run): Affinity's search filters on its side
|
|
310
310
|
if filter_expr is not None or is_filter_cursor(cursor):
|
|
311
|
+
server_filter: dict[str, Any] = {}
|
|
311
312
|
found, next_token = filtered_ls(
|
|
312
313
|
client.persons,
|
|
313
314
|
entity="person",
|
|
@@ -320,6 +321,7 @@ def person_ls(
|
|
|
320
321
|
max_results=max_results,
|
|
321
322
|
all_pages=all_pages,
|
|
322
323
|
warnings=warnings,
|
|
324
|
+
server_filter=server_filter,
|
|
323
325
|
)
|
|
324
326
|
return CommandOutput(
|
|
325
327
|
data={"persons": found},
|
|
@@ -329,6 +331,7 @@ def person_ls(
|
|
|
329
331
|
if next_token
|
|
330
332
|
else None
|
|
331
333
|
),
|
|
334
|
+
server_filter=server_filter or None,
|
|
332
335
|
api_called=True,
|
|
333
336
|
)
|
|
334
337
|
|
|
@@ -1190,6 +1193,14 @@ def person_get(
|
|
|
1190
1193
|
pagination=pagination,
|
|
1191
1194
|
keep_item=keep_entry if list_id is not None else None,
|
|
1192
1195
|
)
|
|
1196
|
+
# The endpoint doesn't name the entity: label each entry with this person, as
|
|
1197
|
+
# persons.get_list_entries() (and company get) do
|
|
1198
|
+
for entry in entries_items:
|
|
1199
|
+
if isinstance(entry, dict):
|
|
1200
|
+
if entry.get("entityId") is None:
|
|
1201
|
+
entry["entityId"] = int(person_id)
|
|
1202
|
+
if entry.get("entityType") is None:
|
|
1203
|
+
entry["entityType"] = int(EntityType.PERSON)
|
|
1193
1204
|
data["listEntries"] = entries_items
|
|
1194
1205
|
|
|
1195
1206
|
if "list-entries" in expand_set and entries_items and ctx.output != "json":
|
|
@@ -995,6 +995,7 @@ def build_result(
|
|
|
995
995
|
truncation_reason: str | None = None,
|
|
996
996
|
not_requested: list[dict[str, str]] | None = None,
|
|
997
997
|
explanation: str | None = None,
|
|
998
|
+
server_filter: dict[str, Any] | None = None,
|
|
998
999
|
affinity_api_version: str | list[str] | None = None,
|
|
999
1000
|
affinity_api_version_per_operation: list[str] | None = None,
|
|
1000
1001
|
) -> CommandResult:
|
|
@@ -1013,6 +1014,7 @@ def build_result(
|
|
|
1013
1014
|
truncation_reason=truncation_reason,
|
|
1014
1015
|
not_requested=not_requested,
|
|
1015
1016
|
explanation=explanation,
|
|
1017
|
+
server_filter=server_filter,
|
|
1016
1018
|
)
|
|
1017
1019
|
return CommandResult(
|
|
1018
1020
|
ok=ok,
|
|
@@ -172,9 +172,11 @@ def filtered_ls(
|
|
|
172
172
|
max_results: int | None,
|
|
173
173
|
all_pages: bool,
|
|
174
174
|
warnings: list[str],
|
|
175
|
+
server_filter: dict[str, Any] | None = None,
|
|
175
176
|
) -> tuple[list[dict[str, Any]], str | None]:
|
|
176
177
|
"""``company ls`` / ``person ls`` with ``--filter`` (or a search ``--cursor``): rows and the
|
|
177
|
-
next cursor. Raises ``CLIError`` for a filter Affinity's search can't apply at all.
|
|
178
|
+
next cursor. Raises ``CLIError`` for a filter Affinity's search can't apply at all.
|
|
179
|
+
``server_filter`` (when given) receives the split: ``pushed`` and ``local`` conditions."""
|
|
178
180
|
from affinity.filters import parse as parse_filter
|
|
179
181
|
|
|
180
182
|
from .errors import CLIError
|
|
@@ -241,6 +243,8 @@ def filtered_ls(
|
|
|
241
243
|
hint="details.local names the conditions Affinity's search can't apply.",
|
|
242
244
|
details=details,
|
|
243
245
|
)
|
|
246
|
+
if server_filter is not None:
|
|
247
|
+
server_filter.update(pushed=plan.pushed, local=plan.local)
|
|
244
248
|
warnings.extend(plan.caveats)
|
|
245
249
|
if plan.local:
|
|
246
250
|
warnings.append(
|
|
@@ -303,6 +303,10 @@ class CommandMeta(AffinityModel):
|
|
|
303
303
|
not_requested: list[dict[str, str]] | None = Field(None, alias="notRequested")
|
|
304
304
|
# Server-provided explanation of how a query was interpreted (semantic search).
|
|
305
305
|
explanation: str | None = None
|
|
306
|
+
# How a --filter was split: {"pushed": [...], "local": [...]} — what Affinity's search
|
|
307
|
+
# applied and what was checked locally — plus "fallback" (why) when the search was refused or
|
|
308
|
+
# turned off: then the whole filter ran locally (and pushed/local may be absent).
|
|
309
|
+
server_filter: dict[str, Any] | None = Field(None, alias="serverFilter")
|
|
306
310
|
# Affinity V2 API version(s) that answered this command (echoed X-Affinity-Api-Version,
|
|
307
311
|
# incl. cache hits): a string, or a sorted list when more than one answered.
|
|
308
312
|
affinity_api_version: str | list[str] | None = Field(None, alias="affinityApiVersion")
|
|
@@ -38,6 +38,7 @@ class CommandOutput:
|
|
|
38
38
|
# [{"key": "data.listEntries", "flag": "--expand list-entries"}, ...]
|
|
39
39
|
not_requested: list[dict[str, str]] | None = None
|
|
40
40
|
explanation: str | None = None # meta.explanation (semantic search)
|
|
41
|
+
server_filter: dict[str, Any] | None = None # meta.serverFilter (--filter split)
|
|
41
42
|
api_called: bool = False
|
|
42
43
|
exit_code: int = 0 # Allow commands to specify non-zero exit codes (e.g., check-key)
|
|
43
44
|
|
|
@@ -52,6 +53,7 @@ def _emit_json(result: CommandResult) -> None:
|
|
|
52
53
|
"truncationReason",
|
|
53
54
|
"notRequested",
|
|
54
55
|
"explanation",
|
|
56
|
+
"serverFilter",
|
|
55
57
|
"affinityApiVersion",
|
|
56
58
|
"affinityApiVersionPerOperation",
|
|
57
59
|
):
|
|
@@ -239,6 +241,7 @@ def run_command(ctx: CLIContext, *, command: str, fn: CommandFn) -> None:
|
|
|
239
241
|
truncation_reason=out.truncation_reason,
|
|
240
242
|
not_requested=out.not_requested,
|
|
241
243
|
explanation=out.explanation,
|
|
244
|
+
server_filter=out.server_filter,
|
|
242
245
|
affinity_api_version=api_version,
|
|
243
246
|
affinity_api_version_per_operation=ctx.api_versions_per_operation(),
|
|
244
247
|
)
|
|
@@ -737,7 +737,10 @@ class ListEntry(AffinityModel):
|
|
|
737
737
|
"""
|
|
738
738
|
A row in a list, linking an entity to a list.
|
|
739
739
|
|
|
740
|
-
|
|
740
|
+
Holds the list-specific field values and which entity the row is for (``entity_id``,
|
|
741
|
+
``entity_type``). ``entity`` (a summary of that entity) is filled only where the endpoint
|
|
742
|
+
embeds it, e.g. a list's entries; it is ``None`` from ``companies.get_list_entries()`` and
|
|
743
|
+
``persons.get_list_entries()``.
|
|
741
744
|
"""
|
|
742
745
|
|
|
743
746
|
id: ListEntryId
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""``batch_get`` with interaction dates and field filters, in fewer calls.
|
|
2
|
+
|
|
3
|
+
``get(id, with_interaction_dates=True, field_ids=...|field_types=...)`` makes two calls per id: V1
|
|
4
|
+
``/organizations|persons/{id}`` for the dates and V2 ``/companies|persons/{id}`` for the fields.
|
|
5
|
+
For many ids the V2 half goes as one ``/companies|persons?ids=...`` call per 100 ids instead, and
|
|
6
|
+
each record is merged exactly as ``get`` merges it.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import asyncio
|
|
12
|
+
from collections.abc import Awaitable, Callable, Sequence
|
|
13
|
+
from typing import Any, Literal, TypeVar
|
|
14
|
+
|
|
15
|
+
from ..exceptions import AffinityError, NotFoundError
|
|
16
|
+
|
|
17
|
+
IdT = TypeVar("IdT", bound=int)
|
|
18
|
+
|
|
19
|
+
V2_IDS_PER_CALL = 100 # V2 list endpoints return at most 100 records per page
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
async def batch_get_with_dates(
|
|
23
|
+
client: Any,
|
|
24
|
+
ids: Sequence[IdT],
|
|
25
|
+
*,
|
|
26
|
+
v1_path: str,
|
|
27
|
+
v2_path: str,
|
|
28
|
+
kind: str,
|
|
29
|
+
v1_params: dict[str, Any],
|
|
30
|
+
v2_params: dict[str, Any],
|
|
31
|
+
max_concurrent: int,
|
|
32
|
+
on_error: Literal["raise", "skip"],
|
|
33
|
+
get_one: Callable[[IdT], Awaitable[Any]],
|
|
34
|
+
build: Callable[[dict[str, Any]], Any],
|
|
35
|
+
) -> dict[IdT, Any]:
|
|
36
|
+
"""Records for ``ids`` (unique, in order): the V2 fields of each merged with its V1
|
|
37
|
+
interaction dates and interactions. ``get_one`` (the plain per-id ``get``) re-reads the ids
|
|
38
|
+
of a V2 call that failed under ``on_error="skip"``, so one bad id doesn't drop 99 others.
|
|
39
|
+
"""
|
|
40
|
+
fields_by_id: dict[int, dict[str, Any]] = {}
|
|
41
|
+
retry_one_by_one: set[int] = set()
|
|
42
|
+
for start in range(0, len(ids), V2_IDS_PER_CALL):
|
|
43
|
+
chunk = list(ids[start : start + V2_IDS_PER_CALL])
|
|
44
|
+
try:
|
|
45
|
+
data = await client.get(
|
|
46
|
+
v2_path,
|
|
47
|
+
params={**v2_params, "ids": [int(i) for i in chunk], "limit": V2_IDS_PER_CALL},
|
|
48
|
+
)
|
|
49
|
+
while True:
|
|
50
|
+
for item in data.get("data", []):
|
|
51
|
+
fields_by_id[int(item["id"])] = item
|
|
52
|
+
next_url = (data.get("pagination") or {}).get("nextUrl")
|
|
53
|
+
if not next_url:
|
|
54
|
+
break
|
|
55
|
+
data = await client.get_url(next_url)
|
|
56
|
+
except AffinityError:
|
|
57
|
+
if on_error == "raise":
|
|
58
|
+
raise
|
|
59
|
+
retry_one_by_one.update(int(i) for i in chunk)
|
|
60
|
+
|
|
61
|
+
async def dates_of(record_id: IdT) -> tuple[IdT, Any | None]:
|
|
62
|
+
try:
|
|
63
|
+
if int(record_id) in retry_one_by_one:
|
|
64
|
+
return record_id, await get_one(record_id)
|
|
65
|
+
fields = fields_by_id.get(int(record_id))
|
|
66
|
+
if fields is None:
|
|
67
|
+
raise NotFoundError(f"{kind} {int(record_id)} not found", status_code=404)
|
|
68
|
+
dates = await client.get(f"{v1_path}/{int(record_id)}", params=v1_params, v1=True)
|
|
69
|
+
merged = dict(fields)
|
|
70
|
+
merged["interaction_dates"] = dates.get("interaction_dates")
|
|
71
|
+
merged["interactions"] = dates.get("interactions")
|
|
72
|
+
return record_id, build(merged)
|
|
73
|
+
except AffinityError:
|
|
74
|
+
if on_error == "raise":
|
|
75
|
+
raise
|
|
76
|
+
return record_id, None
|
|
77
|
+
|
|
78
|
+
results: dict[IdT, Any] = {}
|
|
79
|
+
for start in range(0, len(ids), max_concurrent):
|
|
80
|
+
tasks = [asyncio.create_task(dates_of(i)) for i in ids[start : start + max_concurrent]]
|
|
81
|
+
try:
|
|
82
|
+
for done in asyncio.as_completed(tasks):
|
|
83
|
+
record_id, record = await done
|
|
84
|
+
if record is not None:
|
|
85
|
+
results[record_id] = record
|
|
86
|
+
except BaseException:
|
|
87
|
+
for task in tasks:
|
|
88
|
+
if not task.done():
|
|
89
|
+
task.cancel()
|
|
90
|
+
await asyncio.gather(*tasks, return_exceptions=True)
|
|
91
|
+
raise
|
|
92
|
+
return results
|
|
@@ -5,11 +5,14 @@ from __future__ import annotations
|
|
|
5
5
|
from collections.abc import Iterable
|
|
6
6
|
from datetime import datetime
|
|
7
7
|
from typing import Any, TypeVar
|
|
8
|
+
from urllib.parse import urlsplit
|
|
8
9
|
|
|
9
10
|
from pydantic import BaseModel
|
|
10
11
|
|
|
11
12
|
from ..exceptions import AffinityError
|
|
12
|
-
from ..models.
|
|
13
|
+
from ..models.entities import ListEntry
|
|
14
|
+
from ..models.pagination import PaginatedResponse, PaginationInfo, PaginationInfoWithTotal
|
|
15
|
+
from ..models.types import EntityType
|
|
13
16
|
from ._v2_filters import v2_filter_datetime
|
|
14
17
|
|
|
15
18
|
T = TypeVar("T", bound=BaseModel)
|
|
@@ -69,6 +72,39 @@ def check_cursor_alone(cursor: str | None, *others: Any) -> None:
|
|
|
69
72
|
)
|
|
70
73
|
|
|
71
74
|
|
|
75
|
+
def check_list_entries_cursor(cursor: str, path: str) -> None:
|
|
76
|
+
"""A cursor of ``/companies/{id}/list-entries`` (or persons) must be for the entity asked
|
|
77
|
+
about: its entries are labelled with that entity, so another entity's cursor would mislabel
|
|
78
|
+
them."""
|
|
79
|
+
if not urlsplit(cursor).path.endswith(path):
|
|
80
|
+
raise ValueError(
|
|
81
|
+
f"This cursor is not for {path}: pass the cursor with the same entity id that "
|
|
82
|
+
"returned it."
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def entity_list_entries_page(
|
|
87
|
+
data: dict[str, Any], *, entity_id: int, entity_type: EntityType
|
|
88
|
+
) -> PaginatedResponse[ListEntry]:
|
|
89
|
+
"""A page of one entity's list entries (``/companies|persons/{id}/list-entries``).
|
|
90
|
+
|
|
91
|
+
Those items don't name their entity, so ``entity_id`` / ``entity_type`` are filled in from
|
|
92
|
+
the entity asked about (a value the API does send is kept). ``entity`` stays ``None``.
|
|
93
|
+
"""
|
|
94
|
+
items = []
|
|
95
|
+
for raw in data.get("data", []):
|
|
96
|
+
item = dict(raw)
|
|
97
|
+
if item.get("entityId") is None:
|
|
98
|
+
item["entityId"] = int(entity_id)
|
|
99
|
+
if item.get("entityType") is None:
|
|
100
|
+
item["entityType"] = int(entity_type)
|
|
101
|
+
items.append(ListEntry.model_validate(item))
|
|
102
|
+
return PaginatedResponse[ListEntry](
|
|
103
|
+
data=items,
|
|
104
|
+
pagination=PaginationInfo.model_validate(data.get("pagination", {})),
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
|
|
72
108
|
def check_positive_limit(limit: int | None) -> None:
|
|
73
109
|
"""For endpoints without a documented maximum: ``limit`` must still be at least 1."""
|
|
74
110
|
if limit is not None and limit < 1:
|