pltr-cli 0.13.1__tar.gz → 0.14.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 (190) hide show
  1. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/PKG-INFO +1 -1
  2. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/pyproject.toml +1 -1
  3. pltr_cli-0.14.0/src/pltr/__init__.py +1 -0
  4. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/auth/oauth.py +10 -1
  5. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/auth/token.py +10 -1
  6. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/connectivity.py +121 -3
  7. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/folder.py +25 -4
  8. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/orchestration.py +25 -4
  9. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/project.py +61 -16
  10. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/resource.py +151 -47
  11. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_auth/test_oauth.py +100 -0
  12. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_auth/test_token.py +88 -0
  13. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_connectivity.py +155 -0
  14. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_folder.py +39 -0
  15. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_orchestration.py +96 -0
  16. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_project.py +86 -8
  17. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_resource.py +214 -30
  18. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/uv.lock +1 -1
  19. pltr_cli-0.13.1/src/pltr/__init__.py +0 -1
  20. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/.github/workflows/ci.yml +0 -0
  21. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/.github/workflows/claude-code-review.yml +0 -0
  22. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/.github/workflows/claude.yml +0 -0
  23. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/.github/workflows/publish.yml +0 -0
  24. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/.github/workflows/test-publish.yml +0 -0
  25. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/.gitignore +0 -0
  26. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/.pre-commit-config.yaml +0 -0
  27. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/CHANGELOG.md +0 -0
  28. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/CLAUDE.md +0 -0
  29. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/LICENSE +0 -0
  30. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/README.md +0 -0
  31. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/RELEASE.md +0 -0
  32. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/README.md +0 -0
  33. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/SKILL.md +0 -0
  34. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/admin-commands.md +0 -0
  35. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/aip-agents-commands.md +0 -0
  36. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/connectivity-commands.md +0 -0
  37. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/dataset-commands.md +0 -0
  38. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/filesystem-commands.md +0 -0
  39. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/functions-commands.md +0 -0
  40. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/language-models-commands.md +0 -0
  41. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/mediasets-commands.md +0 -0
  42. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/models-commands.md +0 -0
  43. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/ontology-commands.md +0 -0
  44. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/orchestration-commands.md +0 -0
  45. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/quick-start.md +0 -0
  46. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/sql-commands.md +0 -0
  47. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/reference/streams-commands.md +0 -0
  48. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/workflows/data-analysis.md +0 -0
  49. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/workflows/data-pipeline.md +0 -0
  50. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/claude_skill/workflows/permission-management.md +0 -0
  51. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/README.md +0 -0
  52. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/api/wrapper.md +0 -0
  53. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/examples/csv-upload.md +0 -0
  54. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/examples/gallery.md +0 -0
  55. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/features/dataset-transactions.md +0 -0
  56. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/migration/v2-pagination.md +0 -0
  57. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/pagination.md +0 -0
  58. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/user-guide/aliases.md +0 -0
  59. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/user-guide/authentication.md +0 -0
  60. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/user-guide/claude-skill.md +0 -0
  61. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/user-guide/commands.md +0 -0
  62. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/user-guide/quick-start.md +0 -0
  63. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/user-guide/troubleshooting.md +0 -0
  64. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/docs/user-guide/workflows.md +0 -0
  65. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/mypy.ini +0 -0
  66. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/scripts/release.py +0 -0
  67. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/__main__.py +0 -0
  68. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/auth/__init__.py +0 -0
  69. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/auth/base.py +0 -0
  70. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/auth/manager.py +0 -0
  71. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/auth/storage.py +0 -0
  72. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/cli.py +0 -0
  73. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/__init__.py +0 -0
  74. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/admin.py +0 -0
  75. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/aip_agents.py +0 -0
  76. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/alias.py +0 -0
  77. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/audit.py +0 -0
  78. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/completion.py +0 -0
  79. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/configure.py +0 -0
  80. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/connectivity.py +0 -0
  81. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/cp.py +0 -0
  82. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/data_health.py +0 -0
  83. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/dataset.py +0 -0
  84. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/folder.py +0 -0
  85. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/functions.py +0 -0
  86. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/language_models.py +0 -0
  87. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/mediasets.py +0 -0
  88. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/models.py +0 -0
  89. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/ontology.py +0 -0
  90. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/orchestration.py +0 -0
  91. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/project.py +0 -0
  92. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/resource.py +0 -0
  93. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/resource_role.py +0 -0
  94. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/shell.py +0 -0
  95. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/space.py +0 -0
  96. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/sql.py +0 -0
  97. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/streams.py +0 -0
  98. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/third_party_applications.py +0 -0
  99. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/verify.py +0 -0
  100. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/commands/widgets.py +0 -0
  101. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/config/__init__.py +0 -0
  102. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/config/aliases.py +0 -0
  103. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/config/profiles.py +0 -0
  104. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/config/settings.py +0 -0
  105. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/__init__.py +0 -0
  106. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/admin.py +0 -0
  107. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/aip_agents.py +0 -0
  108. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/audit.py +0 -0
  109. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/base.py +0 -0
  110. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/copy.py +0 -0
  111. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/data_health.py +0 -0
  112. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/dataset.py +0 -0
  113. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/functions.py +0 -0
  114. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/language_models.py +0 -0
  115. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/mediasets.py +0 -0
  116. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/models.py +0 -0
  117. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/ontology.py +0 -0
  118. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/resource_role.py +0 -0
  119. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/space.py +0 -0
  120. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/sql.py +0 -0
  121. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/streams.py +0 -0
  122. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/third_party_applications.py +0 -0
  123. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/services/widgets.py +0 -0
  124. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/utils/__init__.py +0 -0
  125. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/utils/alias_resolver.py +0 -0
  126. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/utils/completion.py +0 -0
  127. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/utils/formatting.py +0 -0
  128. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/utils/pagination.py +0 -0
  129. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/src/pltr/utils/progress.py +0 -0
  130. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/__init__.py +0 -0
  131. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/conftest.py +0 -0
  132. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/integration/README.md +0 -0
  133. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/integration/__init__.py +0 -0
  134. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/integration/conftest.py +0 -0
  135. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/integration/test_auth_flow.py +0 -0
  136. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/integration/test_cli_integration.py +0 -0
  137. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/integration/test_data_workflows.py +0 -0
  138. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/integration/test_data_workflows_simple.py +0 -0
  139. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/integration/test_simple_integration.py +0 -0
  140. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_auth/__init__.py +0 -0
  141. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_auth/test_base.py +0 -0
  142. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_auth/test_manager.py +0 -0
  143. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_auth/test_storage.py +0 -0
  144. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/__init__.py +0 -0
  145. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_admin.py +0 -0
  146. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_aip_agents.py +0 -0
  147. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_alias.py +0 -0
  148. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_audit.py +0 -0
  149. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_completion.py +0 -0
  150. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_connectivity.py +0 -0
  151. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_data_health.py +0 -0
  152. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_dataset.py +0 -0
  153. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_folder.py +0 -0
  154. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_functions.py +0 -0
  155. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_language_models.py +0 -0
  156. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_mediasets.py +0 -0
  157. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_models.py +0 -0
  158. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_ontology.py +0 -0
  159. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_orchestration.py +0 -0
  160. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_shell.py +0 -0
  161. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_sql.py +0 -0
  162. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_streams.py +0 -0
  163. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_third_party_applications.py +0 -0
  164. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_verify_simple.py +0 -0
  165. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_commands/test_widgets.py +0 -0
  166. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_config/__init__.py +0 -0
  167. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_config/test_aliases.py +0 -0
  168. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_config/test_profiles.py +0 -0
  169. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_config/test_settings.py +0 -0
  170. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/__init__.py +0 -0
  171. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_admin.py +0 -0
  172. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_aip_agents.py +0 -0
  173. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_base.py +0 -0
  174. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_copy.py +0 -0
  175. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_data_health.py +0 -0
  176. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_dataset.py +0 -0
  177. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_dataset_transactions.py +0 -0
  178. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_functions.py +0 -0
  179. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_language_models.py +0 -0
  180. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_mediasets.py +0 -0
  181. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_models.py +0 -0
  182. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_ontology.py +0 -0
  183. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_pagination_integration.py +0 -0
  184. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_resource_role.py +0 -0
  185. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_space.py +0 -0
  186. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_sql.py +0 -0
  187. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_services/test_streams.py +0 -0
  188. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_utils/__init__.py +0 -0
  189. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_utils/test_alias_resolver.py +0 -0
  190. {pltr_cli-0.13.1 → pltr_cli-0.14.0}/tests/test_utils/test_pagination.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pltr-cli
