mammoth-cli 2.1.4__tar.gz → 2.1.6__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 (249) hide show
  1. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/PKG-INFO +2 -2
  2. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/__init__.py +1 -1
  3. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/scheduling.md +5 -0
  4. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/activity.py +85 -2
  5. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/dashboard.py +41 -2
  6. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/dataset.py +41 -13
  7. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/folder.py +64 -8
  8. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/project.py +174 -53
  9. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/view.py +102 -14
  10. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/view_ops.py +25 -0
  11. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/view_profile.py +3 -2
  12. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/services/listing.py +53 -9
  13. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/services/read_queries.py +82 -1
  14. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/services/sdk_service.py +5 -1
  15. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/services/write_impact.py +85 -7
  16. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/pyproject.toml +2 -2
  17. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/dashboard.yaml +3 -3
  18. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/dataset.yaml +1 -1
  19. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/file.yaml +4 -1
  20. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/folder.yaml +2 -2
  21. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/project.yaml +1 -1
  22. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/sdk-methods.yaml +1 -1
  23. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/.gitignore +0 -0
  24. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/LICENSE +0 -0
  25. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/README.md +0 -0
  26. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/__main__.py +0 -0
  27. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/app.py +0 -0
  28. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/SKILL.md +0 -0
  29. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/about-mammoth.md +0 -0
  30. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/auth.md +0 -0
  31. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/capabilities-misc.md +0 -0
  32. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/capabilities.md +0 -0
  33. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/command-index.md +0 -0
  34. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/activity.md +0 -0
  35. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/addon.md +0 -0
  36. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/agent.md +0 -0
  37. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/ai.md +0 -0
  38. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/annotation.md +0 -0
  39. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/auth.md +0 -0
  40. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/automation.md +0 -0
  41. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/batch.md +0 -0
  42. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/billing.md +0 -0
  43. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/browse.md +0 -0
  44. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/calc.md +0 -0
  45. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/capability.md +0 -0
  46. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/client-app.md +0 -0
  47. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/completion.md +0 -0
  48. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/config.md +0 -0
  49. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/connector.md +0 -0
  50. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/context.md +0 -0
  51. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard-qa.md +0 -0
  52. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard-style.md +0 -0
  53. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard.md +0 -0
  54. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/data-app.md +0 -0
  55. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dataset.md +0 -0
  56. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/doctor.md +0 -0
  57. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/external-key.md +0 -0
  58. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/file.md +0 -0
  59. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/folder.md +0 -0
  60. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/job.md +0 -0
  61. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/log.md +0 -0
  62. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/notification.md +0 -0
  63. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/parameter.md +0 -0
  64. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/project.md +0 -0
  65. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/report.md +0 -0
  66. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/schedule.md +0 -0
  67. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/schema.md +0 -0
  68. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/skill.md +0 -0
  69. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/snippet.md +0 -0
  70. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/support.md +0 -0
  71. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/template.md +0 -0
  72. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/trash.md +0 -0
  73. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/upgrade.md +0 -0
  74. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/user.md +0 -0
  75. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/version.md +0 -0
  76. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/view-transform.md +0 -0
  77. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/view.md +0 -0
  78. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/webhook.md +0 -0
  79. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/workflow.md +0 -0
  80. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/workspace.md +0 -0
  81. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/handoff.md +0 -0
  82. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/input.md +0 -0
  83. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/jobs-drafts.md +0 -0
  84. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/machine-output.md +0 -0
  85. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/operations.md +0 -0
  86. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/auth-scope.md +0 -0
  87. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/cleanup.md +0 -0
  88. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/dashboards.md +0 -0
  89. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/end-to-end.md +0 -0
  90. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/exports.md +0 -0
  91. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/index.md +0 -0
  92. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/need-action.md +0 -0
  93. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/resources.md +0 -0
  94. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/transforms.md +0 -0
  95. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/typed-etl-discovery.md +0 -0
  96. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/recovery.md +0 -0
  97. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/report-checklist.md +0 -0
  98. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/retention.md +0 -0
  99. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/safety.md +0 -0
  100. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/bundled_skill/mammoth-cli/references/task-start.md +0 -0
  101. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/__init__.py +0 -0
  102. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/addon.py +0 -0
  103. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/agent.py +0 -0
  104. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/ai.py +0 -0
  105. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/annotation.py +0 -0
  106. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/auth.py +0 -0
  107. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/automation.py +0 -0
  108. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/batch.py +0 -0
  109. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/billing.py +0 -0
  110. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/browse.py +0 -0
  111. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/calc.py +0 -0
  112. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/capability.py +0 -0
  113. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/client_app.py +0 -0
  114. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/completion.py +0 -0
  115. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/config.py +0 -0
  116. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/connector.py +0 -0
  117. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/context.py +0 -0
  118. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/data_app.py +0 -0
  119. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/doctor.py +0 -0
  120. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/external_key.py +0 -0
  121. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/file.py +0 -0
  122. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/job.py +0 -0
  123. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/notification.py +0 -0
  124. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/parameter.py +0 -0
  125. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/registry.py +0 -0
  126. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/report.py +0 -0
  127. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/schedule.py +0 -0
  128. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/schema.py +0 -0
  129. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/skill.py +0 -0
  130. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/snippet.py +0 -0
  131. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/support.py +0 -0
  132. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/template.py +0 -0
  133. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/trash.py +0 -0
  134. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/upgrade.py +0 -0
  135. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/user.py +0 -0
  136. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/webhook.py +0 -0
  137. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/workflow.py +0 -0
  138. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/commands/workspace.py +0 -0
  139. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/context/__init__.py +0 -0
  140. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/context/credentials.py +0 -0
  141. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/context/endpoint.py +0 -0
  142. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/context/profiles.py +0 -0
  143. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/context/resolver.py +0 -0
  144. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/contracts/__init__.py +0 -0
  145. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/contracts/auth.py +0 -0
  146. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/embed.py +0 -0
  147. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/errors/__init__.py +0 -0
  148. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/errors/envelope.py +0 -0
  149. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/manifest/__init__.py +0 -0
  150. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/manifest/loader.py +0 -0
  151. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/messages/__init__.py +0 -0
  152. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/output/__init__.py +0 -0
  153. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/output/envelope.py +0 -0
  154. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/output/normalize.py +0 -0
  155. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/output/policy.py +0 -0
  156. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/output/progress.py +0 -0
  157. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/output/render.py +0 -0
  158. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/py.typed +0 -0
  159. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/runtime/__init__.py +0 -0
  160. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/runtime/confirm.py +0 -0
  161. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/runtime/dataset_health.py +0 -0
  162. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/runtime/dryrun.py +0 -0
  163. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/runtime/dryrun_targets.py +0 -0
  164. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/runtime/embedded.py +0 -0
  165. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/runtime/executor.py +0 -0
  166. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/runtime/input_loader.py +0 -0
  167. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/runtime/intent_only.py +0 -0
  168. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/runtime/invocation.py +0 -0
  169. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/runtime/new_data.py +0 -0
  170. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/runtime/options.py +0 -0
  171. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/runtime/parents.py +0 -0
  172. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/runtime/runlog.py +0 -0
  173. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/runtime/session.py +0 -0
  174. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/runtime/state.py +0 -0
  175. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/runtime/strict.py +0 -0
  176. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/runtime/updates.py +0 -0
  177. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/runtime/validate.py +0 -0
  178. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/runtime/verify.py +0 -0
  179. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/services/__init__.py +0 -0
  180. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/services/argspec.py +0 -0
  181. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/services/board_values.py +0 -0
  182. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/services/coerce.py +0 -0
  183. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/services/command_contract.py +0 -0
  184. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/services/conditions.py +0 -0
  185. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/services/dashboard_filters.py +0 -0
  186. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/services/dashboard_pages.py +0 -0
  187. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/services/dashboard_review.py +0 -0
  188. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/services/data_profile.py +0 -0
  189. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/services/data_quality.py +0 -0
  190. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/services/dispatch.py +0 -0
  191. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/services/factory.py +0 -0
  192. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/services/input_fields.py +0 -0
  193. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/services/mapping.py +0 -0
  194. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/services/openapi_types.py +0 -0
  195. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/services/positionals.py +0 -0
  196. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/services/protocol.py +0 -0
  197. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/services/stored_stats.py +0 -0
  198. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/services/testing.py +0 -0
  199. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/services/text_dates.py +0 -0
  200. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/services/type_system.py +0 -0
  201. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/skills/__init__.py +0 -0
  202. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/skills/installer.py +0 -0
  203. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/skills/steering.py +0 -0
  204. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/mammoth_cli/testing.py +0 -0
  205. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/activity.yaml +0 -0
  206. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/addon.yaml +0 -0
  207. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/agent.yaml +0 -0
  208. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/ai.yaml +0 -0
  209. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/annotation.yaml +0 -0
  210. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/auth.yaml +0 -0
  211. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/automation.yaml +0 -0
  212. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/batch.yaml +0 -0
  213. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/billing.yaml +0 -0
  214. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/browse.yaml +0 -0
  215. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/calc.yaml +0 -0
  216. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/capability.yaml +0 -0
  217. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/client-app.yaml +0 -0
  218. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/completion.yaml +0 -0
  219. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/config.yaml +0 -0
  220. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/connector.yaml +0 -0
  221. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/context.yaml +0 -0
  222. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/data-app.yaml +0 -0
  223. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/doctor.yaml +0 -0
  224. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/external-key.yaml +0 -0
  225. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/job.yaml +0 -0
  226. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/log.yaml +0 -0
  227. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/notification.yaml +0 -0
  228. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/parameter.yaml +0 -0
  229. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/report.yaml +0 -0
  230. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/schedule.yaml +0 -0
  231. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/schema.yaml +0 -0
  232. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/skill.yaml +0 -0
  233. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/snippet.yaml +0 -0
  234. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/support.yaml +0 -0
  235. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/template.yaml +0 -0
  236. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/trash.yaml +0 -0
  237. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/upgrade.yaml +0 -0
  238. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/user.yaml +0 -0
  239. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/version.yaml +0 -0
  240. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/view.yaml +0 -0
  241. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/webhook.yaml +0 -0
  242. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/workflow.yaml +0 -0
  243. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/commands/workspace.yaml +0 -0
  244. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/edits-target.source.yaml +0 -0
  245. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/openapi-operations.yaml +0 -0
  246. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/schema-v1.json +0 -0
  247. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/manifests/sdk-catalog.source.yaml +0 -0
  248. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/openapi/metadata.json +0 -0
  249. {mammoth_cli-2.1.4 → mammoth_cli-2.1.6}/spec/openapi/openapi.json +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mammoth-cli
