affinity-sdk 1.29.0__tar.gz → 2.0.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.
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/workflows/ci.yml +3 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/workflows/plugin-build.yml +13 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/CHANGELOG.md +136 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/PKG-INFO +23 -17
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/README.md +22 -16
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/list_cmds.py +6 -1
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/note_cmds.py +148 -29
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/reminder_cmds.py +157 -191
- affinity_sdk-2.0.0/affinity/cli/commands/webhook_cmds.py +365 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/confirm.py +12 -4
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/main.py +2 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/client.py +2 -4
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/inbound_webhooks.py +1 -1
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/models/__init__.py +17 -3
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/models/entities.py +20 -7
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/models/secondary.py +196 -40
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/models/types.py +57 -14
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/__init__.py +4 -4
- affinity_sdk-2.0.0/affinity/services/_note_html.py +165 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/_v2_filters.py +8 -1
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/lists.py +67 -63
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/rate_limits.py +12 -9
- affinity_sdk-2.0.0/affinity/services/reminders.py +715 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/v1_only.py +208 -604
- affinity_sdk-2.0.0/affinity/services/webhooks.py +304 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/types.py +2 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/cli/commands.md +78 -0
- affinity_sdk-2.0.0/docs/public/guides/api-versions-and-routing.md +80 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/errors-and-retries.md +6 -9
- affinity_sdk-2.0.0/docs/public/guides/migrating-to-2.md +90 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/pagination.md +3 -3
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/webhooks.md +45 -8
- affinity_sdk-2.0.0/docs/public/reference/api-coverage.md +190 -0
- affinity_sdk-2.0.0/docs/public/reference/services/reminders.md +5 -0
- affinity_sdk-2.0.0/docs/public/reference/services/v1/files.md +8 -0
- affinity_sdk-2.0.0/docs/public/reference/services/v1/notes.md +6 -0
- affinity_sdk-2.0.0/docs/public/reference/services/webhooks.md +5 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.claude-plugin/plugin.json +1 -1
- affinity_sdk-2.0.0/mcp/.mcp-bash/VERSION +1 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/bin/mcp-bash +11 -1
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/cli/common.sh +4 -10
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/core.sh +118 -8
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/elicitation.sh +3 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/runtime.sh +25 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/timeout.sh +19 -6
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/tools.sh +52 -6
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/tools_policy.sh +48 -2
- affinity_sdk-2.0.0/mcp/.mcp-bash/sdk/tool-error.sh +113 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/sdk/tool-sdk.sh +172 -15
- affinity_sdk-2.0.0/mcp/.mcp-bash/vendor.json +1 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.registry/commands.generated.json +331 -19
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.registry/mcp-commands.json +28 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/CHANGELOG.md +44 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/COMPATIBILITY +9 -2
- affinity_sdk-2.0.0/mcp/VERSION +1 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/mcp-bash.lock +2 -2
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/server.d/policy.sh +4 -5
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/server.d/requirements.json +1 -1
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/server.d/server.meta.json +1 -1
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/test/run.sh +8 -5
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/execute-write-command/tool.meta.json +2 -2
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/execute-write-command/tool.sh +18 -2
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/query/tool.sh +1 -1
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mkdocs.yml +4 -2
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/affinity-sdk/.claude-plugin/plugin.json +1 -1
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/affinity-sdk/.claude-plugin/skills/affinity-python-sdk/SKILL.md +1 -1
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/affinity-sdk/.claude-plugin/skills/affinity-python-sdk/references/services.md +4 -1
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/xaffinity-cli/.claude-plugin/plugin.json +2 -16
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/xaffinity-cli/hooks/guard-env-read.sh +2 -2
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/xaffinity-cli/hooks/pre-xaffinity.sh +9 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/xaffinity-cli/hooks/session-setup.sh +8 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/xaffinity-cli/skills/xaffinity-cli-usage/SKILL.md +6 -1
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/xaffinity-cli/skills/xaffinity-cli-usage/references/setup.md +15 -5
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/pyproject.toml +1 -1
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/README.md +2 -0
- affinity_sdk-2.0.0/tests/cowork/cassettes/company-lists-status.cassette.json +410 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/cassettes/hook-blocks-without-key.cassette.json +66 -66
- affinity_sdk-2.0.0/tests/cowork/cassettes/no-key-skill-path.cassette.json +395 -0
- affinity_sdk-2.0.0/tests/cowork/cassettes/status-history.cassette.json +469 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/scenarios/no-key-skill-path.yaml +3 -2
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/integration/test_sdk_reads.py +8 -10
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/integration/test_sdk_writes.py +44 -69
- affinity_sdk-2.0.0/tests/test_api_coverage.py +162 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_csv_export.py +10 -10
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_date_params.py +17 -14
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_field_options_and_transcripts.py +1 -1
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_list_cmds_coverage.py +13 -13
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_list_expand_interactions.py +6 -6
- affinity_sdk-2.0.0/tests/test_cli_notes_writes.py +181 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_opportunity_cmds.py +1 -1
- affinity_sdk-2.0.0/tests/test_cli_plugin_manifest.py +23 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_pre_xaffinity_hook.py +51 -0
- affinity_sdk-2.0.0/tests/test_cli_reminders.py +253 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_session_setup_hook.py +38 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_set_phase_atomicity.py +50 -9
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_v1_only_cmds.py +0 -195
- affinity_sdk-2.0.0/tests/test_cli_webhooks.py +212 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_write_ops.py +2 -2
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_client.py +2 -2
- affinity_sdk-2.0.0/tests/test_files_v2.py +111 -0
- affinity_sdk-2.0.0/tests/test_lists_v2_writes.py +144 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_mcp_cli_version_check.py +29 -0
- affinity_sdk-2.0.0/tests/test_mcp_query_cli_error.py +75 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_models.py +1 -1
- affinity_sdk-2.0.0/tests/test_notes_v2_writes.py +300 -0
- affinity_sdk-2.0.0/tests/test_rate_limit_v2.py +78 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_readonly_factory.py +3 -2
- affinity_sdk-2.0.0/tests/test_reminder_list_batch.py +136 -0
- affinity_sdk-2.0.0/tests/test_reminders_v2.py +541 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_requirements_additional.py +4 -3
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_lists_additional_coverage.py +22 -10
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_rate_limits_coverage_gaps.py +18 -23
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_v1_only_async.py +3 -119
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_transport_and_readonly_mode.py +3 -2
- affinity_sdk-2.0.0/tests/test_v1_association_parsing.py +28 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_v1_only_services_additional_coverage.py +3 -63
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_v1_only_services_more_coverage.py +0 -133
- affinity_sdk-2.0.0/tests/test_v2_request_bodies.py +271 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_validate_openapi_tool.py +33 -0
- affinity_sdk-2.0.0/tests/test_webhooks_v2.py +232 -0
- affinity_sdk-2.0.0/tools/api_coverage.json +1155 -0
- affinity_sdk-2.0.0/tools/api_coverage.py +238 -0
- affinity_sdk-2.0.0/tools/api_coverage_v1_snapshot.json +68 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tools/validate_openapi_models.py +37 -4
- affinity_sdk-1.29.0/docs/public/guides/api-versions-and-routing.md +0 -52
- affinity_sdk-1.29.0/docs/public/reference/services/v1/files.md +0 -3
- affinity_sdk-1.29.0/docs/public/reference/services/v1/notes.md +0 -3
- affinity_sdk-1.29.0/docs/public/reference/services/v1/reminders.md +0 -3
- affinity_sdk-1.29.0/docs/public/reference/services/v1/webhooks.md +0 -3
- affinity_sdk-1.29.0/mcp/.mcp-bash/VERSION +0 -1
- affinity_sdk-1.29.0/mcp/.mcp-bash/vendor.json +0 -1
- affinity_sdk-1.29.0/mcp/VERSION +0 -1
- affinity_sdk-1.29.0/tests/cowork/cassettes/company-lists-status.cassette.json +0 -410
- affinity_sdk-1.29.0/tests/cowork/cassettes/no-key-skill-path.cassette.json +0 -417
- affinity_sdk-1.29.0/tests/cowork/cassettes/status-history.cassette.json +0 -433
- affinity_sdk-1.29.0/tests/test_reminder_list_batch.py +0 -184
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.claude-plugin/marketplace.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.cursor/rules/test-data-privacy.mdc +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.editorconfig +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.env.example +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.gitattributes +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/CODEOWNERS +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/PULL_REQUEST_TEMPLATE/cli_command.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/PULL_REQUEST_TEMPLATE/release.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/dependabot.yml +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/labels.yml +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/mcp-release-install-footer.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/pull_request_template.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/release-install-footer.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/workflows/cowork-replay.yml +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/workflows/docs.yml +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/workflows/labels.yml +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/workflows/linkcheck.yml +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/workflows/openapi-validation.yml +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/workflows/plugin-release.yml +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/workflows/release-detect.yml +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/workflows/release.yml +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/workflows/version-check.yml +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.gitignore +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.pre-commit-config.yaml +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/AGENTS.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/CODE_OF_CONDUCT.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/CONTRIBUTING.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/LICENSE +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/SECURITY.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/VERSIONING.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/__init__.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/_internal/__init__.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/_internal/keyfile.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/api_versions.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/__init__.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/__main__.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/_update_worker.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/click_compat.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/__init__.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/_entity_field.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/_entity_files_dump.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/_entity_files_read.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/_entity_files_upload.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/_list_entry_fields.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/_org_reads.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/_search_common.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/_v1_parsing.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/company_cmds.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/completion_cmd.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/config_cmds.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/entry_cmds.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/field_cmds.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/file_cmds.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/file_url_cmd.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/interaction_cmds.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/opportunity_cmds.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/org_read_cmds.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/person_cmds.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/query_cmd.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/relationship_strength_cmds.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/resolve_url_cmd.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/session_cmds.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/task_cmds.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/transcript_cmds.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/version_cmd.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/whoami_cmd.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/config.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/constants.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/context.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/csv_utils.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/date_utils.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/decorators.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/errors.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/field_utils.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/formatters.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/help_json.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/interaction_utils.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/logging.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/mcp_limits.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/options.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/paths.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/progress.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/query/__init__.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/query/aggregates.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/query/cursor.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/query/dates.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/query/exceptions.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/query/executor.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/query/filters.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/query/models.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/query/output.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/query/parser.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/query/planner.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/query/progress.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/query/schema.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/render.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/resolve.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/resolvers.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/results.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/runner.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/serialization.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/session_cache.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/types.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/update_check.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/clients/__init__.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/clients/http.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/clients/pipeline.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/compare.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/downloads.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/exceptions.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/field_resolve_utils.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/field_resolver.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/filters.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/hooks.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/models/interactions_v2.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/models/pagination.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/models/rate_limit_snapshot.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/models/relationships_v2.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/models/search.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/models/transcripts.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/policies.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/progress.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/py.typed +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/_dropdown_options.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/_field_listing.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/_field_updates.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/_org_reads.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/companies.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/opportunities.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/persons.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/search.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/tasks.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/transcripts.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/codecov.yml +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/cli-development-guide.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/ai-integrations/index.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/changelog.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/cli/index.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/cli/scripting.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/cli-reference.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/examples.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/getting-started.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/glossary.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/affinity-official-mcp-comparison.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/api-versions.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/authentication.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/claude-code-plugins.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/configuration.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/csv-export.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/datetime-handling.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/debugging-hooks.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/field-types-and-values.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/field-values.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/filtering.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/ids-and-types.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/models.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/opportunity-associations.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/performance.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/query-command.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/rate-limits.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/sync-vs-async.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/index.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/mcp/index.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/client.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/exceptions.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/filters.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/models.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/query-language.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/services/companies.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/services/lists.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/services/opportunities.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/services/persons.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/services/tasks.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/services/v1/auth.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/services/v1/field-values.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/services/v1/fields.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/services/v1/interactions.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/services/v1/relationships.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/types.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/troubleshooting.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/examples/advanced_usage.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/examples/async_lifecycle.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/examples/basic_usage.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/examples/filter_builder.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/examples/hooks_debugging.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/examples/list_management.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/examples/resolve_helpers.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/examples/task_polling.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.claude-plugin/.gitignore +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.claude-plugin/skills/affinity-mcp-workflows/SKILL.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.claude-plugin/skills/pipeline-history/SKILL.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.claude-plugin/skills/query-language/SKILL.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.claude-plugin/skills/query-language/references/filter-operators.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.claude-plugin/skills/query-language/references/include-expand.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.claude-plugin/skills/query-language/references/output-formats.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.claude-plugin/skills/query-language/references/quantifiers.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.claude-plugin/xaffinity-mcp.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.gitignore +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/handlers/completion.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/handlers/lifecycle.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/handlers/logging.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/handlers/ping.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/handlers/prompts.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/handlers/resources.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/handlers/roots.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/handlers/tools.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/auth.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/capabilities.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/cli/health.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/completion.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/file_read.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/handler_helpers.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/hash.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/ids.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/io.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/json.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/lock.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/logging.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/meta_env.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/paginate.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/path.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/policy.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/progress-passthrough.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/progress.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/prompts.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/registry.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/require.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/resource_content.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/resource_match.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/resource_providers.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/resources.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/roots.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/rpc.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/spec.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/ui-templates.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/ui.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/uri.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/validate.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/providers/echo.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/providers/file.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/providers/git.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/providers/https.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/providers/ui.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/sdk/ui-sdk.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.registry/prompts.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.registry/resource-templates.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.registry/resources.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.registry/ui-resources.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/Makefile +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/README.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/completions/entity-name.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/completions/list-name.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/completions/status-value.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/docs/DEBUGGING.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/icon.svg +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/lib/cache.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/lib/cli-detect.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/lib/cli-gateway.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/lib/common.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/lib/entity-types.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/lib/field-resolution.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/mcp-publisher.lock +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/mcpb.conf +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/change-status/change-status.completion.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/change-status/change-status.meta.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/change-status/change-status.txt +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/interaction-brief/interaction-brief.meta.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/interaction-brief/interaction-brief.txt +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/log-call/log-call.meta.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/log-call/log-call.txt +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/log-interaction-and-update-workflow/log-interaction-and-update-workflow.meta.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/log-interaction-and-update-workflow/log-interaction-and-update-workflow.txt +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/log-message/log-message.meta.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/log-message/log-message.txt +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/pipeline-review/pipeline-review.completion.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/pipeline-review/pipeline-review.meta.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/pipeline-review/pipeline-review.txt +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/prepare-briefing/prepare-briefing.meta.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/prepare-briefing/prepare-briefing.txt +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/warm-intro/warm-intro.meta.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/warm-intro/warm-intro.txt +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/providers/xaffinity.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/data-model/data-model.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/data-model/data-model.meta.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/field-catalogs/field-catalogs.meta.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/field-catalogs/field-catalogs.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/interaction-enums/interaction-enums.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/interaction-enums/interaction-enums.meta.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/me/me.meta.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/me/me.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/me-person-id/me-person-id.meta.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/me-person-id/me-person-id.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/query-guide/query-guide.meta.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/query-guide/query-guide.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/saved-views/saved-views.meta.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/saved-views/saved-views.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/workflow-config/workflow-config.meta.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/workflow-config/workflow-config.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/workflows-guide/workflows-guide.meta.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/workflows-guide/workflows-guide.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/xaffinity-field-catalogs.completion.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/xaffinity-saved-views.completion.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/xaffinity-workflow-config.completion.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/server.d/env.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/server.d/health-checks.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/server.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/test/README.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/test/test_env_update_check.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/test-progress.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/discover-commands/tool.meta.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/discover-commands/tool.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/execute-read-command/tool.meta.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/execute-read-command/tool.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/get-entity-dossier/tool.meta.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/get-entity-dossier/tool.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/get-file-url/tool.meta.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/get-file-url/tool.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/query/tool.meta.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/read-xaffinity-resource/tool.meta.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/read-xaffinity-resource/tool.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/user-config.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/xaffinity-mcp-env.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/xaffinity-mcp.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/xaffinity-cli/hooks/hooks.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/xaffinity-cli/skills/xaffinity-cli-usage/references/files-and-writes.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/xaffinity-cli/skills/xaffinity-cli-usage/references/filtering.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/xaffinity-cli/skills/xaffinity-cli-usage/references/history-and-activity.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/xaffinity-cli/skills/xaffinity-cli-usage/references/interactions.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/xaffinity-cli/skills/xaffinity-cli-usage/references/query-guide.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cli/query/test_cursor.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cli/test_company_create_dedup.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cli/test_company_ls_filter_rejection.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cli/test_formatters.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cli/test_output_formats_integration.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cli/test_person_create_dedup.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cli/test_person_ls_filter_rejection.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cli/test_query_filter_rejection.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cli/test_query_list_entry_relationships.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cli/test_query_list_export_parity.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cli/test_query_output_flattening.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cli/test_query_output_truncation.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cli/test_query_unreplied.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/conftest.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/.cowork-redact.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/fixtures/workdir-key/README.txt +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/fixtures/workdir-key/xaffinity-test-key +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/fixtures/workdir-nokey/README.txt +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/image/Dockerfile +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/image/fakeaff/build_fixtures.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/image/fakeaff/fixtures.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/image/fakeaff/server.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/image/xaffinity-wrapper.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/privacy-allow.txt +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/record.sh +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/scenarios/company-lists-status.yaml +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/scenarios/hook-blocks-without-key.yaml +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/scenarios/status-history.yaml +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/sessions/no-key.yaml +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/sessions/with-key.yaml +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/field_write_mocks.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/fixtures/openapi/mini_openapi.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/fixtures/webhooks/field_value_updated.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/fixtures/webhooks/list_entry_created.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/fixtures/webhooks/organization_created.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/fixtures/webhooks/organization_merged.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/fixtures/webhooks/person_created.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/fixtures/webhooks/unknown_event.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/integration/README.md +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/integration/conftest.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/integration/setup_query_parity_data.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/integration/test_cli_writes.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/integration/test_query_parity_integration.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/integration/test_sdk_writes_runner.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/mcp/__init__.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/mcp/test_query_cursor.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/skill-evals/xaffinity-cli-usage-evals/evals.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/spec_guard.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_affinity_client_wrapper_additional_coverage.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_api_key_file_formats.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_api_key_resolution.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_api_version.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_api_version_per_operation.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_async_file_download_streaming.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_batch_get.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_api_version.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_column_limiting.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_command_context.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_company_cmds_coverage.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_company_get.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_config_cmds.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_context_coverage.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_date_utils.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_datetime_formatting.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_datetime_header_offsets.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_domain_linkification.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_dotenv_resolution.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_dropdown_field_writes.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_enriched_field_writes.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_entity_field_writes.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_entity_files_dump.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_entry_field.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_entry_field_batch_writes.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_entry_field_multi_value_limits.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_error_hints.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_error_rendering.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_field_history.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_field_history_bulk.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_field_utils.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_field_utils_coverage.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_field_utils_set_phase.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_field_value_humanization.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_file_url.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_files_ls.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_files_read.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_get_interaction_dates.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_help_json.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_interaction_date_chunking.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_interaction_utils.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_json_safety.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_list_export_entity_scope.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_list_export_field_refresh.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_list_export_filter_safety.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_list_export_truncation_meta.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_missing_coverage.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_multi_value_truncation_warnings.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_no_network_commands.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_opportunity_cmds_coverage.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_pager_logic.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_person_cmds_coverage.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_person_get.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_progress_manager.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_query_aggregates.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_query_cmd.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_query_cmd_coverage.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_query_dates.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_query_executor.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_query_expand_interactions.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_query_filters.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_query_integration.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_query_parser.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_query_planner.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_query_safety.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_query_schema.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_rate_limit_rendering.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_rate_limit_throttle.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_render_coverage.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_resolve_coverage.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_resolve_url_parsing.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_result_summary.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_safe_field_writes.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_search.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_serialization.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_session_cache.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_types.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_unreplied.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_update_check.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_v1_parsing.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_companies_create_dedup.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_companies_filter_rejection.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_compare.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_env_helpers.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_exceptions_coverage.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_field_resolver.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_field_service_caching.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_field_types_c4.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_field_value_type.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_field_values_get_value.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_file_batch_get.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_file_download_streaming.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_file_list_batch.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_file_upload_helpers_and_validation.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_files_upload_returning_files.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_filters.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_generate_mcp_command_registry.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_get_fields_filter_includes.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_get_fields_pagination.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_get_first.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_hidden_field_values.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_hooks.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_http_client_additional_coverage.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_http_client_remaining_coverage.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_inbound_webhooks.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_integration_smoke.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_interaction_date_validation.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_interactions_and_files_regressions.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_isodatetime.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_list_entry_membership_and_opportunities.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_list_term.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_mcp_bundle_env_and_completions.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_mcp_entity_dossier.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_mcp_gateway_limits.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_mcp_history_bulk_gateway.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_mcp_limits.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_mcp_read_truncation.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_mcp_resource_scripts.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_models_v2_2026_fields.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_multi_value_limits.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_new_features.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_notes_v2.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_opportunities_filter_rejection.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_org_reads.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_pagination_iterators.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_persons_create_dedup.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_persons_filter_rejection.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_public_api.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_raw_pipeline_hook_events.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_sdk_interaction_dates.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_search.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_service_get_parameter_combinations.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_companies_coverage_gaps.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_dropdown_options.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_entity_field_updates.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_field_value_changes.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_list_entries_filter_paths.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_lists_coverage_gaps.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_opportunities_additional_coverage.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_opportunities_coverage_gaps.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_opportunities_tasks_additional_coverage.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_persons_companies_additional_coverage.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_v1_only_coverage_gaps.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_small_modules_coverage.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_spec_guard.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/unit/__init__.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/unit/test_exceptions.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tools/__init__.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tools/check_cli_patterns.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tools/generate_mcp_command_registry.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tools/generate_release_notes.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tools/generate_requirements_mapping.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tools/openapi_snapshots/2024-01-01.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tools/openapi_snapshots/2026-07-15.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tools/openapi_snapshots/2026-09-17.json +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tools/sync_mcp_bundle_env.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tools/sync_mcp_registry.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tools/sync_mcp_version.py +0 -0
- {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tools/validate_mcp_registry_metadata.py +0 -0
|
@@ -224,6 +224,9 @@ jobs:
|
|
|
224
224
|
echo "Skipping traceability mapping (docs/internal not present in repo checkout)."
|
|
225
225
|
fi
|
|
226
226
|
|
|
227
|
+
- name: API coverage ledger matches the pinned specs
|
|
228
|
+
run: python tools/api_coverage.py --check
|
|
229
|
+
|
|
227
230
|
- name: MCP commands registry is valid
|
|
228
231
|
run: |
|
|
229
232
|
# Verify registry file exists and is valid JSON with expected structure
|
|
@@ -40,6 +40,19 @@ jobs:
|
|
|
40
40
|
# Uses the full mcp-bash installed above; the vendored runtime has no validate.
|
|
41
41
|
run: ./mcp/xaffinity-mcp.sh validate
|
|
42
42
|
|
|
43
|
+
- uses: actions/setup-python@v6
|
|
44
|
+
with:
|
|
45
|
+
python-version: '3.12'
|
|
46
|
+
|
|
47
|
+
- name: Install the CLI from this checkout
|
|
48
|
+
run: python -m pip install -e ".[cli]"
|
|
49
|
+
|
|
50
|
+
- name: MCP tool tests (dry runs; no key, API unreachable)
|
|
51
|
+
env:
|
|
52
|
+
AFFINITY_V1_BASE_URL: http://127.0.0.1:9
|
|
53
|
+
AFFINITY_V2_BASE_URL: http://127.0.0.1:9/v2
|
|
54
|
+
run: ./mcp/test/run.sh
|
|
55
|
+
|
|
43
56
|
- name: Build MCP plugin ZIP
|
|
44
57
|
run: make -C mcp plugin
|
|
45
58
|
|
|
@@ -7,6 +7,142 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.0.0] - 2026-10-12
|
|
11
|
+
|
|
12
|
+
### Highlights
|
|
13
|
+
|
|
14
|
+
**SDK 2.0 moves to Affinity's V2 API wherever V2 can do the job.** Webhooks, reminders, note
|
|
15
|
+
writes, list get/create, file reads (new `files.get_v2`/`list_v2`) and the rate-limit endpoint
|
|
16
|
+
now use V2; the CLI gains `xaffinity webhook ls|get|create|update|delete`. V1 stays only where
|
|
17
|
+
V2 can't do it, and for person create/delete, opportunity rename/delete and adding to a list,
|
|
18
|
+
which the V2 spec documents but the API didn't serve when tested. **Breaking:** webhook and
|
|
19
|
+
reminder models change shape, note writes return `NoteV2`, `add_opportunity()` is removed, and
|
|
20
|
+
operations added in newer Affinity API versions refuse a client pinned to an older one
|
|
21
|
+
(`ApiVersionTooOldError`). See the [Migrating to 2.0](https://yaniv-golan.github.io/affinity-sdk/latest/guides/migrating-to-2/)
|
|
22
|
+
guide.
|
|
23
|
+
|
|
24
|
+
### Changed (breaking)
|
|
25
|
+
|
|
26
|
+
- **Webhooks use the V2 API** (`/v2/webhooks`, Affinity API 2026-07-15 or later, beta).
|
|
27
|
+
`WebhookSubscription` is now `Webhook`: `webhook_url` → `url`, `disabled` →
|
|
28
|
+
`status` (`WebhookStatus.ACTIVE`/`DISABLED`), `created_by` → `creator` (`PersonRef`), plus
|
|
29
|
+
`created_at`/`updated_at`. `WebhookCreate(url=…, subscriptions=[…])` requires `subscriptions`
|
|
30
|
+
(`[]` = every event type). `WebhookUpdate` takes `url`, `subscriptions`, `status` and sends
|
|
31
|
+
only what is set. `list()` returns one page (`ids`, created/updated ranges, `limit`,
|
|
32
|
+
`cursor`); `iter()` returns every webhook. `update()` returns the webhook as read back (two
|
|
33
|
+
requests); `delete()` returns `None`. 1.x field names raise `ValidationError` instead of being
|
|
34
|
+
ignored. Without permission to manage all webhooks, the API lists, reads and changes only the
|
|
35
|
+
caller's own webhooks. A client pinned to API version 2024-01-01 gets
|
|
36
|
+
`ApiVersionTooOldError`.
|
|
37
|
+
- **Reminders use the V2 API** (`/v2/reminders`; `get`/`delete` need API 2026-07-15, `update`
|
|
38
|
+
2026-09-17). `Reminder` has the V2 shape: `creator`, `owner`, `completer`, `person` are
|
|
39
|
+
`PersonRef` (id only; look names up separately), `company`/`opportunity` are
|
|
40
|
+
`CompanyRef`/`OpportunityRef`, recurrence is `recurrence` (`period_days`, `reset_type`; the
|
|
41
|
+
read-only `reset_type`/`reminder_days` properties still work), plus `updated_at`.
|
|
42
|
+
`ReminderType`, `ReminderResetType` and `ReminderStatus` are string enums with the V2 values
|
|
43
|
+
(member names unchanged; the 1.x integers are still accepted); `ReminderResetType.MEETING` is
|
|
44
|
+
now an alias of `EVENT`. `list()` takes `limit` (1-100), `cursor`, `ids` and created/updated
|
|
45
|
+
ranges instead of `page_size`/`page_token`, and returns reminders soonest-due first.
|
|
46
|
+
`update()` sends only the fields that are set (`clear_content=True` removes the content) and
|
|
47
|
+
returns the reminder as read back. `list_batch()` is on the sync client too, and fetches up to
|
|
48
|
+
50 entities per request. Kept on V1 where V2 can't do it: changing a reminder's type, and updating or deleting a
|
|
49
|
+
reminder you didn't create and don't own (V2 refuses; the SDK retries through V1). A reminder
|
|
50
|
+
must be attached to one person, company or opportunity (both APIs require it; the SDK now
|
|
51
|
+
says so before sending).
|
|
52
|
+
- **Note writes use the V2 API** (`notes.create`, `update`, `delete`; reads are unchanged).
|
|
53
|
+
`create()` and `update()` return `NoteV2` (`content.html`, `creator`; `update()` reads the note
|
|
54
|
+
back with its attachments, two requests). V2 stores notes as HTML: plain text (the default
|
|
55
|
+
`type`) is escaped and wrapped in paragraphs, and `NoteUpdate` takes `type` too (plain text
|
|
56
|
+
unless set to `HTML`, whatever the note was before). With `type=NoteType.HTML`, `<b>`/`<i>`
|
|
57
|
+
become `<strong>`/`<em>`, and what the API rejects (style/class attributes, img, pre, code,
|
|
58
|
+
blockquote, mention spans, non-http(s)/mailto links) raises `ValueError` naming the allowed
|
|
59
|
+
tags. A reply (`parent_id`) with persons/companies/opportunities raises instead of ignoring
|
|
60
|
+
them; `AI_NOTETAKER`/`EMAIL_DERIVED` can't be created. `NoteUpdate` can replace a note's
|
|
61
|
+
persons, companies and opportunities (`[]` clears). Changing the text of a note that
|
|
62
|
+
@mentions people is refused by the API; the error now says so. `NoteV2` and `NoteContent`
|
|
63
|
+
are exported from `affinity.models`.
|
|
64
|
+
- **`rate_limits.refresh()` reads `GET /v2/rate-limit`** (API 2026-07-15+), falling back to
|
|
65
|
+
response headers as before (now also when the client is pinned to an older API version).
|
|
66
|
+
`RateLimitSnapshot` is unchanged; `RateLimits` also reads the V2 names (`callerPerMinute`,
|
|
67
|
+
`orgPerMonth`).
|
|
68
|
+
- **Lists: `get()` and `create()` use the V2 API.** `get()` no longer fills `fields` (use
|
|
69
|
+
`get_fields()`) or `additional_permissions`; it sets `created_at`. `get_size()` still reads
|
|
70
|
+
the size from V1 (V2 has none). `create()` makes the caller the owner; a public list needs the
|
|
71
|
+
"Share accessible Lists globally" permission. A list created with `owner_id` or
|
|
72
|
+
`additional_permissions` still goes through V1.
|
|
73
|
+
- **`entries(list_id).add_opportunity()` is removed.** Opportunities can't be added to a list
|
|
74
|
+
as entries: create them on their list with `opportunities.create(OpportunityCreate(list_id=...))`.
|
|
75
|
+
- Person create/delete, opportunity rename/delete and adding to a list stay on V1: the V2 spec
|
|
76
|
+
documents them, but Affinity didn't serve them when tested (2026-10-12).
|
|
77
|
+
|
|
78
|
+
### Added
|
|
79
|
+
|
|
80
|
+
- **`files.get_v2()`, `files.list_v2()`, `files.iter_v2()`** (V2, Affinity API 2026-09-17+):
|
|
81
|
+
a file's metadata with a download URL that expires after 60 seconds, and every file visible to
|
|
82
|
+
you across the organization, newest first (filter by created date and uploader). `FileV2`
|
|
83
|
+
model. `files.get/list/iter` stay on V1: only V1 lists one entity's files.
|
|
84
|
+
- **CLI `webhook ls|get|create|update|delete`.** `create` takes `--url` and `--event`
|
|
85
|
+
(repeatable) or `--all-events`; `update` takes `--url`, `--event`/`--all-events`, `--status
|
|
86
|
+
active|disabled`. `create`, `update` and `delete` ask for confirmation (`--yes` in scripts),
|
|
87
|
+
since a webhook sends CRM events to an outside URL. Rows include `allEvents`.
|
|
88
|
+
- **CLI `list get <id>`** no longer prints `.data.list.fields` (the fields are in `.data.fields`
|
|
89
|
+
as before), `additionalPermissions` is always `[]`, and `createdAt` is added; `list create
|
|
90
|
+
--owner-id` creates the list through V1.
|
|
91
|
+
- **CLI `reminder create/update --reminder-days`** help now says what it is: the days between a
|
|
92
|
+
recurring reminder's due dates.
|
|
93
|
+
- **CLI `note update --type plain-text|html`**; `note create --type` is now plain-text or html
|
|
94
|
+
(Affinity creates the other kinds itself). `note create`/`update` output keeps the `note get`
|
|
95
|
+
keys (`type` is `html`; content is the stored HTML). The duplicate-note warning still finds
|
|
96
|
+
an earlier copy: V1 shows notes stored as HTML in a markdown form, which the check allows for.
|
|
97
|
+
- **CLI `reminder update --clear-content`**; `reminder ls --page-size` is now at most 100, and
|
|
98
|
+
rows include `updatedAt`; `--reset-type event` (`meeting` still accepted, printed as `event`).
|
|
99
|
+
- **MCP:** the webhook commands are in the command registry; `webhook create`/`update`/`delete`
|
|
100
|
+
go through the same user confirmation as deletes, and the confirmation says why (events sent
|
|
101
|
+
to an outside URL).
|
|
102
|
+
|
|
103
|
+
### Fixed
|
|
104
|
+
|
|
105
|
+
- `Person.company_ids` and `Opportunity.company_ids` are now read from V1 responses
|
|
106
|
+
(`organization_ids`), e.g. from `persons.create()` with companies, `persons.update()`,
|
|
107
|
+
`opportunities.update()` and `get_details()`; they were always empty.
|
|
108
|
+
|
|
109
|
+
### Docs
|
|
110
|
+
|
|
111
|
+
- New **API coverage** reference page: every Affinity API operation (V2 and V1) and how the SDK
|
|
112
|
+
supports it — the SDK call, an equivalent operation, or the planned release — with beta
|
|
113
|
+
operations and the minimum API version marked.
|
|
114
|
+
|
|
115
|
+
### Internal
|
|
116
|
+
|
|
117
|
+
- `tools/api_coverage.py` and the ledger `tools/api_coverage.json` (CI: `--check`): every
|
|
118
|
+
operation in the pinned V2 snapshots and the new V1 snapshot (`tools/api_coverage_v1_snapshot.json`,
|
|
119
|
+
59 operations) has exactly one row. `tests/test_api_coverage.py` runs each supported row's call,
|
|
120
|
+
sync and async, against a recording HTTP layer and checks the method, path and API version it
|
|
121
|
+
requests.
|
|
122
|
+
|
|
123
|
+
### Plugins
|
|
124
|
+
|
|
125
|
+
- **SDK plugin**: 1.7.1 → 2.0.0 (matches SDK 2.0) — skill: note writes go through V2 (HTML, the
|
|
126
|
+
allowed tags), and `add_opportunity()` is gone (create the opportunity on its list).
|
|
127
|
+
- **CLI plugin**: 1.13.6 → 2.0.0 (matches CLI 2.0; no content change).
|
|
128
|
+
- **MCP**: 1.32.2 → 2.0.0 (requires CLI 2.0.0; see `mcp/CHANGELOG.md`).
|
|
129
|
+
- **CLI plugin**: 1.13.5 → 1.13.6 — skill: the Cowork install line adds
|
|
130
|
+
`--no-warn-script-location` (pip's "not on PATH" warning was noise; the skill adds the folder to
|
|
131
|
+
PATH in each call), and the Cowork key paths (`--env-file`, `AFFINITY_API_KEY_FILE`) are quoted,
|
|
132
|
+
so connected folders with spaces in their names work.
|
|
133
|
+
- **CLI plugin**: 1.13.4 → 1.13.5 — no `clis` credential declaration. In local Cowork it routed
|
|
134
|
+
every `xaffinity` call through Desktop's CLI credential broker, which isn't enabled yet and
|
|
135
|
+
refuses the call ("cli-wrapper: plugin oauth disabled"), so the CLI never ran whatever key the
|
|
136
|
+
VM had. Cowork's plugin settings no longer show an Affinity API Key field. The VM has no
|
|
137
|
+
`xaffinity` of its own, so the skill now installs it when it's missing (`pip install --user`,
|
|
138
|
+
about 10s, once per task) and puts `~/.local/bin` on PATH in each call; the CLI then reads the
|
|
139
|
+
key as the skill describes (a connected folder's `.env` with `--env-file`, or a key file).
|
|
140
|
+
- **CLI plugin**: 1.13.3 → 1.13.4 — in local Cowork the plugin's hooks run on the host Mac, not
|
|
141
|
+
in the VM where the CLI runs, so the key check saw the Mac's key (or none) and could deny every
|
|
142
|
+
data command even with a key set in Cowork. There the hooks now do nothing; a missing key
|
|
143
|
+
shows up as the CLI's own error. Cloud Cowork and Claude Code keep the check. The `.env` read
|
|
144
|
+
guard's message no longer claims the key is in the environment.
|
|
145
|
+
|
|
10
146
|
## [1.29.0] - 2026-10-11
|
|
11
147
|
|
|
12
148
|
### Highlights
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: affinity-sdk
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
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/
|
|
@@ -373,8 +373,8 @@ with Affinity(api_key="your-key") as client:
|
|
|
373
373
|
```python
|
|
374
374
|
from datetime import datetime, timedelta
|
|
375
375
|
from affinity import Affinity
|
|
376
|
-
from affinity.models import ReminderCreate
|
|
377
|
-
from affinity.types import PersonId, ReminderResetType, ReminderType, UserId
|
|
376
|
+
from affinity.models import ReminderCreate, ReminderUpdate
|
|
377
|
+
from affinity.types import PersonId, ReminderResetType, ReminderStatus, ReminderType, UserId
|
|
378
378
|
|
|
379
379
|
with Affinity(api_key="your-key") as client:
|
|
380
380
|
# Get current user
|
|
@@ -402,6 +402,14 @@ with Affinity(api_key="your-key") as client:
|
|
|
402
402
|
person_id=PersonId(123),
|
|
403
403
|
)
|
|
404
404
|
)
|
|
405
|
+
|
|
406
|
+
# Complete it (a recurring reminder moves to its next due date)
|
|
407
|
+
client.reminders.update(recurring.id, ReminderUpdate(is_completed=True))
|
|
408
|
+
|
|
409
|
+
# Overdue reminders for many people, one request per 50 people
|
|
410
|
+
overdue = client.reminders.list_batch(
|
|
411
|
+
person_ids=[PersonId(123), PersonId(456)], status=ReminderStatus.OVERDUE
|
|
412
|
+
)
|
|
405
413
|
```
|
|
406
414
|
|
|
407
415
|
### Files
|
|
@@ -456,13 +464,13 @@ with Affinity(api_key="your-key") as client:
|
|
|
456
464
|
```python
|
|
457
465
|
from affinity import Affinity
|
|
458
466
|
from affinity.models import WebhookCreate, WebhookUpdate
|
|
459
|
-
from affinity.types import WebhookEvent
|
|
467
|
+
from affinity.types import WebhookEvent, WebhookStatus
|
|
460
468
|
|
|
461
469
|
with Affinity(api_key="your-key") as client:
|
|
462
|
-
# Create a webhook
|
|
470
|
+
# Create a webhook (subscriptions is required; [] means every event type)
|
|
463
471
|
webhook = client.webhooks.create(
|
|
464
472
|
WebhookCreate(
|
|
465
|
-
|
|
473
|
+
url="https://your-server.com/webhook",
|
|
466
474
|
subscriptions=[
|
|
467
475
|
WebhookEvent.LIST_ENTRY_CREATED,
|
|
468
476
|
WebhookEvent.LIST_ENTRY_DELETED,
|
|
@@ -471,14 +479,12 @@ with Affinity(api_key="your-key") as client:
|
|
|
471
479
|
)
|
|
472
480
|
)
|
|
473
481
|
|
|
474
|
-
#
|
|
475
|
-
|
|
482
|
+
# All webhooks you can see (all of them if you may manage all webhooks)
|
|
483
|
+
for hook in client.webhooks.iter():
|
|
484
|
+
print(hook.id, hook.url, hook.status)
|
|
476
485
|
|
|
477
|
-
#
|
|
478
|
-
client.webhooks.update(
|
|
479
|
-
webhook.id,
|
|
480
|
-
WebhookUpdate(disabled=True)
|
|
481
|
-
)
|
|
486
|
+
# Pause a webhook (returns it as read back)
|
|
487
|
+
client.webhooks.update(webhook.id, WebhookUpdate(status=WebhookStatus.DISABLED))
|
|
482
488
|
```
|
|
483
489
|
|
|
484
490
|
### Rate Limits
|
|
@@ -545,9 +551,9 @@ those to V2 is planned.
|
|
|
545
551
|
| List Entries (write) | Create | ✅ | V1 |
|
|
546
552
|
| Field Values (read) | ✅ | ✅ | V2 |
|
|
547
553
|
| Field Values (write) | ✅ | ✅ | V2 (list entries), V1 (companies/persons) |
|
|
548
|
-
| Notes | ✅ | ✅ | V1 |
|
|
549
|
-
| Reminders | ✅ | ✅ | V1 |
|
|
550
|
-
| Webhooks | ✅ | ✅ |
|
|
554
|
+
| Notes | ✅ | ✅ | V1 reads; V2 writes |
|
|
555
|
+
| Reminders | ✅ | ✅ | V2 (V1 for type changes, and when V2 refuses a non-owner) |
|
|
556
|
+
| Webhooks | ✅ | ✅ | V2 |
|
|
551
557
|
| Interactions | Read-only | ✅ | V1 |
|
|
552
558
|
| Entity Files | Read-only | ✅ | V1 |
|
|
553
559
|
| Relationship Strengths | ✅ | ✅ | V1 |
|
|
@@ -697,7 +703,7 @@ async def main():
|
|
|
697
703
|
asyncio.run(main())
|
|
698
704
|
```
|
|
699
705
|
|
|
700
|
-
Async support mirrors the sync client surface area (including V1
|
|
706
|
+
Async support mirrors the sync client surface area (including the V1 services like notes and files).
|
|
701
707
|
|
|
702
708
|
See `docs/public/guides/sync-vs-async.md` for more details.
|
|
703
709
|
|
|
@@ -312,8 +312,8 @@ with Affinity(api_key="your-key") as client:
|
|
|
312
312
|
```python
|
|
313
313
|
from datetime import datetime, timedelta
|
|
314
314
|
from affinity import Affinity
|
|
315
|
-
from affinity.models import ReminderCreate
|
|
316
|
-
from affinity.types import PersonId, ReminderResetType, ReminderType, UserId
|
|
315
|
+
from affinity.models import ReminderCreate, ReminderUpdate
|
|
316
|
+
from affinity.types import PersonId, ReminderResetType, ReminderStatus, ReminderType, UserId
|
|
317
317
|
|
|
318
318
|
with Affinity(api_key="your-key") as client:
|
|
319
319
|
# Get current user
|
|
@@ -341,6 +341,14 @@ with Affinity(api_key="your-key") as client:
|
|
|
341
341
|
person_id=PersonId(123),
|
|
342
342
|
)
|
|
343
343
|
)
|
|
344
|
+
|
|
345
|
+
# Complete it (a recurring reminder moves to its next due date)
|
|
346
|
+
client.reminders.update(recurring.id, ReminderUpdate(is_completed=True))
|
|
347
|
+
|
|
348
|
+
# Overdue reminders for many people, one request per 50 people
|
|
349
|
+
overdue = client.reminders.list_batch(
|
|
350
|
+
person_ids=[PersonId(123), PersonId(456)], status=ReminderStatus.OVERDUE
|
|
351
|
+
)
|
|
344
352
|
```
|
|
345
353
|
|
|
346
354
|
### Files
|
|
@@ -395,13 +403,13 @@ with Affinity(api_key="your-key") as client:
|
|
|
395
403
|
```python
|
|
396
404
|
from affinity import Affinity
|
|
397
405
|
from affinity.models import WebhookCreate, WebhookUpdate
|
|
398
|
-
from affinity.types import WebhookEvent
|
|
406
|
+
from affinity.types import WebhookEvent, WebhookStatus
|
|
399
407
|
|
|
400
408
|
with Affinity(api_key="your-key") as client:
|
|
401
|
-
# Create a webhook
|
|
409
|
+
# Create a webhook (subscriptions is required; [] means every event type)
|
|
402
410
|
webhook = client.webhooks.create(
|
|
403
411
|
WebhookCreate(
|
|
404
|
-
|
|
412
|
+
url="https://your-server.com/webhook",
|
|
405
413
|
subscriptions=[
|
|
406
414
|
WebhookEvent.LIST_ENTRY_CREATED,
|
|
407
415
|
WebhookEvent.LIST_ENTRY_DELETED,
|
|
@@ -410,14 +418,12 @@ with Affinity(api_key="your-key") as client:
|
|
|
410
418
|
)
|
|
411
419
|
)
|
|
412
420
|
|
|
413
|
-
#
|
|
414
|
-
|
|
421
|
+
# All webhooks you can see (all of them if you may manage all webhooks)
|
|
422
|
+
for hook in client.webhooks.iter():
|
|
423
|
+
print(hook.id, hook.url, hook.status)
|
|
415
424
|
|
|
416
|
-
#
|
|
417
|
-
client.webhooks.update(
|
|
418
|
-
webhook.id,
|
|
419
|
-
WebhookUpdate(disabled=True)
|
|
420
|
-
)
|
|
425
|
+
# Pause a webhook (returns it as read back)
|
|
426
|
+
client.webhooks.update(webhook.id, WebhookUpdate(status=WebhookStatus.DISABLED))
|
|
421
427
|
```
|
|
422
428
|
|
|
423
429
|
### Rate Limits
|
|
@@ -484,9 +490,9 @@ those to V2 is planned.
|
|
|
484
490
|
| List Entries (write) | Create | ✅ | V1 |
|
|
485
491
|
| Field Values (read) | ✅ | ✅ | V2 |
|
|
486
492
|
| Field Values (write) | ✅ | ✅ | V2 (list entries), V1 (companies/persons) |
|
|
487
|
-
| Notes | ✅ | ✅ | V1 |
|
|
488
|
-
| Reminders | ✅ | ✅ | V1 |
|
|
489
|
-
| Webhooks | ✅ | ✅ |
|
|
493
|
+
| Notes | ✅ | ✅ | V1 reads; V2 writes |
|
|
494
|
+
| Reminders | ✅ | ✅ | V2 (V1 for type changes, and when V2 refuses a non-owner) |
|
|
495
|
+
| Webhooks | ✅ | ✅ | V2 |
|
|
490
496
|
| Interactions | Read-only | ✅ | V1 |
|
|
491
497
|
| Entity Files | Read-only | ✅ | V1 |
|
|
492
498
|
| Relationship Strengths | ✅ | ✅ | V1 |
|
|
@@ -636,7 +642,7 @@ async def main():
|
|
|
636
642
|
asyncio.run(main())
|
|
637
643
|
```
|
|
638
644
|
|
|
639
|
-
Async support mirrors the sync client surface area (including V1
|
|
645
|
+
Async support mirrors the sync client surface area (including the V1 services like notes and files).
|
|
640
646
|
|
|
641
647
|
See `docs/public/guides/sync-vs-async.md` for more details.
|
|
642
648
|
|
|
@@ -292,7 +292,12 @@ def list_ls(
|
|
|
292
292
|
default=False,
|
|
293
293
|
help="Whether the list is public (default: private).",
|
|
294
294
|
)
|
|
295
|
-
@click.option(
|
|
295
|
+
@click.option(
|
|
296
|
+
"--owner-id",
|
|
297
|
+
type=int,
|
|
298
|
+
default=None,
|
|
299
|
+
help="Owner id (creates the list through the V1 API; otherwise you are the owner).",
|
|
300
|
+
)
|
|
296
301
|
@output_options
|
|
297
302
|
@click.pass_obj
|
|
298
303
|
def list_create(
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import re
|
|
3
4
|
import sys
|
|
4
5
|
from contextlib import ExitStack
|
|
5
6
|
from datetime import datetime, timedelta, timezone
|
|
6
7
|
from typing import Any
|
|
7
8
|
|
|
9
|
+
from pydantic import ValidationError as PydanticValidationError
|
|
8
10
|
from rich.console import Console
|
|
9
11
|
from rich.progress import BarColumn, Progress, TaskID, TextColumn, TimeElapsedColumn
|
|
10
12
|
|
|
11
|
-
from affinity.models.secondary import Note, NoteCreate, NoteUpdate
|
|
13
|
+
from affinity.models.secondary import Note, NoteCreate, NoteUpdate, NoteV2
|
|
12
14
|
from affinity.models.types import InteractionType, NoteType
|
|
13
15
|
from affinity.services.search import NOTE_SEARCH_DEFAULT_LIMIT, build_keyword_search_body
|
|
14
16
|
from affinity.types import CompanyId, NoteId, OpportunityId, PersonId, UserId
|
|
@@ -42,8 +44,6 @@ _NOTE_TYPE_MAP = {
|
|
|
42
44
|
"plain-text": NoteType.PLAIN_TEXT,
|
|
43
45
|
"plain": NoteType.PLAIN_TEXT,
|
|
44
46
|
"html": NoteType.HTML,
|
|
45
|
-
"ai-notetaker": NoteType.AI_NOTETAKER,
|
|
46
|
-
"email-derived": NoteType.EMAIL_DERIVED,
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
|
|
@@ -66,6 +66,17 @@ def _get_cached_user_id(ctx: CLIContext, client: Any) -> int | None:
|
|
|
66
66
|
return None
|
|
67
67
|
|
|
68
68
|
|
|
69
|
+
def _comparable(text: str) -> str:
|
|
70
|
+
"""Note text for the duplicate check, in a form both copies share.
|
|
71
|
+
|
|
72
|
+
V1 shows notes stored as HTML (every note written through V2) in a markdown form: special
|
|
73
|
+
characters backslash-escaped (``snake\\_case``) and two spaces before a line break. Undo
|
|
74
|
+
those, and compare whitespace-insensitively.
|
|
75
|
+
"""
|
|
76
|
+
text = re.sub(r"\\(.)", r"\1", text)
|
|
77
|
+
return " ".join(text.split())
|
|
78
|
+
|
|
79
|
+
|
|
69
80
|
def _maybe_warn_duplicate_note(
|
|
70
81
|
*,
|
|
71
82
|
ctx: CLIContext,
|
|
@@ -99,7 +110,7 @@ def _maybe_warn_duplicate_note(
|
|
|
99
110
|
return
|
|
100
111
|
scoped_creator_id = resolved_id
|
|
101
112
|
|
|
102
|
-
normalized_new = content
|
|
113
|
+
normalized_new = _comparable(content)
|
|
103
114
|
if not normalized_new:
|
|
104
115
|
return
|
|
105
116
|
|
|
@@ -119,8 +130,7 @@ def _maybe_warn_duplicate_note(
|
|
|
119
130
|
# transient list failure abort the actual note write.
|
|
120
131
|
return False
|
|
121
132
|
for existing in getattr(page, "data", []) or []:
|
|
122
|
-
|
|
123
|
-
if existing_content != normalized_new:
|
|
133
|
+
if _comparable(existing.content or "") != normalized_new:
|
|
124
134
|
continue
|
|
125
135
|
created_at = getattr(existing, "created_at", None)
|
|
126
136
|
if created_at is None:
|
|
@@ -182,6 +192,78 @@ def _note_payload(note: Note) -> dict[str, object]:
|
|
|
182
192
|
}
|
|
183
193
|
|
|
184
194
|
|
|
195
|
+
_INPUT_MODELS = ("NoteCreate", "NoteUpdate")
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def _is_input_error(exc: ValueError) -> bool:
|
|
199
|
+
"""Our own checks, or the request model; not a response the API sent that didn't parse
|
|
200
|
+
(the write may have happened: a usage error would invite a duplicating retry)."""
|
|
201
|
+
if isinstance(exc, PydanticValidationError):
|
|
202
|
+
return exc.title in _INPUT_MODELS
|
|
203
|
+
return True
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def _usage(exc: ValueError) -> CLIError:
|
|
207
|
+
errors = getattr(exc, "errors", None)
|
|
208
|
+
message = str(exc)
|
|
209
|
+
if callable(errors): # pydantic ValidationError: keep only the messages
|
|
210
|
+
message = "; ".join(str(e.get("msg", "")).removeprefix("Value error, ") for e in errors())
|
|
211
|
+
return CLIError(message, error_type="usage_error", exit_code=2)
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def _ids(given: list[int] | None, preview: list[Any] | None) -> list[int]:
|
|
215
|
+
if given is not None:
|
|
216
|
+
return [int(i) for i in given]
|
|
217
|
+
return [int(item.id) for item in preview or []]
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def _note_v2_payload(
|
|
221
|
+
note: NoteV2,
|
|
222
|
+
*,
|
|
223
|
+
person_ids: list[int] | None = None,
|
|
224
|
+
company_ids: list[int] | None = None,
|
|
225
|
+
opportunity_ids: list[int] | None = None,
|
|
226
|
+
) -> dict[str, object]:
|
|
227
|
+
"""A note written through V2, with the same keys as `note get` (V2 stores HTML).
|
|
228
|
+
|
|
229
|
+
Attachment ids come from the request when given, else from the note as read back.
|
|
230
|
+
"""
|
|
231
|
+
interaction = note.interaction or {}
|
|
232
|
+
persons = _ids(person_ids, note.persons)
|
|
233
|
+
mentioned = [
|
|
234
|
+
int(m["person"]["id"])
|
|
235
|
+
for m in note.mentions
|
|
236
|
+
if isinstance(m, dict) and isinstance(m.get("person"), dict) and m["person"].get("id")
|
|
237
|
+
]
|
|
238
|
+
return {
|
|
239
|
+
"id": int(note.id),
|
|
240
|
+
"type": "html",
|
|
241
|
+
"creatorId": int(note.creator.id) if note.creator else None,
|
|
242
|
+
"content": note.content.html,
|
|
243
|
+
"personIds": persons,
|
|
244
|
+
"associatedPersonIds": persons,
|
|
245
|
+
"interactionPersonIds": [],
|
|
246
|
+
"mentionedPersonIds": mentioned,
|
|
247
|
+
"companyIds": _ids(company_ids, note.companies),
|
|
248
|
+
"opportunityIds": _ids(opportunity_ids, note.opportunities),
|
|
249
|
+
"interactionId": interaction.get("id"),
|
|
250
|
+
"interactionType": interaction.get("type"),
|
|
251
|
+
"isMeeting": interaction.get("type") == "meeting",
|
|
252
|
+
"parentId": int(note.parent["id"]) if note.parent and note.parent.get("id") else None,
|
|
253
|
+
"createdAt": note.created_at,
|
|
254
|
+
"updatedAt": note.updated_at,
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def _truncation_warnings(note: NoteV2, warnings: list[str]) -> None:
|
|
259
|
+
for key in ("persons", "companies", "opportunities"):
|
|
260
|
+
shown, total = getattr(note, key), getattr(note, f"{key}_total")
|
|
261
|
+
if shown is not None and total is not None and total > len(shown):
|
|
262
|
+
warnings.append(
|
|
263
|
+
f"The note has {total} attached {key}; the output lists the first {len(shown)}."
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
|
|
185
267
|
@category("read")
|
|
186
268
|
@note_group.command(name="ls", cls=RichCommand)
|
|
187
269
|
@click.option("--person-id", type=int, default=None, help="Filter by person id.")
|
|
@@ -488,7 +570,7 @@ def note_search(
|
|
|
488
570
|
"note_type",
|
|
489
571
|
type=click.Choice(sorted(_NOTE_TYPE_MAP.keys())),
|
|
490
572
|
default=None,
|
|
491
|
-
help="
|
|
573
|
+
help="How --content is written: plain-text (default; stored as escaped HTML) or html.",
|
|
492
574
|
)
|
|
493
575
|
@click.option("--person-id", "person_ids", multiple=True, type=int, help="Associate person id.")
|
|
494
576
|
@click.option(
|
|
@@ -548,15 +630,16 @@ def note_create(
|
|
|
548
630
|
"""
|
|
549
631
|
Create a note attached to an entity.
|
|
550
632
|
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
633
|
+
Affinity stores notes as HTML: plain text is escaped and wrapped in paragraphs (a blank
|
|
634
|
+
line starts a new one). With --type html, <b>/<i> become <strong>/<em>; tags Affinity
|
|
635
|
+
rejects (style/class attributes, img, pre, code, blockquote, ...) fail before anything is
|
|
636
|
+
sent. A reply (--parent-id) has no persons, companies or opportunities of its own.
|
|
555
637
|
|
|
556
638
|
Examples:
|
|
557
639
|
|
|
558
640
|
- `xaffinity note create --content "Meeting notes" --person-id 12345`
|
|
559
|
-
- `xaffinity note create --content "<
|
|
641
|
+
- `xaffinity note create --content "<p><strong>Summary</strong></p>" --type html \\
|
|
642
|
+
--company-id 67890`
|
|
560
643
|
"""
|
|
561
644
|
|
|
562
645
|
def fn(ctx: CLIContext, warnings: list[str]) -> CommandOutput:
|
|
@@ -597,18 +680,23 @@ def note_create(
|
|
|
597
680
|
window_seconds=duplicate_window_seconds,
|
|
598
681
|
)
|
|
599
682
|
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
683
|
+
try:
|
|
684
|
+
note = client.notes.create(
|
|
685
|
+
NoteCreate(
|
|
686
|
+
content=content,
|
|
687
|
+
type=parsed_type or NoteType.PLAIN_TEXT,
|
|
688
|
+
person_ids=[PersonId(pid) for pid in person_ids],
|
|
689
|
+
company_ids=[CompanyId(cid) for cid in company_ids],
|
|
690
|
+
opportunity_ids=[OpportunityId(oid) for oid in opportunity_ids],
|
|
691
|
+
parent_id=NoteId(parent_id) if parent_id else None,
|
|
692
|
+
creator_id=UserId(creator_id) if creator_id is not None else None,
|
|
693
|
+
created_at=created_at_value,
|
|
694
|
+
)
|
|
610
695
|
)
|
|
611
|
-
|
|
696
|
+
except ValueError as exc:
|
|
697
|
+
if not _is_input_error(exc):
|
|
698
|
+
raise
|
|
699
|
+
raise _usage(exc) from exc
|
|
612
700
|
|
|
613
701
|
ctx_modifiers: dict[str, object] = {}
|
|
614
702
|
if note_type:
|
|
@@ -633,7 +721,14 @@ def note_create(
|
|
|
633
721
|
)
|
|
634
722
|
|
|
635
723
|
return CommandOutput(
|
|
636
|
-
data={
|
|
724
|
+
data={
|
|
725
|
+
"note": _note_v2_payload(
|
|
726
|
+
note,
|
|
727
|
+
person_ids=list(person_ids),
|
|
728
|
+
company_ids=list(company_ids),
|
|
729
|
+
opportunity_ids=list(opportunity_ids),
|
|
730
|
+
)
|
|
731
|
+
},
|
|
637
732
|
context=cmd_context,
|
|
638
733
|
api_called=True,
|
|
639
734
|
)
|
|
@@ -645,23 +740,47 @@ def note_create(
|
|
|
645
740
|
@note_group.command(name="update", cls=RichCommand)
|
|
646
741
|
@click.argument("note_id", type=int)
|
|
647
742
|
@click.option("--content", type=str, required=True, help="Updated note content.")
|
|
743
|
+
@click.option(
|
|
744
|
+
"--type",
|
|
745
|
+
"note_type",
|
|
746
|
+
type=click.Choice(sorted(_NOTE_TYPE_MAP.keys())),
|
|
747
|
+
default=None,
|
|
748
|
+
help="How --content is written: plain-text (default) or html, whatever the note was before.",
|
|
749
|
+
)
|
|
648
750
|
@output_options
|
|
649
751
|
@click.pass_obj
|
|
650
|
-
def note_update(ctx: CLIContext, note_id: int, *, content: str) -> None:
|
|
651
|
-
"""
|
|
752
|
+
def note_update(ctx: CLIContext, note_id: int, *, content: str, note_type: str | None) -> None:
|
|
753
|
+
"""Replace a note's content.
|
|
754
|
+
|
|
755
|
+
The content is plain text unless you pass --type html (an HTML note updated with plain text
|
|
756
|
+
shows the text as typed). Notes with @mentions can't be changed through the API.
|
|
757
|
+
"""
|
|
652
758
|
|
|
653
759
|
def fn(ctx: CLIContext, warnings: list[str]) -> CommandOutput:
|
|
760
|
+
parsed_type = parse_choice(note_type, _NOTE_TYPE_MAP, label="note type")
|
|
654
761
|
client = ctx.get_client(warnings=warnings)
|
|
655
|
-
|
|
762
|
+
try:
|
|
763
|
+
note = client.notes.update(
|
|
764
|
+
NoteId(note_id),
|
|
765
|
+
NoteUpdate(content=content, type=parsed_type or NoteType.PLAIN_TEXT),
|
|
766
|
+
)
|
|
767
|
+
except ValueError as exc:
|
|
768
|
+
if not _is_input_error(exc):
|
|
769
|
+
raise
|
|
770
|
+
raise _usage(exc) from exc
|
|
771
|
+
_truncation_warnings(note, warnings)
|
|
656
772
|
|
|
773
|
+
modifiers: dict[str, object] = {"content": content}
|
|
774
|
+
if note_type:
|
|
775
|
+
modifiers["type"] = note_type
|
|
657
776
|
cmd_context = CommandContext(
|
|
658
777
|
name="note update",
|
|
659
778
|
inputs={"noteId": note_id},
|
|
660
|
-
modifiers=
|
|
779
|
+
modifiers=modifiers,
|
|
661
780
|
)
|
|
662
781
|
|
|
663
782
|
return CommandOutput(
|
|
664
|
-
data={"note":
|
|
783
|
+
data={"note": _note_v2_payload(note)},
|
|
665
784
|
context=cmd_context,
|
|
666
785
|
api_called=True,
|
|
667
786
|
)
|