3
- Version: 0.13.1
3
+ Version: 0.14.0
4
4
  Summary: Command-line interface for Palantir Foundry APIs
5
5
  Project-URL: Homepage, https://github.com/anjor/pltr-cli
6
6
  Project-URL: Repository, https://github.com/anjor/pltr-cli
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pltr-cli"
3
- version = "0.13.1"
3
+ version = "0.14.0"
4
4
  description = "Command-line interface for Palantir Foundry APIs"
5
5
  authors = [
6
6
  { name = "anjor", email = "anjor@umd.edu" },
@@ -0,0 +1 @@
1
+ __version__ = "0.14.0"
@@ -54,7 +54,16 @@ class OAuthClientProvider(AuthProvider):
54
54
  client_secret=self.client_secret, # type: ignore
55
55
  scopes=self.scopes,
56
56
  )
57
- return FoundryClient(auth=auth, hostname=self.host)
57
+ # Newer SDKs may support client-level preview mode while older ones do not.
58
+ # Try the preview-aware constructor first, then fall back for compatibility.
59
+ try:
60
+ return FoundryClient( # type: ignore[call-arg]
61
+ auth=auth, hostname=self.host, preview=True
62
+ )
63
+ except TypeError as e:
64
+ if "preview" not in str(e):
65
+ raise
66
+ return FoundryClient(auth=auth, hostname=self.host)
58
67
 
