mammoth-cli 2.2.38__tar.gz → 2.2.40__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 (263) hide show
  1. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/PKG-INFO +2 -2
  2. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/__init__.py +1 -1
  3. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/app.py +2 -0
  4. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/SKILL.md +25 -23
  5. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/auth.md +14 -0
  6. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/capabilities.md +1 -1
  7. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/command-index.md +2 -1
  8. mammoth_cli-2.2.40/mammoth_cli/bundled_skill/mammoth-cli/references/commands/token.md +33 -0
  9. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/operations.md +6 -1
  10. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/auth.py +171 -10
  11. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/job.py +30 -0
  12. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/project.py +3 -0
  13. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/registry.py +74 -23
  14. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/view.py +142 -26
  15. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/context/credentials.py +92 -7
  16. mammoth_cli-2.2.40/mammoth_cli/context/oauth.py +473 -0
  17. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/context/resolver.py +13 -2
  18. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/errors/envelope.py +8 -0
  19. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/output/policy.py +1 -1
  20. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/output/render.py +30 -0
  21. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/dryrun_targets.py +3 -0
  22. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/command_contract.py +3 -0
  23. mammoth_cli-2.2.40/mammoth_cli/services/job_outcome.py +124 -0
  24. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/listing.py +43 -13
  25. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/mapping.py +28 -0
  26. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/positionals.py +36 -3
  27. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/protocol.py +9 -0
  28. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/read_queries.py +32 -3
  29. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/sdk_service.py +100 -21
  30. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/testing.py +11 -1
  31. mammoth_cli-2.2.40/mammoth_cli/services/view_analysis.py +92 -0
  32. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/skills/steering.py +2 -1
  33. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/pyproject.toml +2 -2
  34. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/job.yaml +4 -1
  35. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/project.yaml +1 -1
  36. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/schema.yaml +1 -1
  37. mammoth_cli-2.2.40/spec/manifests/commands/token.yaml +128 -0
  38. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/view.yaml +9 -5
  39. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/edits-target.source.yaml +1 -0
  40. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/sdk-methods.yaml +1 -1
  41. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/.gitignore +0 -0
  42. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/LICENSE +0 -0
  43. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/README.md +0 -0
  44. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/__main__.py +0 -0
  45. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/about-mammoth.md +0 -0
  46. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/capabilities-misc.md +0 -0
  47. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/activity.md +0 -0
  48. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/addon.md +0 -0
  49. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/agent.md +0 -0
  50. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/ai.md +0 -0
  51. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/annotation.md +0 -0
  52. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/auth.md +0 -0
  53. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/automation.md +0 -0
  54. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/batch.md +0 -0
  55. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/billing.md +0 -0
  56. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/browse.md +0 -0
  57. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/calc.md +0 -0
  58. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/capability.md +0 -0
  59. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/client-app.md +0 -0
  60. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/completion.md +0 -0
  61. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/config.md +0 -0
  62. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/connector.md +0 -0
  63. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/context.md +0 -0
  64. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard-qa.md +0 -0
  65. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard-style.md +0 -0
  66. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard-template.md +0 -0
  67. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard.md +0 -0
  68. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/data-app.md +0 -0
  69. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dataset.md +0 -0
  70. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/doctor.md +0 -0
  71. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/external-key.md +0 -0
  72. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/file.md +0 -0
  73. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/folder.md +0 -0
  74. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/job.md +0 -0
  75. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/link.md +0 -0
  76. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/log.md +0 -0
  77. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/notification.md +0 -0
  78. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/parameter.md +0 -0
  79. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/project.md +0 -0
  80. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/report.md +0 -0
  81. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/schedule.md +0 -0
  82. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/schema.md +0 -0
  83. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/skill.md +0 -0
  84. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/snippet.md +0 -0
  85. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/support.md +0 -0
  86. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/template.md +0 -0
  87. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/trash.md +0 -0
  88. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/upgrade.md +0 -0
  89. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/user.md +0 -0
  90. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/version.md +0 -0
  91. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/view-transform.md +0 -0
  92. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/view.md +0 -0
  93. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/webhook.md +0 -0
  94. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/workflow.md +0 -0
  95. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/workspace.md +0 -0
  96. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/handoff.md +0 -0
  97. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/input.md +0 -0
  98. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/jobs-drafts.md +0 -0
  99. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/machine-output.md +0 -0
  100. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/auth-scope.md +0 -0
  101. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/cleanup.md +0 -0
  102. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/dashboards.md +0 -0
  103. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/database-import.md +0 -0
  104. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/end-to-end.md +0 -0
  105. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/exports.md +0 -0
  106. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/index.md +0 -0
  107. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/need-action.md +0 -0
  108. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/resources.md +0 -0
  109. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/scheduling.md +0 -0
  110. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/transforms.md +0 -0
  111. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/typed-etl-discovery.md +0 -0
  112. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/recovery.md +0 -0
  113. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/report-checklist.md +0 -0
  114. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/retention.md +0 -0
  115. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/safety.md +0 -0
  116. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/task-start.md +0 -0
  117. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/__init__.py +0 -0
  118. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/activity.py +0 -0
  119. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/addon.py +0 -0
  120. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/agent.py +0 -0
  121. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/ai.py +0 -0
  122. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/annotation.py +0 -0
  123. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/automation.py +0 -0
  124. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/batch.py +0 -0
  125. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/billing.py +0 -0
  126. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/browse.py +0 -0
  127. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/calc.py +0 -0
  128. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/capability.py +0 -0
  129. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/client_app.py +0 -0
  130. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/completion.py +0 -0
  131. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/config.py +0 -0
  132. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/connector.py +0 -0
  133. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/context.py +0 -0
  134. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/dashboard.py +0 -0
  135. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/data_app.py +0 -0
  136. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/dataset.py +0 -0
  137. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/doctor.py +0 -0
  138. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/external_key.py +0 -0
  139. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/file.py +0 -0
  140. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/folder.py +0 -0
  141. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/link.py +0 -0
  142. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/notification.py +0 -0
  143. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/parameter.py +0 -0
  144. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/report.py +0 -0
  145. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/schedule.py +0 -0
  146. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/schema.py +0 -0
  147. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/skill.py +0 -0
  148. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/snippet.py +0 -0
  149. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/support.py +0 -0
  150. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/template.py +0 -0
  151. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/trash.py +0 -0
  152. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/upgrade.py +0 -0
  153. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/user.py +0 -0
  154. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/view_ops.py +0 -0
  155. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/view_profile.py +0 -0
  156. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/webhook.py +0 -0
  157. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/workflow.py +0 -0
  158. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/workspace.py +0 -0
  159. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/context/__init__.py +0 -0
  160. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/context/endpoint.py +0 -0
  161. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/context/profiles.py +0 -0
  162. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/contracts/__init__.py +0 -0
  163. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/contracts/auth.py +0 -0
  164. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/embed.py +0 -0
  165. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/errors/__init__.py +0 -0
  166. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/manifest/__init__.py +0 -0
  167. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/manifest/loader.py +0 -0
  168. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/messages/__init__.py +0 -0
  169. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/output/__init__.py +0 -0
  170. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/output/envelope.py +0 -0
  171. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/output/normalize.py +0 -0
  172. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/output/progress.py +0 -0
  173. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/py.typed +0 -0
  174. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/__init__.py +0 -0
  175. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/confirm.py +0 -0
  176. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/dataset_health.py +0 -0
  177. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/dryrun.py +0 -0
  178. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/embedded.py +0 -0
  179. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/executor.py +0 -0
  180. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/input_loader.py +0 -0
  181. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/intent_only.py +0 -0
  182. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/invocation.py +0 -0
  183. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/new_data.py +0 -0
  184. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/options.py +0 -0
  185. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/parents.py +0 -0
  186. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/runlog.py +0 -0
  187. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/session.py +0 -0
  188. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/state.py +0 -0
  189. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/strict.py +0 -0
  190. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/updates.py +0 -0
  191. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/validate.py +0 -0
  192. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/verify.py +0 -0
  193. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/__init__.py +0 -0
  194. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/append_blank_columns.py +0 -0
  195. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/argspec.py +0 -0
  196. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/board_values.py +0 -0
  197. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/coerce.py +0 -0
  198. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/conditional_format.py +0 -0
  199. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/conditions.py +0 -0
  200. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/dashboard_filters.py +0 -0
  201. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/dashboard_pages.py +0 -0
  202. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/dashboard_review.py +0 -0
  203. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/data_profile.py +0 -0
  204. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/data_quality.py +0 -0
  205. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/dispatch.py +0 -0
  206. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/factory.py +0 -0
  207. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/input_fields.py +0 -0
  208. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/local_time.py +0 -0
  209. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/openapi_types.py +0 -0
  210. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/sql_check.py +0 -0
  211. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/stored_stats.py +0 -0
  212. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/text_dates.py +0 -0
  213. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/type_system.py +0 -0
  214. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/write_impact.py +0 -0
  215. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/skills/__init__.py +0 -0
  216. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/skills/installer.py +0 -0
  217. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/testing.py +0 -0
  218. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/activity.yaml +0 -0
  219. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/addon.yaml +0 -0
  220. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/agent.yaml +0 -0
  221. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/ai.yaml +0 -0
  222. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/annotation.yaml +0 -0
  223. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/auth.yaml +0 -0
  224. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/automation.yaml +0 -0
  225. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/batch.yaml +0 -0
  226. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/billing.yaml +0 -0
  227. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/browse.yaml +0 -0
  228. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/calc.yaml +0 -0
  229. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/capability.yaml +0 -0
  230. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/client-app.yaml +0 -0
  231. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/completion.yaml +0 -0
  232. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/config.yaml +0 -0
  233. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/connector.yaml +0 -0
  234. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/context.yaml +0 -0
  235. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/dashboard.yaml +0 -0
  236. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/data-app.yaml +0 -0
  237. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/dataset.yaml +0 -0
  238. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/doctor.yaml +0 -0
  239. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/external-key.yaml +0 -0
  240. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/file.yaml +0 -0
  241. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/folder.yaml +0 -0
  242. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/link.yaml +0 -0
  243. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/log.yaml +0 -0
  244. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/notification.yaml +0 -0
  245. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/parameter.yaml +0 -0
  246. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/report.yaml +0 -0
  247. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/schedule.yaml +0 -0
  248. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/skill.yaml +0 -0
  249. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/snippet.yaml +0 -0
  250. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/support.yaml +0 -0
  251. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/template.yaml +0 -0
  252. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/trash.yaml +0 -0
  253. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/upgrade.yaml +0 -0
  254. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/user.yaml +0 -0
  255. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/version.yaml +0 -0
  256. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/webhook.yaml +0 -0
  257. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/workflow.yaml +0 -0
  258. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/workspace.yaml +0 -0
  259. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/openapi-operations.yaml +0 -0
  260. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/schema-v1.json +0 -0
  261. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/sdk-catalog.source.yaml +0 -0
  262. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/openapi/metadata.json +0 -0
  263. {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/openapi/openapi.json +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mammoth-cli
3
- Version: 2.2.38
3
+ Version: 2.2.40
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.20
20
+ Requires-Dist: mammoth-io<0.9,>=0.8.21
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.2.38"
9
+ __version__ = "2.2.40"
10
10
 
11
11
  # The versioned machine output envelope contract.
12
12
  SCHEMA_VERSION = 1
@@ -74,6 +74,7 @@ _GROUP_DESCRIPTIONS = {
74
74
  "Manage the workspace's API keys (client apps): key + secret credentials "
75
75
  "for scripts and integrations."
76
76
  ),
77
+ "token": "Create, list, and revoke long-lived API keys (aliases of client-app).",
77
78
  "completion": "Install or print shell completion.",
78
79
  "config": "Read and update local CLI configuration.",
79
80
  "connector": "Manage data connectors and connector profiles.",
@@ -134,6 +135,7 @@ _ROOT_HELP_PANELS = {
134
135
  "annotation": "Manage resources",
135
136
  "billing": "Manage resources",
136
137
  "client-app": "Manage resources",
138
+ "token": "Manage resources",
137
139
  "external-key": "Manage resources",
138
140
  "notification": "Manage resources",
139
141
  "parameter": "Manage resources",
@@ -8,7 +8,7 @@ description: "Use Mammoth Analytics from a terminal: install or authenticate the
8
8
 
9
9
  Use this skill for Mammoth shell work, not Python SDK integration. The CLI
10
10
  is the contract: it validates requests locally and returns one JSON
11
- envelope, with no flag needed for that when piped.
11
+ envelope (compact when piped).
12
12
 
13
13
  ## What Mammoth is
14
14
 
@@ -18,15 +18,15 @@ calculated in a **pipeline** of tasks on a **view**, and the result is
18
18
  published as a dashboard or delivered as a CSV, a database table, a BI feed
19
19
  or another dataset. The pipeline re-runs when new data arrives, so build the
20
20
  steps in Mammoth rather than computing a result locally. The web app and
21
- this CLI call the same API: every Transform-menu task is a `mammoth view
22
- transform` command. The data model, capabilities and full web-to-CLI map:
21
+ this CLI call the same API: each Transform-menu task is a `view transform`
22
+ command. The data model, capabilities and full web-to-CLI map:
23
23
  [about Mammoth](references/about-mammoth.md).
24
24
 
25
25
  ## Start
26
26
 
27
27
  ```bash
28
28
  mammoth doctor # auth, endpoint, connectivity; must succeed
29
- mammoth project ensure 'PROJECT NAME' # get-or-create; active project
29
+ mammoth project ensure 'PROJECT NAME' # active project
30
30
  ```
31
31
 
32
32
  Never proceed if `doctor` fails.
@@ -53,16 +53,17 @@ downloads return `download_url`. On an auth error, ask the user to reload.
53
53
 
54
54
  ## Defaults you do not repeat
55
55
 
56
- - The CLI remembers which dataset owns each view from any read (`view list
57
- DATASET_ID`, `view get VIEW_ID`, an upload). After that, no `dataset_id`
56
+ - The CLI remembers which dataset owns each view from any read (`view list`,
57
+ `view get`, an upload). After that, no `dataset_id`
58
58
  on transforms, exports or deletes. If a command asks for the parent
59
59
  `DATASET_ID`, read the view once and repeat it; an explicit value wins.
60
- - Commands that start platform work wait up to 300 s for the job; on
61
- `timeout` use the `job get` recovery command printed, do not resubmit.
60
+ - Commands that start platform work wait up to 300 s; on `timeout` run the
61
+ `job get` recovery printed, never resubmit. `job wait` returns `outcome`
62
+ (view rows and state, copy `runs`): no `view get` after it.
62
63
 
63
64
  ## Find the command for a goal
64
65
 
65
- State the goal in plain words; the search knows common phrasing, and
66
+ State the goal in plain words;
66
67
  `view transform --help` is the Transform menu with one line per task:
67
68
 
68
69
  ```bash
@@ -73,20 +74,21 @@ mammoth schema find "join two datasets; remove duplicates; build a dashboard"
73
74
 
74
75
  | Goal | Command |
75
76
  |---|---|
76
- | Combine two datasets on a key (merge, VLOOKUP) | `view transform join`; one value per key: `view transform lookup` |
77
+ | Combine two datasets on a key | `view transform join`; one value per key: `view transform lookup` |
77
78
  | Add rows to an existing dataset, or combine sources | Local file: `file upload FILE --input '{"append_to_ds_id": DATASET_ID}'`. Already in Mammoth: `view export dataset VIEW_ID --input '{"dataset_name": "NAME"}'`, then per further source `view export dataset VIEW_ID --input '{"dataset_name": "NAME", "target_ds_id": DATASET_ID, "save_as_mode": "APPEND_TO_DS"}'` — combine first, clean once; then `discard-duplicates` and diff `row_count` before/after ([about Mammoth](references/about-mammoth.md#view-settings-and-what-has-no-command)) |
78
79
  | Keep or remove rows | `view transform filter` |
79
80
  | Remove duplicate rows | read `duplicates`; 0: stop. Else `view transform discard-duplicates` |
80
- | Totals, counts, averages per group — just to read the number | `view data aggregate` (read-only: `--input '{"group_by": [...], "aggregations": [{"column": ..., "function": "SUM"}]}'` or `{"metric": {...}}`); never add a `pivot` task just to answer a question |
81
+ | Totals, counts, averages per group, to read | `view data aggregate` (read-only: `--input '{"group_by": [...], "aggregations": [{"column": ..., "function": "SUM"}]}'` or `{"metric": {...}}`); never a `pivot` task |
82
+ | Top values, distribution, trend, earliest/latest date, unique count, filter a column | `view data explore VIEW_ID COLUMN` (read-only; `--help` lists the options; `-o csv`) |
81
83
  | Totals, counts, averages per group — as a lasting change to the pipeline | `view transform pivot` |
82
84
  | A calculated column | `view transform math` |
83
85
  | Blanks to a constant, or to the previous row's value | `view transform set-values` (`IS_EMPTY`), `view transform fill-missing` |
84
86
  | Clean text | `view transform text`, `replace`, `bulk-replace` |
85
87
  | Change a column's type | `view transform convert-type` |
86
- | Rename a column, sort the rows (view settings, not tasks) | `view transform rename-columns`, `view transform sort` |
88
+ | Rename a column, sort the rows | `view transform rename-columns`, `view transform sort` |
87
89
  | Rank, running total, previous row | `view transform window` |
88
90
  | A dashboard, or its PDF or slides | `dashboard v3 generate`, then `chat edit` ([dashboards](references/recipes/dashboards.md)) |
89
- | Deliver the rows | `view export csv`, `view export postgres` (and more), `view export dataset` |
91
+ | Deliver the rows | `view export csv`, `view export postgres`, `view export dataset` |
90
92
  | Run something on a schedule or on new data (refresh, append, alert) | `automation create`: a condition (`at_specific_time`, new file in a folder, ...) and tasks (`run_data_retrieval`, `append_data`, `send_an_alert`, `pull_cloud_files`). `schedule create` only pulls a connector's data. A dataset from an uploaded file or URL is a one-time copy with no source to refresh; say so. Recipe and caveats: [recurring work](references/recipes/scheduling.md) |
91
93
 
92
94
  Call a find result (or `suggestions` entry) from its `accepted_fields` and
@@ -103,9 +105,9 @@ dashboard from t_a and t_b"). Work it out from the data before building:
103
105
 
104
106
  1. Upload every file, or find the ones already uploaded. An upload result
105
107
  carries a `view` preview of what Mammoth made of it (`view_id`, column
106
- types, sample rows, `column_warnings`, `before_dashboard`). What Mammoth
107
- made of the files is what counts, not the raw files. Run `view data get VIEW_ID` per view;
108
- warnings list numbers/dates stored as text, and blanks, each with its fix.
108
+ types, sample rows, `column_warnings`, `before_dashboard`). Run `view
109
+ data get VIEW_ID` per view; warnings list numbers/dates stored as text,
110
+ and blanks, each with its fix.
109
111
  2. Find the keys. A column in one view whose values appear in a column of
110
112
  the other (`customer_id` and `id`, `order_ref` and `order_no`) is a
111
113
  foreign key; the view with many rows per key is the main one.
@@ -140,15 +142,15 @@ your report. If no column links the files, ask before you combine them.
140
142
  - Ids are positionals; request fields are one `--input '{...}'` document;
141
143
  no per-field flags (`project create NAME`, not `--name`).
142
144
  - `COMMAND --help` lists input fields; `schema find WORDS` inlines
143
- `accepted_fields`/`agent_example` for top matches, else `mammoth schema
144
- get COMMAND_ID` (`--input '{"full": true}'` for the schema); `schema
145
- list`/`schema list view` list families.
145
+ `accepted_fields`/`agent_example` for top matches, else `schema get
146
+ ID,ID` (one call; `--input '{"full": true}'` for all
147
+ fields); `schema list`/`schema list view` list families.
146
148
  - Uploads return a **dataset** id; transforms, joins, exports and previews
147
149
  take the **view** id from `view list DATASET_ID`.
148
- - `view list` and `view get` return the brief record (id, ds_id, name,
149
- status, row_count, `metadata` columns and types, pipeline state);
150
- `view get ... --input '{"fields": "__full"}'` or `view list ... --input
151
- '{"full": true}'` returns the dependency and display trees too.
150
+ - `view list` gives rows, columns, samples, `built_from`/`feeds`; `view get`
151
+ the brief record; `view analyze A,B` adds `view` and `steps`. `view get
152
+ ... --input '{"fields": "__full"}'` or `view list ... --input '{"full":
153
+ true}'` adds the dependency and display trees.
152
154
  - Column inputs/expressions use the exact **display names** the view
153
155
  returns, never backend aliases.
154
156
  - `--dry-run` on any API-backed command resolves and reports the request
@@ -12,6 +12,20 @@ created. When that happens, stop creating projects: ask the operator which
12
12
  project the token belongs to and pass `--project ID`, or ask for a token
13
13
  created without a project.
14
14
 
15
+ ## Browser sign-in
16
+
17
+ `mammoth auth login --method oauth` signs the operator in through the browser (PKCE, loopback
18
+ `127.0.0.1`). The CLI keeps a 1 h `mm_` token and refreshes it under a file lock. `auth status`
19
+ reports `credential: oauth` and `expires_at`. A refresh that fails exits 4 with `login_expired`:
20
+ tell the operator to run `mammoth auth login` again. `--no-browser` prints the URL. Browser sign-in
21
+ is for the operator's own terminal; an agent never runs it. `auth logout` also revokes the
22
+ connection on the server, and warns (still clearing local state) if it cannot.
23
+
24
+ `mammoth token create NAME`, `token list`, `token revoke KEY` are aliases of `client-app create`,
25
+ `list`, `delete`. `cli_keys_not_allowed` means this server does not let a browser sign-in create
26
+ keys: the operator creates one in **Settings → API keys** and runs
27
+ `mammoth auth login --method token`.
28
+
15
29
  ## Precedence
16
30
  1. Explicit login handed to the current command (secure prompt or `--input`).
17
31
  2. The selected or `--profile` profile's saved credentials.
@@ -1,7 +1,7 @@
1
1
  # What is proven on release
2
2
 
3
3
  Generated from `docs/release-capability-matrix.json`; do not edit by hand.
4
- The CLI publishes 652 commands. 516 of them bind one of the 545 API operations in the matrix; the remainder are local commands (`schema`, `auth`, `doctor`, `log`, ...) or typed variants that share an operation (`view transform *` commands submit through `view.task.add`, except `rename-columns` and `sort`, which set view display properties through `view.update`). 262 bound commands ran once successfully on release, 1 are not supported there, and the rest are untried. Untried is not broken: discover the contract with `mammoth schema get COMMAND_ID`, run it, and treat the structured error envelope as the answer. Use an untried command normally: confirm a write with the user first, check its result with a read afterwards, and never refuse a command only because it is untried.
4
+ The CLI publishes 655 commands. 516 of them bind one of the 545 API operations in the matrix; the remainder are local commands (`schema`, `auth`, `doctor`, `log`, ...) or typed variants that share an operation (`view transform *` commands submit through `view.task.add`, except `rename-columns` and `sort`, which set view display properties through `view.update`). 262 bound commands ran once successfully on release, 1 are not supported there, and the rest are untried. Untried is not broken: discover the contract with `mammoth schema get COMMAND_ID`, run it, and treat the structured error envelope as the answer. Use an untried command normally: confirm a write with the user first, check its result with a read afterwards, and never refuse a command only because it is untried.
5
5
 
6
6
  Status meanings:
7
7
 
@@ -1,6 +1,6 @@
1
1
  # Published CLI command catalog
2
2
 
3
- This generated catalog is a lookup table for every command in the published CLI manifest, currently 652; each entry carries its release status line. It is a command-contract index, not an assertion that every backend/OpenAPI operation has a CLI binding. For an exact local CLI contract, run `mammoth schema get COMMAND_ID`; `mammoth capability list` is an API-binding inventory and can omit typed/local CLI routes. For focused workflows, read the [recipes index](recipes/index.md). Sensitive structured input must come from a private file or pipe; never put secrets in literal argv.
3
+ This generated catalog is a lookup table for every command in the published CLI manifest, currently 655; each entry carries its release status line. It is a command-contract index, not an assertion that every backend/OpenAPI operation has a CLI binding. For an exact local CLI contract, run `mammoth schema get COMMAND_ID`; `mammoth capability list` is an API-binding inventory and can omit typed/local CLI routes. For focused workflows, read the [recipes index](recipes/index.md). Sensitive structured input must come from a private file or pipe; never put secrets in literal argv.
4
4
 
5
5
  Load only the applicable domain file:
6
6
 
@@ -44,6 +44,7 @@ Load only the applicable domain file:
44
44
  - [snippet](commands/snippet.md) — 8 published commands
45
45
  - [support](commands/support.md) — 66 published commands
46
46
  - [template](commands/template.md) — 5 published commands
47
+ - [token](commands/token.md) — 3 published commands
47
48
  - [trash](commands/trash.md) — 3 published commands
48
49
  - [upgrade](commands/upgrade.md) — 1 published commands
49
50
  - [user](commands/user.md) — 8 published commands
@@ -0,0 +1,33 @@
1
+ # `token` commands
2
+
3
+ Every command returns the standard JSON envelope. On nonzero exit, read the error envelope and its `recovery_commands`; do not guess request fields. "Status on release" is joined from `docs/release-capability-matrix.json`: *ran once* means one bounded live run succeeded on the named CLI release, *untried* means nobody has run it (use it normally: confirm writes with the user, check the result afterwards), *not supported* means the backend refuses it. When this file disagrees with [capabilities](../capabilities.md) or a recipe, they win. Envelope shapes: [machine output](../machine-output.md).
4
+
5
+ ### `token.create`
6
+
7
+ Run: `mammoth token create`. Exact input fields: `mammoth schema get token.create`.
8
+
9
+ Example: `mammoth token create 'Revenue report'`. Illustrative only: append `--yes --confirm <EXACT_TARGET>` after observing the target.
10
+
11
+ Result: `ClientAppCreateResult`; mutation `high_impact`, confirmation `confirm_target`, wait policy `not_async`.
12
+
13
+ Status on release: untried; no live run recorded.
14
+
15
+ ### `token.list`
16
+
17
+ Run: `mammoth token list`. Exact input fields: `mammoth schema get token.list`.
18
+
19
+ Example: `mammoth token list`. Placeholders are illustrative; resolve IDs and input from observed reads.
20
+
21
+ Result: `ClientAppListResult`; mutation `read`, confirmation `none`, wait policy `not_async`.
22
+
23
+ Status on release: untried; no live run recorded.
24
+
25
+ ### `token.revoke`
26
+
27
+ Run: `mammoth token revoke`. Exact input fields: `mammoth schema get token.revoke`.
28
+
29
+ Example: `mammoth token revoke sample`. Illustrative only: append `--yes` after observing an owned target.
30
+
31
+ Result: `ClientAppDeleteResult`; mutation `destructive`, confirmation `prompt_or_yes`, wait policy `not_async`.
32
+
33
+ Status on release: untried; no live run recorded.
@@ -150,7 +150,12 @@ applied.
150
150
 
151
151
  - A trend, distribution or top-values answer: `view data explore VIEW_ID
152
152
  COLUMN` (read-only; `level` sets the date bucket). `{"cumulative": true}`
153
- adds a running total per bucket, whatever `sort` or `limit` shows. Figures
153
+ adds a running total per bucket, whatever `sort` or `limit` shows.
154
+ `{"range": true}` adds the exact earliest and latest value;
155
+ `{"percentage_of": "metric"}` shares by the `metric`; `sort` `metric_desc`
156
+ ranks by it; `-o csv` saves the buckets. Excluding a value (`NE`, `not`)
157
+ drops blank rows, which the web card keeps: `or` it with `IS_EMPTY`. To
158
+ put a card on a dashboard, say it to `dashboard chat edit`. Figures
154
159
  from `explore` and `view data aggregate` are rounded for display (2
155
160
  decimals; 4 below 1); `view data compare` keeps full precision.
156
161
  - "Who changed X": `activity list` (a change list of time, user, action and a
@@ -1,11 +1,13 @@
1
1
  """Bespoke `auth` command family: login, status, logout.
2
2
 
3
- Authentication needs only an API token (``mm_...``, sent as ``Authorization:
4
- Bearer``), plus an optional server prefix (default ``app``). The token names its
5
- own workspace, which login learns from the server. There is no environment
6
- credential path. These commands never accept a secret as an
7
- ordinary command-line value: it comes from a hidden TTY prompt or a
8
- permission-checked JSON/YAML login document read through ``--input``.
3
+ Two ways in. A browser sign-in (OAuth, PKCE) stores a refreshable ``mm_`` access
4
+ token; pasting an API token (``mm_...``, sent as ``Authorization: Bearer``)
5
+ stores that token. Either way the token names its own workspace, which login
6
+ learns from the server, and there is an optional server prefix (default
7
+ ``app``). There is no environment credential path. These commands never accept
8
+ a secret as an ordinary command-line value: it comes from the browser, a hidden
9
+ TTY prompt, or a permission-checked JSON/YAML login document read through
10
+ ``--input``.
9
11
  """
10
12
 
11
13
  from __future__ import annotations
@@ -13,13 +15,14 @@ from __future__ import annotations
13
15
  import os
14
16
  import stat
15
17
  import sys
18
+ from datetime import UTC, datetime
16
19
  from pathlib import Path
17
20
  from typing import Any, cast
18
21
 
19
22
  import typer
20
23
  from pydantic import ValidationError
21
24
 
22
- from mammoth_cli.context import credentials, profiles, resolver
25
+ from mammoth_cli.context import credentials, oauth, profiles, resolver
23
26
  from mammoth_cli.context.endpoint import resolve_base_url
24
27
  from mammoth_cli.context.resolver import ResolvedAuth, resolve_auth
25
28
  from mammoth_cli.contracts.auth import LoginRequest
@@ -267,11 +270,114 @@ def _verify_login(invocation: Invocation, *, base_url: str, api_token: str) -> i
267
270
  return workspace_id
268
271
 
269
272
 
273
+ _LOGIN_METHODS = ("oauth", "token")
274
+
275
+
276
+ def _choose_method(
277
+ method: str | None, invocation: Invocation, *, server_prefix: str | None, blockers: list[str]
278
+ ) -> str:
279
+ """Pick ``oauth`` or ``token``: explicit, implied by ``--input``, or asked.
280
+
281
+ A server with no CLI OAuth client, a non-interactive run, and ``--input``
282
+ all keep the token login that existed before browser sign-in.
283
+ """
284
+ if method is not None:
285
+ if method not in _LOGIN_METHODS:
286
+ raise CliError(
287
+ code="invalid_login_method",
288
+ message=f"'{method}' is not a valid --method value.",
289
+ exit_status=EXIT_USAGE,
290
+ hint=f"Use one of: {', '.join(_LOGIN_METHODS)}.",
291
+ )
292
+ if method == "oauth" and invocation.input_file is not None:
293
+ raise CliError(
294
+ code="invalid_argument_combination",
295
+ message="--input is for token logins; it cannot be used with --method oauth.",
296
+ exit_status=EXIT_USAGE,
297
+ )
298
+ return method
299
+ if invocation.input_file is not None or blockers:
300
+ return "token"
301
+ if not oauth.has_client_id(server_prefix):
302
+ return "token"
303
+ typer.echo("How do you want to sign in?", err=True)
304
+ typer.echo(" 1) Browser (OAuth) recommended", err=True)
305
+ typer.echo(" 3) Paste an API token for CI and scripts", err=True)
306
+ choice = typer.prompt("Choose", default="1", show_default=False).strip()
307
+ if choice not in ("1", "3"):
308
+ raise CliError(
309
+ code="invalid_login_method",
310
+ message=f"'{choice}' is not one of the choices.",
311
+ exit_status=EXIT_USAGE,
312
+ hint="Enter 1 for the browser or 3 to paste an API token.",
313
+ )
314
+ return "oauth" if choice == "1" else "token"
315
+
316
+
317
+ def _iso(epoch: int) -> str:
318
+ return datetime.fromtimestamp(epoch, UTC).strftime("%Y-%m-%dT%H:%M:%SZ")
319
+
320
+
321
+ def _run_oauth_login(
322
+ invocation: Invocation,
323
+ *,
324
+ server_prefix: str | None,
325
+ storage: str,
326
+ open_browser: bool,
327
+ interactive: bool,
328
+ ) -> tuple[dict[str, Any], dict[str, Any]]:
329
+ """Sign in through the browser and persist the refreshable session."""
330
+ base_url = resolve_base_url(server_prefix)
331
+ client_id = oauth.client_id_for(server_prefix)
332
+ session = oauth.browser_login(
333
+ base_url,
334
+ client_id=client_id,
335
+ open_browser=open_browser,
336
+ say=lambda line: typer.echo(line, err=True),
337
+ )
338
+ workspace_id = _verify_login(invocation, base_url=base_url, api_token=session.access)
339
+
340
+ profile_name = invocation.profile or profiles.DEFAULT_PROFILE_NAME
341
+ profiles.validate_profile_name(profile_name)
342
+ existing = profiles.get_profile(profile_name)
343
+ profiles.save_profile(
344
+ profiles.ProfileRecord(
345
+ name=profile_name,
346
+ workspace_id=workspace_id,
347
+ server_prefix=server_prefix,
348
+ project_id=existing.project_id if existing is not None else None,
349
+ ),
350
+ select=True,
351
+ )
352
+ storage_used = credentials.store_credentials(
353
+ profile_name,
354
+ storage=cast(credentials.StorageMode, storage),
355
+ interactive=interactive,
356
+ oauth=session,
357
+ )
358
+ typer.echo(
359
+ f"Signed in to workspace {workspace_id}. Credential stored in {storage_used} "
360
+ f'(profile "{profile_name}"). The token refreshes automatically.',
361
+ err=True,
362
+ )
363
+ data = {
364
+ "profile": profile_name,
365
+ "workspace_id": workspace_id,
366
+ "base_url": base_url,
367
+ "storage": storage_used,
368
+ "credential": "oauth",
369
+ "expires_at": _iso(session.expires_at),
370
+ }
371
+ return data, {"profile": profile_name, "workspace_id": workspace_id}
372
+
373
+
270
374
  def _run_login(
271
375
  invocation: Invocation,
272
376
  *,
273
377
  server_prefix: str | None,
274
378
  storage: str,
379
+ method: str | None = None,
380
+ no_browser: bool = False,
275
381
  ) -> tuple[dict[str, Any], dict[str, Any]]:
276
382
  """Validate, connection-check, and persist one `auth login` invocation."""
277
383
  if storage not in _STORAGE_MODES:
@@ -284,6 +390,18 @@ def _run_login(
284
390
 
285
391
  blockers = _prompt_blockers(invocation)
286
392
 
393
+ if (
394
+ _choose_method(method, invocation, server_prefix=server_prefix, blockers=blockers)
395
+ == "oauth"
396
+ ):
397
+ return _run_oauth_login(
398
+ invocation,
399
+ server_prefix=server_prefix,
400
+ storage=storage,
401
+ open_browser=not no_browser,
402
+ interactive=not blockers,
403
+ )
404
+
287
405
  if invocation.input_file is not None:
288
406
  # The permission check is deliberately separate from parsing so a
289
407
  # secret-bearing file is rejected before any bytes are read. The
@@ -367,11 +485,21 @@ def auth_login(
367
485
  storage: str = typer.Option(
368
486
  "auto", "--storage", help="Credential storage backend.", metavar="auto|keyring|file"
369
487
  ),
488
+ method: str | None = typer.Option(
489
+ None,
490
+ "--method",
491
+ help="How to sign in: a browser (oauth) or a pasted API token (token).",
492
+ metavar="oauth|token",
493
+ ),
494
+ no_browser: bool = typer.Option(
495
+ False, "--no-browser", help="Print the sign-in URL instead of opening a browser."
496
+ ),
370
497
  ) -> None:
371
498
  """Log in and store one profile's credentials.
372
499
 
373
- Prompts for the API token (mm_..., from Workspace settings -> API Tokens)
374
- in a terminal; the token names its workspace. For non-interactive use
500
+ In a terminal, choose a browser sign-in (OAuth; the CLI keeps a token that
501
+ refreshes itself) or paste an API token (mm_..., from Workspace settings ->
502
+ API Tokens). The token names its workspace. For non-interactive use
375
503
  (agents, CI), pass ``--input FILE`` with {"api_token": ...} instead.
376
504
  Performs a lightweight connection check before saving anything; a failed
377
505
  check leaves existing profile state unchanged.
@@ -401,6 +529,8 @@ def auth_login(
401
529
  invocation,
402
530
  server_prefix=server_prefix,
403
531
  storage=storage,
532
+ method=method,
533
+ no_browser=no_browser,
404
534
  )
405
535
 
406
536
  executor.run(
@@ -435,6 +565,9 @@ def _run_status(invocation: Invocation, *, check: bool) -> tuple[dict[str, Any],
435
565
  "checked": False,
436
566
  "connected": None,
437
567
  }
568
+ if credential is not None and credential.oauth is not None:
569
+ data["expires_at"] = _iso(credential.oauth.expires_at)
570
+ data["client_id"] = credential.oauth.client_id
438
571
  if credential is not None and credential.kind == "key_secret":
439
572
  data["recommendation"] = (
440
573
  "This profile uses a legacy API key + secret. Create an API token in "
@@ -501,6 +634,29 @@ def auth_status(
501
634
  )
502
635
 
503
636
 
637
+ def _revoke_oauth_connection(profile_name: str, warnings: list[str]) -> None:
638
+ """Revoke a browser login's server-side connection; warn on failure, never raise.
639
+
640
+ Logout must always clear local state, so every failure here (no record, an
641
+ unreadable keyring, a refused or unreachable server) becomes a warning.
642
+ """
643
+ try:
644
+ credential = credentials.load_credential(profile_name)
645
+ record = profiles.get_profile(profile_name)
646
+ if credential is None or credential.oauth is None or record is None:
647
+ return
648
+ base_url = resolve_base_url(record.server_prefix)
649
+ session = credential.oauth
650
+ if not oauth.is_fresh(session):
651
+ session = oauth.refresh_session(profile_name, base_url)
652
+ problem = oauth.revoke_grant(base_url, session)
653
+ except CliError as exc:
654
+ problem = f"Could not revoke the connection on the server: {exc.message}"
655
+ if problem is not None:
656
+ warnings.append(problem)
657
+ typer.echo(f"Warning: {problem} Local credentials are still removed.", err=True)
658
+
659
+
504
660
  def _run_logout(
505
661
  invocation: Invocation, *, all_profiles: bool, yes: bool
506
662
  ) -> tuple[dict[str, Any], dict[str, Any]]:
@@ -533,21 +689,26 @@ def _run_logout(
533
689
  )
534
690
 
535
691
  removed: list[str] = []
692
+ warnings: list[str] = []
536
693
  if all_profiles:
537
694
  # Iterate raw profile names so an unparseable legacy profile (for
538
695
  # example one with an unsupported base_url) is still cleaned up rather
539
696
  # than blocking the very command meant to remove it.
540
697
  for name in profiles.list_profile_names():
698
+ _revoke_oauth_connection(name, warnings)
541
699
  if credentials.delete_credentials(name):
542
700
  removed.append(name)
543
701
  profiles.delete_profile(name)
544
702
  else:
545
703
  profile_name = invocation.profile or profiles.get_selected()
704
+ _revoke_oauth_connection(profile_name, warnings)
546
705
  if credentials.delete_credentials(profile_name):
547
706
  removed.append(profile_name)
548
707
  profiles.delete_profile(profile_name)
549
708
 
550
- data = {"removed_profiles": sorted(removed), "all": all_profiles}
709
+ data: dict[str, Any] = {"removed_profiles": sorted(removed), "all": all_profiles}
710
+ if warnings:
711
+ data["warnings"] = warnings
551
712
  return data, {}
552
713
 
553
714
 
@@ -26,6 +26,7 @@ from mammoth_cli.errors.envelope import (
26
26
  from mammoth_cli.manifest.loader import command_by_id
27
27
  from mammoth_cli.runtime.invocation import Invocation
28
28
  from mammoth_cli.runtime.session import open_service
29
+ from mammoth_cli.services import job_outcome
29
30
  from mammoth_cli.services.board_values import board_values, dashboard_link
30
31
 
31
32
  HandlerResult = tuple[Any, dict[str, Any]]
@@ -171,6 +172,7 @@ def job_wait(invocation: Invocation) -> HandlerResult:
171
172
  try:
172
173
  with open_service(invocation) as (service, auth):
173
174
  data = _with_board(service, auth, _wait_result(job_id, service.call(symbol, **kwargs)))
175
+ data = _with_outcome(service, data)
174
176
  except KeyboardInterrupt as exc:
175
177
  # Keep the explicit handle even when the polling implementation raises
176
178
  # a bare SIGINT. A caller can inspect/resume it without replaying the
@@ -187,6 +189,34 @@ def job_wait(invocation: Invocation) -> HandlerResult:
187
189
  return data, _meta(invocation, auth.workspace_id)
188
190
 
189
191
 
192
+ _DATAVIEW_GET_SYMBOL = "mammoth.api.dataviews.DataviewsAPI.get"
193
+
194
+
195
+ def _with_outcome(service: Any, data: dict[str, Any]) -> dict[str, Any]:
196
+ """Add ``outcome``: the state of what the finished job acted on.
197
+
198
+ A job on a view gets that view's rows, columns and state (one read); a project copy
199
+ gets its copied counts and per-view runs (no read). The job succeeded either way, so
200
+ a view that cannot be read is an ``outcome_error``, never a failed wait.
201
+ """
202
+ copied = job_outcome.copy_outcome(data.get("result"))
203
+ if copied is not None and data.get("operation") == job_outcome.COPY_PROJECT_OPERATION:
204
+ return {**data, "outcome": copied}
205
+ target = job_outcome.view_target(data)
206
+ if target is None:
207
+ return data
208
+ try:
209
+ record = service.call(
210
+ _DATAVIEW_GET_SYMBOL,
211
+ dataset_id=target.dataset_id,
212
+ dataview_id=target.view_id,
213
+ project_id=target.project_id,
214
+ )
215
+ except CliError as error:
216
+ return {**data, "outcome_error": f"{error.code}: {error.message}"}
217
+ return {**data, "outcome": job_outcome.view_outcome(record, target)}
218
+
219
+
190
220
  #: Jobs that build a board. A build that outlived its own wait hands back a running
191
221
  #: job; waiting on it here must report what the build would have: the board's link
192
222
  #: and its evaluated numbers (UQA-RT2-05).
@@ -281,6 +281,9 @@ def project_copy(invocation: Invocation) -> HandlerResult:
281
281
  ``PROJECT_ID NAME`` are positional; ``dataset_ids``, ``include_dashboards`` and
282
282
  ``exclude_data`` come from ``--input``. The result is the job's:
283
283
  ``project_id``, ``dataset_map``, ``view_map``, ``skipped`` and ``dashboards``.
284
+
285
+ A taken NAME is not an error: the server names the copy with the next free suffix
286
+ ("NAME 2", "NAME 3", ...), so there is no need to check the name first.
284
287
  """
285
288
  source_id = _int_positional(invocation, "project id")
286
289
  name = invocation.extra_args[1] if len(invocation.extra_args) > 1 else None