3
- Version: 2.1.4
3
+ Version: 2.1.6
4
4
  Summary: Command-line interface for the Mammoth Analytics platform
5
5
  Project-URL: homepage, https://mammoth.io
6
6
  Project-URL: repository, https://github.com/EdgeMetric/mammothsdk
@@ -17,7 +17,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
17
17
  Requires-Python: <3.15,>=3.12
18
18
  Requires-Dist: jsonschema>=4.20
19
19
  Requires-Dist: keyring<26,>=25.7
20
- Requires-Dist: mammoth-io<0.9,>=0.8.1
20
+ Requires-Dist: mammoth-io<0.9,>=0.8.2
21
21
  Requires-Dist: platformdirs<5,>=4.10
22
22
  Requires-Dist: pydantic<3,>=2.12.5
23
23
  Requires-Dist: pyyaml<7,>=6
@@ -6,7 +6,7 @@ not implement a second HTTP client and does not call private SDK members.
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
- __version__ = "2.1.4"
9
+ __version__ = "2.1.6"
10
10
 
11
11
  # The versioned machine output envelope contract.
12
12
  SCHEMA_VERSION = 1
@@ -23,6 +23,11 @@ request:
23
23
  an id you already have (for example from a dataset's own automation/task
24
24
  metadata) instead.