59
68
  def validate(self) -> bool:
60
69
  """Validate authentication credentials."""
@@ -32,7 +32,16 @@ class TokenAuthProvider(AuthProvider):
32
32
  from foundry_sdk import FoundryClient, UserTokenAuth
33
33
 
34
34
  auth = UserTokenAuth(token=self.token) # type: ignore
35
- return FoundryClient(auth=auth, hostname=self.host)
35
+ # Newer SDKs may support client-level preview mode while older ones do not.
36
+ # Try the preview-aware constructor first, then fall back for compatibility.
37
+ try:
38
+ return FoundryClient( # type: ignore[call-arg]
39
+ auth=auth, hostname=self.host, preview=True
40
+ )
41
+ except TypeError as e:
42
+ if "preview" not in str(e):
43
+ raise
44
+ return FoundryClient(auth=auth, hostname=self.host)
36
45
 
37
46
  def validate(self) -> bool:
38
47
  """Validate authentication credentials."""
@@ -2,14 +2,22 @@
2
2
  Connectivity service wrapper for Foundry SDK.
3
3
  """
4
4
 
5
+ import logging
6
+ import os
7
+ from collections import deque
5
8
  from typing import Any, Optional, Dict, List
6
9
 
7
10
  from .base import BaseService
8
11
 
12
+ logger = logging.getLogger(__name__)
13
+
9
14
 
10
15
  class ConnectivityService(BaseService):
11
16
  """Service wrapper for Foundry connectivity operations."""
12
17
 
18
+ DEFAULT_FILESYSTEM_FALLBACK_START_FOLDER_RID = "ri.compass.main.folder.0"
19
+ MAX_FALLBACK_FOLDERS = 1000
20
+
13
21
  def _get_service(self) -> Any:
14
22
  """Get the Foundry client for connectivity operations."""
15
23
  return self.client
@@ -17,7 +25,15 @@ class ConnectivityService(BaseService):
17
25
  @property
18
26
  def connections_service(self) -> Any:
19
27
  """Get the connections service from the client."""
20
- return self.client.connections
28
+ # Prefer legacy namespace first for backward compatibility with older SDKs.
29
+ legacy_connections = getattr(self.client, "connections", None)
30
+ if legacy_connections is not None:
31
+ return legacy_connections
32
+
33
+ connectivity = getattr(self.client, "connectivity", None)
34
+ if connectivity is None:
35
+ raise RuntimeError("Connectivity service is not available on the client")
36
+ return connectivity
21
37
 
22
38
  @property
23
39
  def file_imports_service(self) -> Any:
@@ -37,8 +53,17 @@ class ConnectivityService(BaseService):
37
53
  List of connection information dictionaries
38
54
  """
