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.
Files changed (674) hide show
  1. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/workflows/ci.yml +3 -0
  2. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/workflows/plugin-build.yml +13 -0
  3. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/CHANGELOG.md +136 -0
  4. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/PKG-INFO +23 -17
  5. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/README.md +22 -16
  6. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/list_cmds.py +6 -1
  7. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/note_cmds.py +148 -29
  8. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/reminder_cmds.py +157 -191
  9. affinity_sdk-2.0.0/affinity/cli/commands/webhook_cmds.py +365 -0
  10. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/confirm.py +12 -4
  11. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/main.py +2 -0
  12. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/client.py +2 -4
  13. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/inbound_webhooks.py +1 -1
  14. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/models/__init__.py +17 -3
  15. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/models/entities.py +20 -7
  16. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/models/secondary.py +196 -40
  17. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/models/types.py +57 -14
  18. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/__init__.py +4 -4
  19. affinity_sdk-2.0.0/affinity/services/_note_html.py +165 -0
  20. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/_v2_filters.py +8 -1
  21. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/lists.py +67 -63
  22. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/rate_limits.py +12 -9
  23. affinity_sdk-2.0.0/affinity/services/reminders.py +715 -0
  24. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/v1_only.py +208 -604
  25. affinity_sdk-2.0.0/affinity/services/webhooks.py +304 -0
  26. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/types.py +2 -0
  27. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/cli/commands.md +78 -0
  28. affinity_sdk-2.0.0/docs/public/guides/api-versions-and-routing.md +80 -0
  29. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/errors-and-retries.md +6 -9
  30. affinity_sdk-2.0.0/docs/public/guides/migrating-to-2.md +90 -0
  31. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/pagination.md +3 -3
  32. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/webhooks.md +45 -8
  33. affinity_sdk-2.0.0/docs/public/reference/api-coverage.md +190 -0
  34. affinity_sdk-2.0.0/docs/public/reference/services/reminders.md +5 -0
  35. affinity_sdk-2.0.0/docs/public/reference/services/v1/files.md +8 -0
  36. affinity_sdk-2.0.0/docs/public/reference/services/v1/notes.md +6 -0
  37. affinity_sdk-2.0.0/docs/public/reference/services/webhooks.md +5 -0
  38. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.claude-plugin/plugin.json +1 -1
  39. affinity_sdk-2.0.0/mcp/.mcp-bash/VERSION +1 -0
  40. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/bin/mcp-bash +11 -1
  41. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/cli/common.sh +4 -10
  42. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/core.sh +118 -8
  43. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/elicitation.sh +3 -0
  44. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/runtime.sh +25 -0
  45. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/timeout.sh +19 -6
  46. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/tools.sh +52 -6
  47. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/tools_policy.sh +48 -2
  48. affinity_sdk-2.0.0/mcp/.mcp-bash/sdk/tool-error.sh +113 -0
  49. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/sdk/tool-sdk.sh +172 -15
  50. affinity_sdk-2.0.0/mcp/.mcp-bash/vendor.json +1 -0
  51. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.registry/commands.generated.json +331 -19
  52. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.registry/mcp-commands.json +28 -0
  53. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/CHANGELOG.md +44 -0
  54. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/COMPATIBILITY +9 -2
  55. affinity_sdk-2.0.0/mcp/VERSION +1 -0
  56. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/mcp-bash.lock +2 -2
  57. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/server.d/policy.sh +4 -5
  58. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/server.d/requirements.json +1 -1
  59. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/server.d/server.meta.json +1 -1
  60. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/test/run.sh +8 -5
  61. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/execute-write-command/tool.meta.json +2 -2
  62. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/execute-write-command/tool.sh +18 -2
  63. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/query/tool.sh +1 -1
  64. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mkdocs.yml +4 -2
  65. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/affinity-sdk/.claude-plugin/plugin.json +1 -1
  66. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/affinity-sdk/.claude-plugin/skills/affinity-python-sdk/SKILL.md +1 -1
  67. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/affinity-sdk/.claude-plugin/skills/affinity-python-sdk/references/services.md +4 -1
  68. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/xaffinity-cli/.claude-plugin/plugin.json +2 -16
  69. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/xaffinity-cli/hooks/guard-env-read.sh +2 -2
  70. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/xaffinity-cli/hooks/pre-xaffinity.sh +9 -0
  71. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/xaffinity-cli/hooks/session-setup.sh +8 -0
  72. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/xaffinity-cli/skills/xaffinity-cli-usage/SKILL.md +6 -1
  73. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/xaffinity-cli/skills/xaffinity-cli-usage/references/setup.md +15 -5
  74. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/pyproject.toml +1 -1
  75. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/README.md +2 -0
  76. affinity_sdk-2.0.0/tests/cowork/cassettes/company-lists-status.cassette.json +410 -0
  77. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/cassettes/hook-blocks-without-key.cassette.json +66 -66
  78. affinity_sdk-2.0.0/tests/cowork/cassettes/no-key-skill-path.cassette.json +395 -0
  79. affinity_sdk-2.0.0/tests/cowork/cassettes/status-history.cassette.json +469 -0
  80. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/scenarios/no-key-skill-path.yaml +3 -2
  81. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/integration/test_sdk_reads.py +8 -10
  82. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/integration/test_sdk_writes.py +44 -69
  83. affinity_sdk-2.0.0/tests/test_api_coverage.py +162 -0
  84. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_csv_export.py +10 -10
  85. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_date_params.py +17 -14
  86. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_field_options_and_transcripts.py +1 -1
  87. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_list_cmds_coverage.py +13 -13
  88. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_list_expand_interactions.py +6 -6
  89. affinity_sdk-2.0.0/tests/test_cli_notes_writes.py +181 -0
  90. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_opportunity_cmds.py +1 -1
  91. affinity_sdk-2.0.0/tests/test_cli_plugin_manifest.py +23 -0
  92. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_pre_xaffinity_hook.py +51 -0
  93. affinity_sdk-2.0.0/tests/test_cli_reminders.py +253 -0
  94. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_session_setup_hook.py +38 -0
  95. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_set_phase_atomicity.py +50 -9
  96. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_v1_only_cmds.py +0 -195
  97. affinity_sdk-2.0.0/tests/test_cli_webhooks.py +212 -0
  98. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_write_ops.py +2 -2
  99. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_client.py +2 -2
  100. affinity_sdk-2.0.0/tests/test_files_v2.py +111 -0
  101. affinity_sdk-2.0.0/tests/test_lists_v2_writes.py +144 -0
  102. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_mcp_cli_version_check.py +29 -0
  103. affinity_sdk-2.0.0/tests/test_mcp_query_cli_error.py +75 -0
  104. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_models.py +1 -1
  105. affinity_sdk-2.0.0/tests/test_notes_v2_writes.py +300 -0
  106. affinity_sdk-2.0.0/tests/test_rate_limit_v2.py +78 -0
  107. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_readonly_factory.py +3 -2
  108. affinity_sdk-2.0.0/tests/test_reminder_list_batch.py +136 -0
  109. affinity_sdk-2.0.0/tests/test_reminders_v2.py +541 -0
  110. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_requirements_additional.py +4 -3
  111. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_lists_additional_coverage.py +22 -10
  112. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_rate_limits_coverage_gaps.py +18 -23
  113. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_v1_only_async.py +3 -119
  114. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_transport_and_readonly_mode.py +3 -2
  115. affinity_sdk-2.0.0/tests/test_v1_association_parsing.py +28 -0
  116. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_v1_only_services_additional_coverage.py +3 -63
  117. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_v1_only_services_more_coverage.py +0 -133
  118. affinity_sdk-2.0.0/tests/test_v2_request_bodies.py +271 -0
  119. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_validate_openapi_tool.py +33 -0
  120. affinity_sdk-2.0.0/tests/test_webhooks_v2.py +232 -0
  121. affinity_sdk-2.0.0/tools/api_coverage.json +1155 -0
  122. affinity_sdk-2.0.0/tools/api_coverage.py +238 -0
  123. affinity_sdk-2.0.0/tools/api_coverage_v1_snapshot.json +68 -0
  124. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tools/validate_openapi_models.py +37 -4
  125. affinity_sdk-1.29.0/docs/public/guides/api-versions-and-routing.md +0 -52
  126. affinity_sdk-1.29.0/docs/public/reference/services/v1/files.md +0 -3
  127. affinity_sdk-1.29.0/docs/public/reference/services/v1/notes.md +0 -3
  128. affinity_sdk-1.29.0/docs/public/reference/services/v1/reminders.md +0 -3
  129. affinity_sdk-1.29.0/docs/public/reference/services/v1/webhooks.md +0 -3
  130. affinity_sdk-1.29.0/mcp/.mcp-bash/VERSION +0 -1
  131. affinity_sdk-1.29.0/mcp/.mcp-bash/vendor.json +0 -1
  132. affinity_sdk-1.29.0/mcp/VERSION +0 -1
  133. affinity_sdk-1.29.0/tests/cowork/cassettes/company-lists-status.cassette.json +0 -410
  134. affinity_sdk-1.29.0/tests/cowork/cassettes/no-key-skill-path.cassette.json +0 -417
  135. affinity_sdk-1.29.0/tests/cowork/cassettes/status-history.cassette.json +0 -433
  136. affinity_sdk-1.29.0/tests/test_reminder_list_batch.py +0 -184
  137. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.claude-plugin/marketplace.json +0 -0
  138. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.cursor/rules/test-data-privacy.mdc +0 -0
  139. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.editorconfig +0 -0
  140. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.env.example +0 -0
  141. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.gitattributes +0 -0
  142. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/CODEOWNERS +0 -0
  143. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  144. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  145. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/PULL_REQUEST_TEMPLATE/cli_command.md +0 -0
  146. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/PULL_REQUEST_TEMPLATE/release.md +0 -0
  147. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/dependabot.yml +0 -0
  148. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/labels.yml +0 -0
  149. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/mcp-release-install-footer.md +0 -0
  150. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/pull_request_template.md +0 -0
  151. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/release-install-footer.md +0 -0
  152. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/workflows/cowork-replay.yml +0 -0
  153. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/workflows/docs.yml +0 -0
  154. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/workflows/labels.yml +0 -0
  155. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/workflows/linkcheck.yml +0 -0
  156. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/workflows/openapi-validation.yml +0 -0
  157. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/workflows/plugin-release.yml +0 -0
  158. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/workflows/release-detect.yml +0 -0
  159. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/workflows/release.yml +0 -0
  160. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.github/workflows/version-check.yml +0 -0
  161. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.gitignore +0 -0
  162. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/.pre-commit-config.yaml +0 -0
  163. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/AGENTS.md +0 -0
  164. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/CODE_OF_CONDUCT.md +0 -0
  165. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/CONTRIBUTING.md +0 -0
  166. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/LICENSE +0 -0
  167. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/SECURITY.md +0 -0
  168. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/VERSIONING.md +0 -0
  169. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/__init__.py +0 -0
  170. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/_internal/__init__.py +0 -0
  171. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/_internal/keyfile.py +0 -0
  172. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/api_versions.py +0 -0
  173. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/__init__.py +0 -0
  174. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/__main__.py +0 -0
  175. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/_update_worker.py +0 -0
  176. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/click_compat.py +0 -0
  177. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/__init__.py +0 -0
  178. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/_entity_field.py +0 -0
  179. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/_entity_files_dump.py +0 -0
  180. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/_entity_files_read.py +0 -0
  181. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/_entity_files_upload.py +0 -0
  182. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/_list_entry_fields.py +0 -0
  183. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/_org_reads.py +0 -0
  184. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/_search_common.py +0 -0
  185. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/_v1_parsing.py +0 -0
  186. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/company_cmds.py +0 -0
  187. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/completion_cmd.py +0 -0
  188. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/config_cmds.py +0 -0
  189. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/entry_cmds.py +0 -0
  190. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/field_cmds.py +0 -0
  191. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/file_cmds.py +0 -0
  192. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/file_url_cmd.py +0 -0
  193. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/interaction_cmds.py +0 -0
  194. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/opportunity_cmds.py +0 -0
  195. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/org_read_cmds.py +0 -0
  196. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/person_cmds.py +0 -0
  197. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/query_cmd.py +0 -0
  198. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/relationship_strength_cmds.py +0 -0
  199. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/resolve_url_cmd.py +0 -0
  200. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/session_cmds.py +0 -0
  201. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/task_cmds.py +0 -0
  202. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/transcript_cmds.py +0 -0
  203. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/version_cmd.py +0 -0
  204. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/commands/whoami_cmd.py +0 -0
  205. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/config.py +0 -0
  206. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/constants.py +0 -0
  207. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/context.py +0 -0
  208. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/csv_utils.py +0 -0
  209. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/date_utils.py +0 -0
  210. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/decorators.py +0 -0
  211. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/errors.py +0 -0
  212. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/field_utils.py +0 -0
  213. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/formatters.py +0 -0
  214. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/help_json.py +0 -0
  215. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/interaction_utils.py +0 -0
  216. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/logging.py +0 -0
  217. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/mcp_limits.py +0 -0
  218. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/options.py +0 -0
  219. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/paths.py +0 -0
  220. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/progress.py +0 -0
  221. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/query/__init__.py +0 -0
  222. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/query/aggregates.py +0 -0
  223. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/query/cursor.py +0 -0
  224. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/query/dates.py +0 -0
  225. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/query/exceptions.py +0 -0
  226. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/query/executor.py +0 -0
  227. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/query/filters.py +0 -0
  228. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/query/models.py +0 -0
  229. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/query/output.py +0 -0
  230. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/query/parser.py +0 -0
  231. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/query/planner.py +0 -0
  232. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/query/progress.py +0 -0
  233. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/query/schema.py +0 -0
  234. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/render.py +0 -0
  235. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/resolve.py +0 -0
  236. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/resolvers.py +0 -0
  237. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/results.py +0 -0
  238. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/runner.py +0 -0
  239. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/serialization.py +0 -0
  240. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/session_cache.py +0 -0
  241. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/types.py +0 -0
  242. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/cli/update_check.py +0 -0
  243. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/clients/__init__.py +0 -0
  244. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/clients/http.py +0 -0
  245. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/clients/pipeline.py +0 -0
  246. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/compare.py +0 -0
  247. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/downloads.py +0 -0
  248. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/exceptions.py +0 -0
  249. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/field_resolve_utils.py +0 -0
  250. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/field_resolver.py +0 -0
  251. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/filters.py +0 -0
  252. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/hooks.py +0 -0
  253. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/models/interactions_v2.py +0 -0
  254. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/models/pagination.py +0 -0
  255. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/models/rate_limit_snapshot.py +0 -0
  256. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/models/relationships_v2.py +0 -0
  257. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/models/search.py +0 -0
  258. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/models/transcripts.py +0 -0
  259. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/policies.py +0 -0
  260. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/progress.py +0 -0
  261. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/py.typed +0 -0
  262. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/_dropdown_options.py +0 -0
  263. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/_field_listing.py +0 -0
  264. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/_field_updates.py +0 -0
  265. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/_org_reads.py +0 -0
  266. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/companies.py +0 -0
  267. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/opportunities.py +0 -0
  268. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/persons.py +0 -0
  269. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/search.py +0 -0
  270. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/tasks.py +0 -0
  271. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/affinity/services/transcripts.py +0 -0
  272. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/codecov.yml +0 -0
  273. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/cli-development-guide.md +0 -0
  274. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/ai-integrations/index.md +0 -0
  275. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/changelog.md +0 -0
  276. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/cli/index.md +0 -0
  277. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/cli/scripting.md +0 -0
  278. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/cli-reference.md +0 -0
  279. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/examples.md +0 -0
  280. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/getting-started.md +0 -0
  281. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/glossary.md +0 -0
  282. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/affinity-official-mcp-comparison.md +0 -0
  283. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/api-versions.md +0 -0
  284. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/authentication.md +0 -0
  285. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/claude-code-plugins.md +0 -0
  286. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/configuration.md +0 -0
  287. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/csv-export.md +0 -0
  288. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/datetime-handling.md +0 -0
  289. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/debugging-hooks.md +0 -0
  290. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/field-types-and-values.md +0 -0
  291. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/field-values.md +0 -0
  292. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/filtering.md +0 -0
  293. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/ids-and-types.md +0 -0
  294. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/models.md +0 -0
  295. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/opportunity-associations.md +0 -0
  296. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/performance.md +0 -0
  297. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/query-command.md +0 -0
  298. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/rate-limits.md +0 -0
  299. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/guides/sync-vs-async.md +0 -0
  300. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/index.md +0 -0
  301. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/mcp/index.md +0 -0
  302. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/client.md +0 -0
  303. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/exceptions.md +0 -0
  304. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/filters.md +0 -0
  305. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/models.md +0 -0
  306. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/query-language.md +0 -0
  307. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/services/companies.md +0 -0
  308. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/services/lists.md +0 -0
  309. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/services/opportunities.md +0 -0
  310. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/services/persons.md +0 -0
  311. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/services/tasks.md +0 -0
  312. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/services/v1/auth.md +0 -0
  313. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/services/v1/field-values.md +0 -0
  314. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/services/v1/fields.md +0 -0
  315. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/services/v1/interactions.md +0 -0
  316. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/services/v1/relationships.md +0 -0
  317. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/reference/types.md +0 -0
  318. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/docs/public/troubleshooting.md +0 -0
  319. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/examples/advanced_usage.py +0 -0
  320. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/examples/async_lifecycle.py +0 -0
  321. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/examples/basic_usage.py +0 -0
  322. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/examples/filter_builder.py +0 -0
  323. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/examples/hooks_debugging.py +0 -0
  324. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/examples/list_management.py +0 -0
  325. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/examples/resolve_helpers.py +0 -0
  326. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/examples/task_polling.py +0 -0
  327. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.claude-plugin/.gitignore +0 -0
  328. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.claude-plugin/skills/affinity-mcp-workflows/SKILL.md +0 -0
  329. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.claude-plugin/skills/pipeline-history/SKILL.md +0 -0
  330. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.claude-plugin/skills/query-language/SKILL.md +0 -0
  331. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.claude-plugin/skills/query-language/references/filter-operators.md +0 -0
  332. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.claude-plugin/skills/query-language/references/include-expand.md +0 -0
  333. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.claude-plugin/skills/query-language/references/output-formats.md +0 -0
  334. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.claude-plugin/skills/query-language/references/quantifiers.md +0 -0
  335. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.claude-plugin/xaffinity-mcp.sh +0 -0
  336. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.gitignore +0 -0
  337. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/handlers/completion.sh +0 -0
  338. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/handlers/lifecycle.sh +0 -0
  339. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/handlers/logging.sh +0 -0
  340. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/handlers/ping.sh +0 -0
  341. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/handlers/prompts.sh +0 -0
  342. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/handlers/resources.sh +0 -0
  343. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/handlers/roots.sh +0 -0
  344. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/handlers/tools.sh +0 -0
  345. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/auth.sh +0 -0
  346. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/capabilities.sh +0 -0
  347. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/cli/health.sh +0 -0
  348. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/completion.sh +0 -0
  349. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/file_read.sh +0 -0
  350. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/handler_helpers.sh +0 -0
  351. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/hash.sh +0 -0
  352. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/ids.sh +0 -0
  353. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/io.sh +0 -0
  354. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/json.sh +0 -0
  355. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/lock.sh +0 -0
  356. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/logging.sh +0 -0
  357. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/meta_env.sh +0 -0
  358. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/paginate.sh +0 -0
  359. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/path.sh +0 -0
  360. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/policy.sh +0 -0
  361. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/progress-passthrough.sh +0 -0
  362. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/progress.sh +0 -0
  363. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/prompts.sh +0 -0
  364. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/registry.sh +0 -0
  365. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/require.sh +0 -0
  366. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/resource_content.sh +0 -0
  367. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/resource_match.sh +0 -0
  368. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/resource_providers.sh +0 -0
  369. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/resources.sh +0 -0
  370. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/roots.sh +0 -0
  371. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/rpc.sh +0 -0
  372. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/spec.sh +0 -0
  373. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/ui-templates.sh +0 -0
  374. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/ui.sh +0 -0
  375. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/uri.sh +0 -0
  376. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/lib/validate.sh +0 -0
  377. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/providers/echo.sh +0 -0
  378. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/providers/file.sh +0 -0
  379. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/providers/git.sh +0 -0
  380. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/providers/https.sh +0 -0
  381. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/providers/ui.sh +0 -0
  382. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.mcp-bash/sdk/ui-sdk.sh +0 -0
  383. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.registry/prompts.json +0 -0
  384. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.registry/resource-templates.json +0 -0
  385. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.registry/resources.json +0 -0
  386. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/.registry/ui-resources.json +0 -0
  387. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/Makefile +0 -0
  388. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/README.md +0 -0
  389. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/completions/entity-name.sh +0 -0
  390. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/completions/list-name.sh +0 -0
  391. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/completions/status-value.sh +0 -0
  392. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/docs/DEBUGGING.md +0 -0
  393. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/icon.svg +0 -0
  394. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/lib/cache.sh +0 -0
  395. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/lib/cli-detect.sh +0 -0
  396. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/lib/cli-gateway.sh +0 -0
  397. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/lib/common.sh +0 -0
  398. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/lib/entity-types.sh +0 -0
  399. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/lib/field-resolution.sh +0 -0
  400. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/mcp-publisher.lock +0 -0
  401. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/mcpb.conf +0 -0
  402. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/change-status/change-status.completion.sh +0 -0
  403. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/change-status/change-status.meta.json +0 -0
  404. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/change-status/change-status.txt +0 -0
  405. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/interaction-brief/interaction-brief.meta.json +0 -0
  406. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/interaction-brief/interaction-brief.txt +0 -0
  407. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/log-call/log-call.meta.json +0 -0
  408. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/log-call/log-call.txt +0 -0
  409. {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
  410. {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
  411. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/log-message/log-message.meta.json +0 -0
  412. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/log-message/log-message.txt +0 -0
  413. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/pipeline-review/pipeline-review.completion.sh +0 -0
  414. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/pipeline-review/pipeline-review.meta.json +0 -0
  415. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/pipeline-review/pipeline-review.txt +0 -0
  416. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/prepare-briefing/prepare-briefing.meta.json +0 -0
  417. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/prepare-briefing/prepare-briefing.txt +0 -0
  418. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/warm-intro/warm-intro.meta.json +0 -0
  419. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/prompts/warm-intro/warm-intro.txt +0 -0
  420. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/providers/xaffinity.sh +0 -0
  421. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/data-model/data-model.md +0 -0
  422. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/data-model/data-model.meta.json +0 -0
  423. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/field-catalogs/field-catalogs.meta.json +0 -0
  424. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/field-catalogs/field-catalogs.sh +0 -0
  425. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/interaction-enums/interaction-enums.json +0 -0
  426. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/interaction-enums/interaction-enums.meta.json +0 -0
  427. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/me/me.meta.json +0 -0
  428. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/me/me.sh +0 -0
  429. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/me-person-id/me-person-id.meta.json +0 -0
  430. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/me-person-id/me-person-id.sh +0 -0
  431. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/query-guide/query-guide.meta.json +0 -0
  432. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/query-guide/query-guide.sh +0 -0
  433. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/saved-views/saved-views.meta.json +0 -0
  434. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/saved-views/saved-views.sh +0 -0
  435. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/workflow-config/workflow-config.meta.json +0 -0
  436. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/workflow-config/workflow-config.sh +0 -0
  437. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/workflows-guide/workflows-guide.meta.json +0 -0
  438. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/workflows-guide/workflows-guide.sh +0 -0
  439. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/xaffinity-field-catalogs.completion.sh +0 -0
  440. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/xaffinity-saved-views.completion.sh +0 -0
  441. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/resources/xaffinity-workflow-config.completion.sh +0 -0
  442. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/server.d/env.sh +0 -0
  443. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/server.d/health-checks.sh +0 -0
  444. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/server.json +0 -0
  445. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/test/README.md +0 -0
  446. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/test/test_env_update_check.sh +0 -0
  447. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/test-progress.sh +0 -0
  448. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/discover-commands/tool.meta.json +0 -0
  449. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/discover-commands/tool.sh +0 -0
  450. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/execute-read-command/tool.meta.json +0 -0
  451. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/execute-read-command/tool.sh +0 -0
  452. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/get-entity-dossier/tool.meta.json +0 -0
  453. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/get-entity-dossier/tool.sh +0 -0
  454. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/get-file-url/tool.meta.json +0 -0
  455. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/get-file-url/tool.sh +0 -0
  456. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/query/tool.meta.json +0 -0
  457. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/read-xaffinity-resource/tool.meta.json +0 -0
  458. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/tools/read-xaffinity-resource/tool.sh +0 -0
  459. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/user-config.json +0 -0
  460. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/xaffinity-mcp-env.sh +0 -0
  461. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/mcp/xaffinity-mcp.sh +0 -0
  462. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/xaffinity-cli/hooks/hooks.json +0 -0
  463. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/xaffinity-cli/skills/xaffinity-cli-usage/references/files-and-writes.md +0 -0
  464. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/xaffinity-cli/skills/xaffinity-cli-usage/references/filtering.md +0 -0
  465. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/xaffinity-cli/skills/xaffinity-cli-usage/references/history-and-activity.md +0 -0
  466. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/xaffinity-cli/skills/xaffinity-cli-usage/references/interactions.md +0 -0
  467. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/plugins/xaffinity-cli/skills/xaffinity-cli-usage/references/query-guide.md +0 -0
  468. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cli/query/test_cursor.py +0 -0
  469. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cli/test_company_create_dedup.py +0 -0
  470. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cli/test_company_ls_filter_rejection.py +0 -0
  471. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cli/test_formatters.py +0 -0
  472. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cli/test_output_formats_integration.py +0 -0
  473. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cli/test_person_create_dedup.py +0 -0
  474. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cli/test_person_ls_filter_rejection.py +0 -0
  475. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cli/test_query_filter_rejection.py +0 -0
  476. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cli/test_query_list_entry_relationships.py +0 -0
  477. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cli/test_query_list_export_parity.py +0 -0
  478. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cli/test_query_output_flattening.py +0 -0
  479. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cli/test_query_output_truncation.py +0 -0
  480. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cli/test_query_unreplied.py +0 -0
  481. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/conftest.py +0 -0
  482. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/.cowork-redact.json +0 -0
  483. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/fixtures/workdir-key/README.txt +0 -0
  484. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/fixtures/workdir-key/xaffinity-test-key +0 -0
  485. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/fixtures/workdir-nokey/README.txt +0 -0
  486. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/image/Dockerfile +0 -0
  487. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/image/fakeaff/build_fixtures.py +0 -0
  488. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/image/fakeaff/fixtures.json +0 -0
  489. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/image/fakeaff/server.py +0 -0
  490. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/image/xaffinity-wrapper.sh +0 -0
  491. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/privacy-allow.txt +0 -0
  492. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/record.sh +0 -0
  493. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/scenarios/company-lists-status.yaml +0 -0
  494. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/scenarios/hook-blocks-without-key.yaml +0 -0
  495. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/scenarios/status-history.yaml +0 -0
  496. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/sessions/no-key.yaml +0 -0
  497. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/cowork/sessions/with-key.yaml +0 -0
  498. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/field_write_mocks.py +0 -0
  499. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/fixtures/openapi/mini_openapi.json +0 -0
  500. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/fixtures/webhooks/field_value_updated.json +0 -0
  501. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/fixtures/webhooks/list_entry_created.json +0 -0
  502. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/fixtures/webhooks/organization_created.json +0 -0
  503. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/fixtures/webhooks/organization_merged.json +0 -0
  504. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/fixtures/webhooks/person_created.json +0 -0
  505. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/fixtures/webhooks/unknown_event.json +0 -0
  506. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/integration/README.md +0 -0
  507. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/integration/conftest.py +0 -0
  508. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/integration/setup_query_parity_data.py +0 -0
  509. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/integration/test_cli_writes.py +0 -0
  510. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/integration/test_query_parity_integration.py +0 -0
  511. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/integration/test_sdk_writes_runner.py +0 -0
  512. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/mcp/__init__.py +0 -0
  513. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/mcp/test_query_cursor.py +0 -0
  514. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/skill-evals/xaffinity-cli-usage-evals/evals.json +0 -0
  515. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/spec_guard.py +0 -0
  516. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_affinity_client_wrapper_additional_coverage.py +0 -0
  517. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_api_key_file_formats.py +0 -0
  518. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_api_key_resolution.py +0 -0
  519. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_api_version.py +0 -0
  520. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_api_version_per_operation.py +0 -0
  521. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_async_file_download_streaming.py +0 -0
  522. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_batch_get.py +0 -0
  523. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_api_version.py +0 -0
  524. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_column_limiting.py +0 -0
  525. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_command_context.py +0 -0
  526. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_company_cmds_coverage.py +0 -0
  527. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_company_get.py +0 -0
  528. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_config_cmds.py +0 -0
  529. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_context_coverage.py +0 -0
  530. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_date_utils.py +0 -0
  531. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_datetime_formatting.py +0 -0
  532. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_datetime_header_offsets.py +0 -0
  533. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_domain_linkification.py +0 -0
  534. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_dotenv_resolution.py +0 -0
  535. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_dropdown_field_writes.py +0 -0
  536. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_enriched_field_writes.py +0 -0
  537. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_entity_field_writes.py +0 -0
  538. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_entity_files_dump.py +0 -0
  539. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_entry_field.py +0 -0
  540. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_entry_field_batch_writes.py +0 -0
  541. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_entry_field_multi_value_limits.py +0 -0
  542. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_error_hints.py +0 -0
  543. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_error_rendering.py +0 -0
  544. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_field_history.py +0 -0
  545. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_field_history_bulk.py +0 -0
  546. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_field_utils.py +0 -0
  547. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_field_utils_coverage.py +0 -0
  548. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_field_utils_set_phase.py +0 -0
  549. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_field_value_humanization.py +0 -0
  550. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_file_url.py +0 -0
  551. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_files_ls.py +0 -0
  552. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_files_read.py +0 -0
  553. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_get_interaction_dates.py +0 -0
  554. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_help_json.py +0 -0
  555. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_interaction_date_chunking.py +0 -0
  556. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_interaction_utils.py +0 -0
  557. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_json_safety.py +0 -0
  558. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_list_export_entity_scope.py +0 -0
  559. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_list_export_field_refresh.py +0 -0
  560. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_list_export_filter_safety.py +0 -0
  561. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_list_export_truncation_meta.py +0 -0
  562. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_missing_coverage.py +0 -0
  563. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_multi_value_truncation_warnings.py +0 -0
  564. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_no_network_commands.py +0 -0
  565. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_opportunity_cmds_coverage.py +0 -0
  566. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_pager_logic.py +0 -0
  567. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_person_cmds_coverage.py +0 -0
  568. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_person_get.py +0 -0
  569. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_progress_manager.py +0 -0
  570. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_query_aggregates.py +0 -0
  571. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_query_cmd.py +0 -0
  572. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_query_cmd_coverage.py +0 -0
  573. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_query_dates.py +0 -0
  574. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_query_executor.py +0 -0
  575. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_query_expand_interactions.py +0 -0
  576. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_query_filters.py +0 -0
  577. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_query_integration.py +0 -0
  578. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_query_parser.py +0 -0
  579. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_query_planner.py +0 -0
  580. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_query_safety.py +0 -0
  581. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_query_schema.py +0 -0
  582. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_rate_limit_rendering.py +0 -0
  583. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_rate_limit_throttle.py +0 -0
  584. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_render_coverage.py +0 -0
  585. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_resolve_coverage.py +0 -0
  586. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_resolve_url_parsing.py +0 -0
  587. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_result_summary.py +0 -0
  588. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_safe_field_writes.py +0 -0
  589. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_search.py +0 -0
  590. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_serialization.py +0 -0
  591. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_session_cache.py +0 -0
  592. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_types.py +0 -0
  593. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_unreplied.py +0 -0
  594. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_update_check.py +0 -0
  595. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_cli_v1_parsing.py +0 -0
  596. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_companies_create_dedup.py +0 -0
  597. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_companies_filter_rejection.py +0 -0
  598. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_compare.py +0 -0
  599. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_env_helpers.py +0 -0
  600. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_exceptions_coverage.py +0 -0
  601. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_field_resolver.py +0 -0
  602. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_field_service_caching.py +0 -0
  603. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_field_types_c4.py +0 -0
  604. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_field_value_type.py +0 -0
  605. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_field_values_get_value.py +0 -0
  606. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_file_batch_get.py +0 -0
  607. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_file_download_streaming.py +0 -0
  608. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_file_list_batch.py +0 -0
  609. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_file_upload_helpers_and_validation.py +0 -0
  610. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_files_upload_returning_files.py +0 -0
  611. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_filters.py +0 -0
  612. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_generate_mcp_command_registry.py +0 -0
  613. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_get_fields_filter_includes.py +0 -0
  614. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_get_fields_pagination.py +0 -0
  615. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_get_first.py +0 -0
  616. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_hidden_field_values.py +0 -0
  617. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_hooks.py +0 -0
  618. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_http_client_additional_coverage.py +0 -0
  619. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_http_client_remaining_coverage.py +0 -0
  620. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_inbound_webhooks.py +0 -0
  621. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_integration_smoke.py +0 -0
  622. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_interaction_date_validation.py +0 -0
  623. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_interactions_and_files_regressions.py +0 -0
  624. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_isodatetime.py +0 -0
  625. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_list_entry_membership_and_opportunities.py +0 -0
  626. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_list_term.py +0 -0
  627. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_mcp_bundle_env_and_completions.py +0 -0
  628. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_mcp_entity_dossier.py +0 -0
  629. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_mcp_gateway_limits.py +0 -0
  630. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_mcp_history_bulk_gateway.py +0 -0
  631. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_mcp_limits.py +0 -0
  632. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_mcp_read_truncation.py +0 -0
  633. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_mcp_resource_scripts.py +0 -0
  634. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_models_v2_2026_fields.py +0 -0
  635. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_multi_value_limits.py +0 -0
  636. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_new_features.py +0 -0
  637. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_notes_v2.py +0 -0
  638. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_opportunities_filter_rejection.py +0 -0
  639. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_org_reads.py +0 -0
  640. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_pagination_iterators.py +0 -0
  641. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_persons_create_dedup.py +0 -0
  642. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_persons_filter_rejection.py +0 -0
  643. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_public_api.py +0 -0
  644. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_raw_pipeline_hook_events.py +0 -0
  645. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_sdk_interaction_dates.py +0 -0
  646. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_search.py +0 -0
  647. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_service_get_parameter_combinations.py +0 -0
  648. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_companies_coverage_gaps.py +0 -0
  649. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_dropdown_options.py +0 -0
  650. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_entity_field_updates.py +0 -0
  651. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_field_value_changes.py +0 -0
  652. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_list_entries_filter_paths.py +0 -0
  653. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_lists_coverage_gaps.py +0 -0
  654. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_opportunities_additional_coverage.py +0 -0
  655. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_opportunities_coverage_gaps.py +0 -0
  656. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_opportunities_tasks_additional_coverage.py +0 -0
  657. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_persons_companies_additional_coverage.py +0 -0
  658. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_services_v1_only_coverage_gaps.py +0 -0
  659. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_small_modules_coverage.py +0 -0
  660. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/test_spec_guard.py +0 -0
  661. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/unit/__init__.py +0 -0
  662. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tests/unit/test_exceptions.py +0 -0
  663. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tools/__init__.py +0 -0
  664. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tools/check_cli_patterns.py +0 -0
  665. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tools/generate_mcp_command_registry.py +0 -0
  666. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tools/generate_release_notes.py +0 -0
  667. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tools/generate_requirements_mapping.py +0 -0
  668. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tools/openapi_snapshots/2024-01-01.json +0 -0
  669. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tools/openapi_snapshots/2026-07-15.json +0 -0
  670. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tools/openapi_snapshots/2026-09-17.json +0 -0
  671. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tools/sync_mcp_bundle_env.py +0 -0
  672. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tools/sync_mcp_registry.py +0 -0
  673. {affinity_sdk-1.29.0 → affinity_sdk-2.0.0}/tools/sync_mcp_version.py +0 -0
  674. {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: 1.29.0
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 subscription
470
+ # Create a webhook (subscriptions is required; [] means every event type)
463
471
  webhook = client.webhooks.create(
464
472
  WebhookCreate(
465
- webhook_url="https://your-server.com/webhook",
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
- # List all webhooks (max 3 per instance)
475
- webhooks = client.webhooks.list()
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
- # Disable a webhook
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 | ✅ | ✅ | V1 |
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-only services like notes/reminders/webhooks/files).
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 subscription
409
+ # Create a webhook (subscriptions is required; [] means every event type)
402
410
  webhook = client.webhooks.create(
403
411
  WebhookCreate(
404
- webhook_url="https://your-server.com/webhook",
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
- # List all webhooks (max 3 per instance)
414
- webhooks = client.webhooks.list()
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
- # Disable a webhook
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 | ✅ | ✅ | V1 |
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-only services like notes/reminders/webhooks/files).
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("--owner-id", type=int, default=None, help="Owner id.")
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.strip()
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
- existing_content = (existing.content or "").strip()
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="Note type (plain-text, html, ai-notetaker, email-derived).",
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
- Note: The Affinity API escapes underscores in note content (e.g., "test_note"
552
- becomes "test\\_note"). This is server-side markdown escaping and cannot be
553
- prevented. If you need to search for or compare note content, account for
554
- this transformation.
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 "<b>Summary</b>" --type html --company-id 67890`
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
- note = client.notes.create(
601
- NoteCreate(
602
- content=content,
603
- type=parsed_type or NoteType.PLAIN_TEXT,
604
- person_ids=[PersonId(pid) for pid in person_ids],
605
- company_ids=[CompanyId(cid) for cid in company_ids],
606
- opportunity_ids=[OpportunityId(oid) for oid in opportunity_ids],
607
- parent_id=NoteId(parent_id) if parent_id else None,
608
- creator_id=UserId(creator_id) if creator_id is not None else None,
609
- created_at=created_at_value,
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={"note": _note_payload(note)},
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
- """Update a note."""
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
- note = client.notes.update(NoteId(note_id), NoteUpdate(content=content))
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={"content": content},
779
+ modifiers=modifiers,
661
780
  )
662
781
 
663
782
  return CommandOutput(
664
- data={"note": _note_payload(note)},
783
+ data={"note": _note_v2_payload(note)},
665
784
  context=cmd_context,
666
785
  api_called=True,
667
786
  )