25
25
 
26
+ PDF or image intake (`append_data` + `new_data_addition_in_folder`) needs one
27
+ destination dataset that already has a saved extraction recipe and a name
28
+ pattern the file name matches; a password-protected or unreadable file holds
29
+ for input. Read `automation capabilities` before you promise it.
30
+
26
31
  `schema find "recurring work"` phrasing (e.g. "schedule a daily refresh",
27
32
  "run every week automatically") resolves to `automation create`.
28
33
 
@@ -12,6 +12,7 @@ public SDK method named by the command's reviewed manifest ``sdk_symbol``.
12
12
  from __future__ import annotations
13
13
 
14
14
  import json
15
+ from datetime import UTC, datetime
15
16
  from typing import Any
16
17
 
17
18
  from mammoth_cli.errors.envelope import (
@@ -157,14 +158,96 @@ def _meta(invocation: Invocation, workspace_id: int, project_id: int | None) ->
157
158
  }
158
159
 
159
160
 
161
+ _WORKSPACE_USERS_SYMBOL = "mammoth.api.workspace.WorkspaceAPI.list_users"
162
+ _TIME_FORMAT = "%Y-%m-%d %H:%M:%S"
163
+ _EPOCH = "1970-01-01 00:00:00"
164
+
165
+
166
+ def _close_time_window(kwargs: dict[str, Any]) -> str | None:
167
+ """Give a lone ``start_time`` or ``end_time`` its missing bound; say so.
168
+
169
+ The backend applies the time filter only when BOTH bounds are present
170
+ (activity_logs/manager.py ``_get_time_filters``) and otherwise lists the
171
+ latest entries of all time -- so "what changed today" with only a
172
+ ``start_time`` answered from the wrong window.
173
+ """
174
+ start, end = kwargs.get("start_time"), kwargs.get("end_time")
175
+ if bool(start) == bool(end):
176
+ return None
177
+ if start:
178
+ kwargs["end_time"] = datetime.now(UTC).strftime(_TIME_FORMAT)
179
+ return f"end_time was not given; the window runs to now ({kwargs['end_time']} UTC)."
180
+ kwargs["start_time"] = _EPOCH
181
+ return f"start_time was not given; the window starts at {_EPOCH} UTC."
182
+
183
+
184
+ def _local_time(stamp: Any) -> str | None:
185
+ """A ``created_at`` (UTC if it has no offset) as ISO in this machine's timezone."""
186
+ if not isinstance(stamp, str):
187
+ return None
188
+ try:
189
+ moment = datetime.fromisoformat(stamp)
190
+ except ValueError:
191
+ return stamp
192
+ if moment.tzinfo is None:
193
+ moment = moment.replace(tzinfo=UTC)
194
+ return moment.astimezone().isoformat(timespec="seconds")
195
+
196
+
197
+ def _user_emails(service: Any) -> dict[Any, str]:
198
+ """Workspace users by id; empty when the caller may not list them."""
199
+ try:
200
+ users = service.call(_WORKSPACE_USERS_SYMBOL)
201
+ except Exception: # noqa: BLE001 -- a name is a convenience; the id is always shown
202
+ return {}
203
+ return {u["id"]: u["email"] for u in users if isinstance(u, dict) and u.get("email")}
204
+
205
+
206
+ def _change(entry: dict[str, Any], emails: dict[Any, str]) -> dict[str, Any]:
207
+ """One log entry as a line of a change list: when, who, what, on which object."""
208
+ details = entry.get("details") if isinstance(entry.get("details"), dict) else {}
209
+ primary = entry.get("primary_object") if isinstance(entry.get("primary_object"), dict) else {}
210
+ user_id = entry.get("user_id")
211
+ change = {
212
+ "when": _local_time(entry.get("created_at")),
213
+ "user_id": user_id,
214
+ "user": emails.get(user_id),
215
+ "action": entry.get("name_key"),
216
+ "category": entry.get("category"),
217
+ "object": {"name": primary.get("name"), "resource_id": primary.get("resource_id")},
218
+ "result": entry.get("result"),
219
+ }
220
+ if details.get("task_name"):
221
+ change["task"] = details["task_name"]
222
+ return change
223
+
224
+
225
+ def _with_changes(service: Any, data: Any, note: str | None) -> Any:
226
+ """Add ``changes``: each entry with its time, user and action (no entry dropped)."""
227
+ logs = data.get("activity_logs") if isinstance(data, dict) else None
228
+ if not isinstance(logs, list):
229
+ return data
230
+ emails = _user_emails(service)
231
+ changes = [_change(entry, emails) for entry in logs if isinstance(entry, dict)]
232
+ extra = {"time_window_note": note} if note else {}
233
+ return {**data, "changes": changes, **extra}
234
+
235
+
160
236
  def activity_list(invocation: Invocation) -> HandlerResult:
161
- """List activity logs in the active workspace, with optional filters."""
237
+ """List activity logs in the active workspace, with optional filters.
238
+
239
+ ``changes`` lists each entry with its ``when`` (ISO, this machine's UTC
240
+ offset), ``user_id`` and ``user``, ``action``, ``object`` and ``result``,
241
+ so "who changed this view today" is answered from the list, not from its
242
+ absence.
243
+ """
162
244
  document = _bound_document(invocation)
163
245
  _refuse_bare_resource_id(document)
164
246
  kwargs: dict[str, Any] = {}
165
247
  _forward_optional(document, kwargs, _LIST_OPTIONAL)
248
+ note = _close_time_window(kwargs)
166
249
  with open_service(invocation) as (service, auth):
167
- data = service.call(_symbol(invocation), **kwargs)
250
+ data = _with_changes(service, service.call(_symbol(invocation), **kwargs), note)
168
251
  return data, _meta(invocation, auth.workspace_id, resolved_project(invocation))
169
252
 
170
253
 
@@ -17,7 +17,7 @@ from typing import Any, Literal, cast
17
17
  from mammoth.models.dashboards import AddPagesSpec
18
18
  from pydantic import ValidationError
19
19
 
20
- from mammoth_cli.commands.view import view_profiles
20
+ from mammoth_cli.commands.view import _FIND_DATASET_SYMBOL, view_profiles
21
21
  from mammoth_cli.context import profiles