39
55
  try:
40
- connections = self.connections_service.Connection.list()
41
- return [self._format_connection_info(conn) for conn in connections]
56
+ connection_client = self.connections_service.Connection
57
+ if hasattr(connection_client, "list"):
58
+ connections = connection_client.list()
59
+ return [self._format_connection_info(conn) for conn in connections]
60
+
61
+ logger.warning(
62
+ "Connection.list() is unavailable; falling back to filesystem scan. "
63
+ "Set PLTR_CONNECTIONS_FALLBACK_START_FOLDER_RID to a narrower folder "
64
+ "if this is slow."
65
+ )
66
+ return self._list_connections_from_filesystem()
42
67
  except Exception as e:
43
68
  raise RuntimeError(f"Failed to list connections: {e}")
44
69
 
@@ -384,6 +409,17 @@ class ConnectivityService(BaseService):
384
409
  Formatted connection dictionary
385
410
  """
386
411
  try:
412
+ if isinstance(connection, dict):
413
+ return {
414
+ "rid": connection.get("rid", "N/A"),
415
+ "display_name": connection.get("display_name", "N/A"),
416
+ "description": connection.get("description", ""),
417
+ "connection_type": connection.get("connection_type", "N/A"),
418
+ "status": connection.get("status", "N/A"),
419
+ "created_time": connection.get("created_time", "N/A"),
420
+ "modified_time": connection.get("modified_time", "N/A"),
421
+ }
422
+
387
423
  return {
388
424
  "rid": getattr(connection, "rid", "N/A"),
389
425
  "display_name": getattr(connection, "display_name", "N/A"),
@@ -396,6 +432,88 @@ class ConnectivityService(BaseService):
396
432
  except Exception:
397
433
  return {"raw": str(connection)}
398
434
 
435
+ def _list_connections_from_filesystem(self) -> List[Dict[str, Any]]:
436
+ """
437
+ Discover connection resources from filesystem when SDK list() is unavailable.
438
+
439
+ Notes:
440
+ - Uses Folder.children(preview=True), which requires preview access.
441
+ - Traversal starts from PLTR_CONNECTIONS_FALLBACK_START_FOLDER_RID when set,
442
+ otherwise defaults to ri.compass.main.folder.0.
443
+ """
444
+ filesystem = getattr(self.client, "filesystem", None)
445
+ if filesystem is None or not hasattr(filesystem, "Folder"):
446
+ raise RuntimeError(
447
+ "Connection.list() is unavailable and filesystem fallback is not supported"
448
+ )
449
+
450
+ folder_client = filesystem.Folder
451
+ start_folder_rid = os.environ.get(
452
+ "PLTR_CONNECTIONS_FALLBACK_START_FOLDER_RID",
453
+ self.DEFAULT_FILESYSTEM_FALLBACK_START_FOLDER_RID,
454
+ )
455
+ pending_folders = deque([start_folder_rid])
456
+ visited_folders: set[str] = set()
457
+ discovered_connections: List[Dict[str, Any]] = []
458
+
459
+ while pending_folders and len(visited_folders) < self.MAX_FALLBACK_FOLDERS:
460
+ folder_rid = pending_folders.popleft()
461
+ if folder_rid in visited_folders:
462
+ continue
463
+ visited_folders.add(folder_rid)
464
+
465
+ try:
466
+ children = folder_client.children(folder_rid, preview=True)
467
+ except Exception as error:
468
+ if folder_rid == start_folder_rid:
469
+ raise RuntimeError(
470
+ f"Unable to list fallback start folder '{start_folder_rid}': {error}"
471
+ ) from error
472
+ logger.debug(
473
+ "Skipping folder '%s' during connection discovery due to error: %s",
474
+ folder_rid,
475
+ error,
476
+ )
477
+ continue
478
+
479
+ for child in children:
480
+ child_rid = getattr(child, "rid", None)
481
+ if not child_rid:
482
+ continue
483
+
484
+ child_type = str(getattr(child, "type", "") or "").lower()
485
+ if self._looks_like_connection_resource(child_rid, child_type):
486
+ discovered_connections.append(
487
+ {
488
+ "rid": child_rid,
489
+ "display_name": getattr(child, "display_name", "N/A"),
490
+ "description": getattr(child, "description", ""),
491
+ "connection_type": child_type or "connection",
492
+ "status": getattr(child, "status", "N/A"),
493
+ "created_time": getattr(child, "created_time", "N/A"),
494
+ "modified_time": getattr(child, "modified_time", "N/A"),
495
+ }
496
+ )
497
+ continue
498
+
499
+ if child_type in {"folder", "compass_folder", "project", "space"}:
500
+ pending_folders.append(child_rid)
501
+
502
+ if pending_folders:
503
+ raise RuntimeError(
504
+ "Connection discovery exceeded folder scan limit "
505
+ f"({self.MAX_FALLBACK_FOLDERS}). "
506
+ "Set PLTR_CONNECTIONS_FALLBACK_START_FOLDER_RID to a narrower folder "
507
+ "and retry."
508
+ )
509
+
510
+ return discovered_connections
511
+
512
+ @staticmethod
513
+ def _looks_like_connection_resource(resource_rid: str, resource_type: str) -> bool:
514
+ """Best-effort detection for connection resources from filesystem entries."""
515
+ return "connection" in resource_type or ".connection." in resource_rid
516
+
399
517
  def _format_import_info(self, import_obj: Any) -> Dict[str, Any]:
400
518
  """
401
519
  Format import information for display.
@@ -37,7 +37,8 @@ class FolderService(BaseService):
37
37
  )
38
38
  return self._format_folder_info(folder)
39
39
  except Exception as e:
40
- raise RuntimeError(f"Failed to create folder '{display_name}': {e}")
40
+ detail = self._format_error_detail(e)
41
+ raise RuntimeError(f"Failed to create folder '{display_name}': {detail}")
41
42
 
42
43
  def get_folder(self, folder_rid: str) -> Dict[str, Any]:
43
44
  """
@@ -53,7 +54,8 @@ class FolderService(BaseService):
53
54
  folder = self.service.Folder.get(folder_rid, preview=True)
54
55
  return self._format_folder_info(folder)
55
56
  except Exception as e:
56
- raise RuntimeError(f"Failed to get folder {folder_rid}: {e}")
57
+ detail = self._format_error_detail(e)
58
+ raise RuntimeError(f"Failed to get folder {folder_rid}: {detail}")
57
59
 
58
60
  def list_children(
59
61
  self,
@@ -81,7 +83,10 @@ class FolderService(BaseService):
81
83
  children.append(self._format_resource_info(child))
82
84
  return children
83
85
  except Exception as e:
84
- raise RuntimeError(f"Failed to list children of folder {folder_rid}: {e}")
86
+ detail = self._format_error_detail(e)
87
+ raise RuntimeError(
88
+ f"Failed to list children of folder {folder_rid}: {detail}"
89
+ )
85
90
 
86
91
  def get_folders_batch(self, folder_rids: List[str]) -> List[Dict[str, Any]]:
87
92
  """