22
22
  from mammoth_cli.errors.envelope import (
23
23
  CODE_INVALID_ARGUMENT,
@@ -392,9 +392,48 @@ def dashboard_get(invocation: Invocation) -> HandlerResult:
392
392
  if not invocation.readback:
393
393
  data = _with_board_values(service, auth, {"dashboard_id": dashboard_id}, data)
394
394
  data = _with_board_project(data)
395
+ data = _with_source_datasets(service, invocation, auth.workspace_id, data)
395
396
  return data, _meta(invocation, auth.workspace_id)
396
397
 
397
398
 
399
+ def _source_dataset(service: Any, invocation: Invocation, workspace_id: Any, view_id: int) -> Any:
400
+ """The dataset that owns ``view_id``: remembered, else looked up; never raises."""
401
+ profile_name = invocation.profile or profiles.get_selected()
402
+ remembered = parents.lookup(profile_name, workspace_id, view_id)
403
+ if remembered is not None:
404
+ return {"view_id": view_id, "dataset_id": remembered}
405
+ try:
406
+ dataset_id = int(service.call(_FIND_DATASET_SYMBOL, dataview_id=view_id))
407
+ except Exception as exc: # noqa: BLE001 -- one unreadable source must not hide the others
408
+ return {"view_id": view_id, "dataset_id": None, "error": f"{type(exc).__name__}: {exc}"}
409
+ parents.remember(profile_name, workspace_id, {view_id: dataset_id})
410
+ return {"view_id": view_id, "dataset_id": dataset_id}
411
+
412
+
413
+ def _with_source_datasets(
414
+ service: Any, invocation: Invocation, workspace_id: Any, data: Any
415
+ ) -> Any:
416
+ """Label each source: a board's ``sources`` are VIEW ids, never dataset ids.
417
+
418
+ An agent read 3882 from ``sources`` as a dataset id and got a 403
419
+ (RT21-01). ``source_views`` gives each source's ``view_id`` and the
420
+ ``dataset_id`` that owns it.
421
+ """
422
+ sources = data.get("sources") if isinstance(data, dict) else None
423
+ if not isinstance(sources, list) or not sources:
424
+ return data
425
+ views = [
426
+ _source_dataset(service, invocation, workspace_id, view_id)
427
+ for view_id in sources
428
+ if isinstance(view_id, int)
429
+ ]
430
+ return {
431
+ **data,
432
+ "source_views": views,
433
+ "sources_note": "sources are view ids; use a source's dataset_id for dataset commands.",
434
+ }
435
+
436
+
398
437
  def _with_board_project(data: Any) -> Any:
399
438
  """Name the project the board lives in; ``None`` when the backend does not say."""
400
439
  data = _dump_model(data)
@@ -714,7 +753,7 @@ def _with_board_values(service: Any, auth: Any, positionals: dict[str, Any], dat
714
753
  data = _dump_model(data)
715
754
  if not isinstance(data, dict):
716
755
  return data
717
- dashboard_id = positionals.get("dashboard_id") or data.get("id") or data.get("dashboard_id")
756
+ dashboard_id = positionals.get("dashboard_id") or data.get("id")
718
757
  if not isinstance(dashboard_id, int):
719
758
  return {**data, "values": {"unavailable": "the result names no dashboard id"}}
720
759
  return {
@@ -32,8 +32,10 @@ from mammoth_cli.runtime.new_data import with_file_upload_path
32
32
  from mammoth_cli.runtime.session import open_service, require_project
33
33
  from mammoth_cli.services.listing import (
34
34
  DATASET_LIST_FIELDS,
35
+ ambiguity_note,
35
36
  dataset_summary,
36
37
  fit_budget,
38
+ name_hit,
37
39
  search_page,
38
40
  )
39
41
 
@@ -170,16 +172,31 @@ def _find_in_projects(
170
172
  {
171
173
  "project_id": project_id,
172
174
  "project_name": project.get("name"),
173
- "id": dataset.get("id"),
174
- "name": name,
175
+ **name_hit(dataset),
175
176
  }
176
177
  )
177
178
  return matches
178
179
 
179
180
 
180
- def _other_projects(service: Any, project_id: int) -> list[dict[str, Any]]:
181
+ def _other_projects(visible: list[dict[str, Any]], project_id: int) -> list[dict[str, Any]]:
181
182
  """Every visible project except ``project_id``."""
182
- return [p for p in _visible_projects(service) if p.get("id") != project_id]
183
+ return [p for p in visible if p.get("id") != project_id]
184
+
185
+
186
+ def named_project(service: Any, project_id: int, visible: list[dict[str, Any]]) -> dict[str, Any]:
187
+ """``{"id", "name"}`` of ``project_id``, so a match can say where it was found.
188
+
189
+ A search scoped by ``--project`` knew only the id, and its matches came back
190
+ with ``project_name: None``: the agent could not tell the user which project
191
+ held the dataset.
192
+ """
193
+ for project in visible:
194
+ if project.get("id") == project_id:
195
+ return project
196
+ record = service.call("mammoth.api.projects.ProjectsAPI.get", project_id=project_id)
197
+ record = record.model_dump(mode="json") if hasattr(record, "model_dump") else record
198
+ record = record.get("project", record) if isinstance(record, dict) else {}
199
+ return {"id": project_id, "name": record.get("name")}
183
200
 
184
201
 
185
202
  def dataset_find(invocation: Invocation) -> HandlerResult:
@@ -195,26 +212,30 @@ def dataset_find(invocation: Invocation) -> HandlerResult:
195
212
  name_substring = _require_string_positional(invocation, "name substring")
196
213
  needle = name_substring.lower()
197
214
  with open_service(invocation) as (service, auth):
215
+ visible = _visible_projects(service)
198
216
  if invocation.project is not None:
199
- projects: list[dict[str, Any]] = [{"id": invocation.project, "name": None}]
217
+ projects: list[dict[str, Any]] = [named_project(service, invocation.project, visible)]
200
218
  matches = _find_in_projects(service, needle, projects)
201
219
  if not matches:
202
- others = _other_projects(service, invocation.project)
220
+ others = _other_projects(visible, invocation.project)
203
221
  matches = _find_in_projects(service, needle, others)
204
222
  projects += others
205
223
  else:
206
- projects = _visible_projects(service)
224
+ projects = visible
207
225
  matches = _find_in_projects(service, needle, projects)
208
226
  meta = {
209
227
  "profile": invocation.profile,
210
228
  "workspace_id": auth.workspace_id,
211
229
  "project_id": invocation.project,
212
230
  }
213
- return {
231
+ result: dict[str, Any] = {
214
232
  "matches": matches,
215
233
  "projects_searched": len(projects),
216
234
  "projects_truncated": len(projects) >= _MAX_PROJECTS_SEARCHED,
217
- }, meta
235
+ }
236
+ if note := ambiguity_note(len(matches), name_substring):
237
+ result["note"] = note
238
+ return result, meta
218
239
 
219
240
 
220
241
  def dataset_list(invocation: Invocation) -> HandlerResult:
@@ -264,7 +285,7 @@ def _dataset_name_search(
264
285
  page = search_page(records, name, int(document.get("offset", 0)), document.get("limit"))
265
286
  if page["matched"] == 0:
266
287
  elsewhere = _find_in_projects(
267
- service, name.lower(), _other_projects(service, project_id)
288
+ service, name.lower(), _other_projects(_visible_projects(service), project_id)
268
289
  )
269
290
  if elsewhere:
270
291
  page["in_other_projects"] = elsewhere
@@ -504,14 +525,21 @@ def dataset_interpretation(invocation: Invocation) -> HandlerResult:
504
525
 
505
526
  ``--input`` carries ``user_instruction`` (plain English, e.g. one of the
506
527
  suggestions ``dataset get`` shows), a ``structure_map`` from an earlier
507
- preview, or a ``destination_dataset_id``; at least one is required.
528
+ preview, or a ``destination_dataset_id``; at least one is required. ``confirm``
529
+ alone also takes ``mode``: ``"original"`` keeps the file in its uploaded layout
530
+ (no other field then), ``"interpreted"`` is the default.
508
531
  """
509
532
  project_id = require_project(invocation)
510
533
  dataset_id = _require_int_positional(invocation, "dataset id")
511
534
  document = invocation.load_input() or {}
512
535
  kwargs: dict[str, Any] = {"dataset_id": dataset_id, "project_id": project_id}
513
- _forward_optional(document, kwargs, _INTERPRETATION_FIELDS)
514
- if not any(field in kwargs for field in _INTERPRETATION_FIELDS):
536
+ confirming = invocation.command_id == "dataset.interpretation.confirm"
537
+ _forward_optional(
538
+ document,
539
+ kwargs,
540
+ (*_INTERPRETATION_FIELDS, "mode") if confirming else _INTERPRETATION_FIELDS,
541
+ )
542
+ if not any(field in kwargs for field in (*_INTERPRETATION_FIELDS, "mode")):
515
543
  raise CliError(
516
544
  code=CODE_MISSING_ARGUMENT,
517
545
  message="Say how to read the file: pass one of " + ", ".join(_INTERPRETATION_FIELDS),
@@ -11,6 +11,7 @@ from __future__ import annotations
11
11
 
12
12
  from typing import Any
13
13
 
14
+ from mammoth_cli.commands.dataset import named_project
14
15
  from mammoth_cli.errors.envelope import (
15
16
  CODE_INVALID_ARGUMENT,
16
17
  CODE_MISSING_ARGUMENT,
@@ -121,11 +122,12 @@ def folder_find(invocation: Invocation) -> HandlerResult:
121
122
  needle = name_substring.lower()
122
123
  matches: list[dict[str, Any]] = []
123
124
  with open_service(invocation) as (service, auth):
125
+ listing = service.list_projects(limit=_MAX_PROJECTS_SEARCHED)
126
+ visible = list(listing.get("projects", [])) if isinstance(listing, dict) else []
124
127
  if invocation.project is not None:
125
- projects: list[dict[str, Any]] = [{"id": invocation.project, "name": None}]
128
+ projects: list[dict[str, Any]] = [named_project(service, invocation.project, visible)]
126
129
  else:
127
- listing = service.list_projects(limit=_MAX_PROJECTS_SEARCHED)
128
- projects = list(listing.get("projects", [])) if isinstance(listing, dict) else []
130
+ projects = visible
129
131
  for project in projects:
130
132
  project_id = project.get("id")
131
133
  if project_id is None:
@@ -136,8 +138,7 @@ def folder_find(invocation: Invocation) -> HandlerResult:
136
138
  response = service.call(
137
139
  "mammoth.api.folders.FoldersAPI.list", project_id=project_id, limit=100
138
140
  )
139
- folders = response.get("folders", []) if isinstance(response, dict) else []
140
- for folder in folders:
141
+ for folder in _folders_of(response):
141
142
  name = folder.get("name") if isinstance(folder, dict) else None
142
143
  if isinstance(name, str) and needle in name.lower():
143
144
  matches.append(
@@ -265,9 +266,7 @@ def folder_move(invocation: Invocation) -> HandlerResult:
265
266
  if not any(field in kwargs for field in ("resource_ids", "dataset_ids", "view_ids")):
266
267
  raise CliError(
267
268
  code=CODE_MISSING_FIELD,
268
- message=(
269
- "This command requires one of 'resource_ids', 'dataset_ids', " "or 'view_ids'."
270
- ),
269
+ message=("This command requires one of 'resource_ids', 'dataset_ids', or 'view_ids'."),
271
270
  exit_status=EXIT_USAGE,
272
271
  hint=(
273
272
  "Pass it via --input, e.g. "
@@ -275,10 +274,67 @@ def folder_move(invocation: Invocation) -> HandlerResult:
275
274
  ),
276
275
  )
277
276
  with open_service(invocation) as (service, auth):
277
+ _resolve_folder_fields(service, project_id, kwargs)
278
278
  data = service.call(_symbol(invocation), **kwargs)
279
279
  return data, _meta(invocation, auth.workspace_id, project_id)
280
280
 
281
281
 
282
+ _FOLDER_LIST_SYMBOL = "mammoth.api.folders.FoldersAPI.list"
283
+ _FOLDER_PAGE = 100
284
+
285
+
286
+ def _folders_of(page: Any) -> list[dict[str, Any]]:
287
+ """The folder records of a ``FoldersAPI.list`` page (a model or a dict)."""
288
+ page = page.model_dump(mode="json") if hasattr(page, "model_dump") else page
289
+ folders = page.get("folders", []) if isinstance(page, dict) else []
290
+ return [f for f in folders if isinstance(f, dict)]
291
+
292
+
293
+ def _project_folders(service: Any, project_id: int) -> list[dict[str, Any]]:
294
+ """Every folder of the project (``id`` and ``resource_id`` each), page by page."""
295
+ folders: list[dict[str, Any]] = []
296
+ while True:
297
+ page = service.call(
298
+ _FOLDER_LIST_SYMBOL, project_id=project_id, limit=_FOLDER_PAGE, offset=len(folders)
299
+ )
300
+ batch = _folders_of(page)
301
+ folders += batch
302
+ if len(batch) < _FOLDER_PAGE:
303
+ return folders
304
+
305
+
306
+ def _resolve_folder_fields(service: Any, project_id: int, kwargs: dict[str, Any]) -> None:
307
+ """Turn a folder's ``resource_id`` into the ``id`` the backend wants, in place.
308
+
309
+ ``target_folder_resource_id`` is named for a resource id but the backend
310
+ wants the folder's own ``id``. A value that is a folder's ``id`` is sent
311
+ as it is; one that is only some folder's ``resource_id`` is replaced by
312
+ that folder's ``id``; one that is both (two different folders) is refused.
313
+ """
314
+ for field in ("target_folder_resource_id", "source_folder_resource_id"):
315
+ value = kwargs.get(field)
316
+ if value in (None, "", "root"):
317
+ continue
318
+ folders = _project_folders(service, project_id)
319
+ by_id = [f for f in folders if str(f.get("id")) == str(value)]
320
+ by_resource = [f for f in folders if str(f.get("resource_id")) == str(value)]
321
+ if by_id and by_resource and by_id != by_resource:
322
+ raise CliError(
323
+ code=CODE_INVALID_ARGUMENT,
324
+ message=(
325
+ f"'{field}' {value} is the id of folder '{by_id[0].get('name')}' and the "
326
+ f"resource_id of folder '{by_resource[0].get('name')}'."
327
+ ),
328
+ exit_status=EXIT_USAGE,
329
+ hint=(
330
+ f"Pass the folder's id ({by_id[0].get('id')} or {by_resource[0].get('id')}) "
331
+ "as it appears in 'folder list'."
332
+ ),
333
+ )
334
+ if not by_id and by_resource:
335
+ kwargs[field] = by_resource[0].get("id")
336
+
337
+
282
338
  def folder_trash(invocation: Invocation) -> HandlerResult:
283
339
  """Move one folder to the project trash (reversible)."""
284
340
  project_id = require_project(invocation)