@@ -106,7 +111,8 @@ class FolderService(BaseService):
106
111
  folders.append(self._format_folder_info(folder))
107
112
  return folders
108
113
  except Exception as e:
109
- raise RuntimeError(f"Failed to get folders batch: {e}")
114
+ detail = self._format_error_detail(e)
115
+ raise RuntimeError(f"Failed to get folders batch: {detail}")
110
116
 
111
117
  def _format_folder_info(self, folder: Any) -> Dict[str, Any]:
112
118
  """
@@ -170,3 +176,18 @@ class FolderService(BaseService):
170
176
  if hasattr(timestamp, "time"):
171
177
  return str(timestamp.time)
172
178
  return str(timestamp)
179
+
180
+ @staticmethod
181
+ def _format_error_detail(error: Exception) -> str:
182
+ """Format exception details, including fallback for empty SDK error strings."""
183
+ message = str(error).strip()
184
+ if message:
185
+ return message
186
+
187
+ args = getattr(error, "args", ())
188
+ if args:
189
+ joined = " ".join(str(arg) for arg in args if arg is not None)
190
+ if joined:
191
+ return joined
192
+
193
+ return error.__class__.__name__
@@ -147,14 +147,14 @@ class OrchestrationService(BaseService):
147
147
  Search results with pagination info
148
148
  """
149
149
  try:
150
- kwargs: Dict[str, Any] = {}
150
+ kwargs: Dict[str, Any] = {"preview": True}
151
151
  if page_size is not None:
152
152
  kwargs["page_size"] = page_size
153
153
  if page_token is not None:
154
154
  kwargs["page_token"] = page_token
155
155
  kwargs.update(search_params)
156
156
 
157
- response = self.service.Build.search(**kwargs)
157
+ response = self._search_with_optional_preview(kwargs)
158
158
  return self._format_builds_search_response(response)
159
159
  except Exception as e:
160
160
  raise RuntimeError(f"Failed to search builds: {e}")
@@ -183,18 +183,39 @@ class OrchestrationService(BaseService):
183
183
  """Fetch a single page of builds."""
184
184
  kwargs: Dict[str, Any] = {
185
185
  "page_size": config.page_size or settings.get("page_size", 20),
186
+ "preview": True,
186
187
  }
187
188
  if page_token:
188
189
  kwargs["page_token"] = page_token
189
190
  kwargs.update(search_params)
190
191
 
191
- response = self.service.Build.search(**kwargs)
192
- return self._format_builds_search_response(response)
192
+ response = self._search_with_optional_preview(kwargs)
193
+ formatted = self._format_builds_search_response(response)
194
+ return {
195
+ "data": formatted.get("builds", []),
196
+ "next_page_token": formatted.get("next_page_token"),
197
+ }
193
198
 
194
199
  return self._paginate_response(fetch_page, config, progress_callback)
195
200
  except Exception as e:
196
201
  raise RuntimeError(f"Failed to search builds: {e}")
197
202
 
203
+ def _search_with_optional_preview(self, kwargs: Dict[str, Any]) -> Any:
204
+ """
205
+ Execute Build.search with preview compatibility fallback.
206
+
207
+ Some SDK versions reject the `preview` kwarg at call-time even if preview
208
+ mode is enabled via client defaults.
209
+ """
210
+ try:
211
+ return self.service.Build.search(**kwargs)
212
+ except TypeError as e:
213
+ if "preview" not in str(e):
214
+ raise
215
+ fallback_kwargs = dict(kwargs)
216
+ fallback_kwargs.pop("preview", None)
217
+ return self.service.Build.search(**fallback_kwargs)
218
+
198
219
  def get_builds_batch(self, build_rids: List[str]) -> Dict[str, Any]:
199
220
  """
200
221
  Get multiple builds in batch.
@@ -155,20 +155,30 @@ class ProjectService(BaseService):
155
155
  List of project information dictionaries
156
156
  """
157
157
  try:
158
- projects = []
159
- list_params: Dict[str, Any] = {"preview": True}
160
-
161
158
  if space_rid:
162
- list_params["space_rid"] = space_rid
163
- if page_size:
164
- list_params["page_size"] = page_size
165
- if page_token:
166
- list_params["page_token"] = page_token
159
+ return self._list_projects_in_parent(
160
+ parent_folder_rid=space_rid,
161
+ page_size=page_size,
162
+ page_token=page_token,
163
+ )
164
+
165
+ # page_size/page_token are cursor semantics for a single folder listing.
166
+ # They are not meaningful when aggregating projects across all spaces.
167
+ projects_by_rid: Dict[str, Dict[str, Any]] = {}
168
+ for space in self.service.Space.list(preview=True):
169
+ parent_space_rid = getattr(space, "rid", None)
170
+ if not parent_space_rid:
171
+ continue
172
+
173
+ projects = self._list_projects_in_parent(
174
+ parent_folder_rid=parent_space_rid
175
+ )
176
+ for project in projects:
177
+ rid = project.get("rid")
178
+ if rid:
179
+ projects_by_rid[rid] = project
167
180
 
168
- # The list method returns an iterator
169
- for project in self.service.Project.list(**list_params):
170
- projects.append(self._format_project_info(project))
171
- return projects
181
+ return list(projects_by_rid.values())
172
182
  except Exception as e:
173
183
  raise RuntimeError(f"Failed to list projects: {e}")
174
184
 
@@ -353,6 +363,14 @@ class ProjectService(BaseService):
353
363
  Returns:
354
364
  Formatted project information dictionary
355
365
  """
366
+ modified_by = getattr(project, "modified_by", None)
367
+ if modified_by is None:
368
+ modified_by = getattr(project, "updated_by", None)
369
+
370
+ modified_time = getattr(project, "modified_time", None)
371
+ if modified_time is None:
372
+ modified_time = getattr(project, "updated_time", None)
373
+
356
374
  return {
357
375
  "rid": getattr(project, "rid", None),
358
376
  "display_name": getattr(project, "display_name", None),
@@ -363,14 +381,41 @@ class ProjectService(BaseService):
363
381
  "created_time": self._format_timestamp(
364
382
  getattr(project, "created_time", None)
365
383
  ),
366
- "modified_by": getattr(project, "modified_by", None),
367
- "modified_time": self._format_timestamp(
368
- getattr(project, "modified_time", None)
369
- ),
384
+ "modified_by": modified_by,
385
+ "modified_time": self._format_timestamp(modified_time),
370
386
  "trash_status": getattr(project, "trash_status", None),
371
387
  "type": "project",
372
388
  }
373
389
 
390
+ def _list_projects_in_parent(
391
+ self,
392
+ parent_folder_rid: str,
393
+ page_size: Optional[int] = None,
394
+ page_token: Optional[str] = None,
395
+ ) -> List[Dict[str, Any]]:
396
+ """List project resources directly under a parent folder (space)."""
397
+ list_params: Dict[str, Any] = {"preview": True}
398
+ if page_size:
399
+ list_params["page_size"] = page_size
400
+ if page_token:
401
+ list_params["page_token"] = page_token
402
+
403
+ projects: List[Dict[str, Any]] = []
404
+ for resource in self.service.Folder.children(parent_folder_rid, **list_params):
405
+ if self._is_project_resource(resource):
406
+ projects.append(self._format_project_info(resource))
407
+ return projects
408
+
409
+ @staticmethod
410
+ def _is_project_resource(resource: Any) -> bool:
411
+ """Check whether a filesystem resource is a project."""
412
+ resource_type = str(getattr(resource, "type", "") or "").upper()
413
+ resource_rid = str(getattr(resource, "rid", "") or "")
414
+ # Fallback to canonical project RID prefix when type is missing.
415
+ return resource_type == "PROJECT" or resource_rid.startswith(
416
+ "ri.compass.main.project."
417
+ )
418
+
374
419
  def _format_organization_info(self, organization: Any) -> Dict[str, Any]:
375
420
  """
376
421
  Format organization information for consistent output.