mammoth-cli 2.2.4__tar.gz → 2.2.5__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 (253) hide show
  1. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/PKG-INFO +3 -4
  2. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/README.md +1 -2
  3. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/__init__.py +1 -1
  4. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/auth.md +5 -6
  5. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/capabilities.md +1 -1
  6. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/command-index.md +3 -2
  7. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dataset.md +10 -0
  8. mammoth_cli-2.2.5/mammoth_cli/bundled_skill/mammoth-cli/references/commands/link.md +13 -0
  9. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/need-action.md +36 -0
  10. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/auth.py +65 -60
  11. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/dataset.py +36 -11
  12. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/folder.py +1 -11
  13. mammoth_cli-2.2.5/mammoth_cli/commands/link.py +89 -0
  14. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/registry.py +3 -0
  15. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/schema.py +17 -1
  16. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/context/endpoint.py +2 -2
  17. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/context/profiles.py +1 -1
  18. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/context/resolver.py +39 -3
  19. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/contracts/auth.py +1 -11
  20. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/embed.py +1 -1
  21. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/services/command_contract.py +1 -1
  22. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/services/mapping.py +17 -2
  23. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/services/positionals.py +9 -0
  24. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/services/sdk_service.py +25 -3
  25. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/pyproject.toml +2 -2
  26. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/dataset.yaml +45 -0
  27. mammoth_cli-2.2.5/spec/manifests/commands/link.yaml +40 -0
  28. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/project.yaml +1 -1
  29. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/edits-target.source.yaml +1 -0
  30. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/sdk-catalog.source.yaml +15 -0
  31. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/sdk-methods.yaml +17 -5
  32. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/.gitignore +0 -0
  33. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/LICENSE +0 -0
  34. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/__main__.py +0 -0
  35. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/app.py +0 -0
  36. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/SKILL.md +0 -0
  37. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/about-mammoth.md +0 -0
  38. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/capabilities-misc.md +0 -0
  39. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/activity.md +0 -0
  40. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/addon.md +0 -0
  41. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/agent.md +0 -0
  42. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/ai.md +0 -0
  43. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/annotation.md +0 -0
  44. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/auth.md +0 -0
  45. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/automation.md +0 -0
  46. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/batch.md +0 -0
  47. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/billing.md +0 -0
  48. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/browse.md +0 -0
  49. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/calc.md +0 -0
  50. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/capability.md +0 -0
  51. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/client-app.md +0 -0
  52. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/completion.md +0 -0
  53. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/config.md +0 -0
  54. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/connector.md +0 -0
  55. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/context.md +0 -0
  56. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard-qa.md +0 -0
  57. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard-style.md +0 -0
  58. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard.md +0 -0
  59. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/data-app.md +0 -0
  60. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/doctor.md +0 -0
  61. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/external-key.md +0 -0
  62. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/file.md +0 -0
  63. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/folder.md +0 -0
  64. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/job.md +0 -0
  65. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/log.md +0 -0
  66. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/notification.md +0 -0
  67. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/parameter.md +0 -0
  68. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/project.md +0 -0
  69. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/report.md +0 -0
  70. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/schedule.md +0 -0
  71. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/schema.md +0 -0
  72. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/skill.md +0 -0
  73. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/snippet.md +0 -0
  74. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/support.md +0 -0
  75. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/template.md +0 -0
  76. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/trash.md +0 -0
  77. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/upgrade.md +0 -0
  78. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/user.md +0 -0
  79. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/version.md +0 -0
  80. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/view-transform.md +0 -0
  81. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/view.md +0 -0
  82. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/webhook.md +0 -0
  83. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/workflow.md +0 -0
  84. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/workspace.md +0 -0
  85. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/handoff.md +0 -0
  86. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/input.md +0 -0
  87. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/jobs-drafts.md +0 -0
  88. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/machine-output.md +0 -0
  89. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/operations.md +0 -0
  90. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/auth-scope.md +0 -0
  91. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/cleanup.md +0 -0
  92. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/dashboards.md +0 -0
  93. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/database-import.md +0 -0
  94. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/end-to-end.md +0 -0
  95. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/exports.md +0 -0
  96. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/index.md +0 -0
  97. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/resources.md +0 -0
  98. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/scheduling.md +0 -0
  99. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/transforms.md +0 -0
  100. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/typed-etl-discovery.md +0 -0
  101. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/recovery.md +0 -0
  102. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/report-checklist.md +0 -0
  103. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/retention.md +0 -0
  104. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/safety.md +0 -0
  105. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/bundled_skill/mammoth-cli/references/task-start.md +0 -0
  106. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/__init__.py +0 -0
  107. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/activity.py +0 -0
  108. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/addon.py +0 -0
  109. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/agent.py +0 -0
  110. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/ai.py +0 -0
  111. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/annotation.py +0 -0
  112. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/automation.py +0 -0
  113. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/batch.py +0 -0
  114. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/billing.py +0 -0
  115. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/browse.py +0 -0
  116. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/calc.py +0 -0
  117. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/capability.py +0 -0
  118. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/client_app.py +0 -0
  119. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/completion.py +0 -0
  120. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/config.py +0 -0
  121. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/connector.py +0 -0
  122. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/context.py +0 -0
  123. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/dashboard.py +0 -0
  124. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/data_app.py +0 -0
  125. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/doctor.py +0 -0
  126. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/external_key.py +0 -0
  127. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/file.py +0 -0
  128. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/job.py +0 -0
  129. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/notification.py +0 -0
  130. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/parameter.py +0 -0
  131. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/project.py +0 -0
  132. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/report.py +0 -0
  133. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/schedule.py +0 -0
  134. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/skill.py +0 -0
  135. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/snippet.py +0 -0
  136. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/support.py +0 -0
  137. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/template.py +0 -0
  138. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/trash.py +0 -0
  139. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/upgrade.py +0 -0
  140. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/user.py +0 -0
  141. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/view.py +0 -0
  142. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/view_ops.py +0 -0
  143. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/view_profile.py +0 -0
  144. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/webhook.py +0 -0
  145. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/workflow.py +0 -0
  146. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/commands/workspace.py +0 -0
  147. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/context/__init__.py +0 -0
  148. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/context/credentials.py +0 -0
  149. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/contracts/__init__.py +0 -0
  150. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/errors/__init__.py +0 -0
  151. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/errors/envelope.py +0 -0
  152. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/manifest/__init__.py +0 -0
  153. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/manifest/loader.py +0 -0
  154. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/messages/__init__.py +0 -0
  155. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/output/__init__.py +0 -0
  156. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/output/envelope.py +0 -0
  157. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/output/normalize.py +0 -0
  158. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/output/policy.py +0 -0
  159. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/output/progress.py +0 -0
  160. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/output/render.py +0 -0
  161. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/py.typed +0 -0
  162. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/runtime/__init__.py +0 -0
  163. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/runtime/confirm.py +0 -0
  164. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/runtime/dataset_health.py +0 -0
  165. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/runtime/dryrun.py +0 -0
  166. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/runtime/dryrun_targets.py +0 -0
  167. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/runtime/embedded.py +0 -0
  168. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/runtime/executor.py +0 -0
  169. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/runtime/input_loader.py +0 -0
  170. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/runtime/intent_only.py +0 -0
  171. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/runtime/invocation.py +0 -0
  172. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/runtime/new_data.py +0 -0
  173. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/runtime/options.py +0 -0
  174. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/runtime/parents.py +0 -0
  175. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/runtime/runlog.py +0 -0
  176. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/runtime/session.py +0 -0
  177. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/runtime/state.py +0 -0
  178. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/runtime/strict.py +0 -0
  179. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/runtime/updates.py +0 -0
  180. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/runtime/validate.py +0 -0
  181. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/runtime/verify.py +0 -0
  182. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/services/__init__.py +0 -0
  183. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/services/argspec.py +0 -0
  184. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/services/board_values.py +0 -0
  185. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/services/coerce.py +0 -0
  186. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/services/conditions.py +0 -0
  187. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/services/dashboard_filters.py +0 -0
  188. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/services/dashboard_pages.py +0 -0
  189. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/services/dashboard_review.py +0 -0
  190. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/services/data_profile.py +0 -0
  191. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/services/data_quality.py +0 -0
  192. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/services/dispatch.py +0 -0
  193. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/services/factory.py +0 -0
  194. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/services/input_fields.py +0 -0
  195. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/services/listing.py +0 -0
  196. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/services/openapi_types.py +0 -0
  197. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/services/protocol.py +0 -0
  198. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/services/read_queries.py +0 -0
  199. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/services/stored_stats.py +0 -0
  200. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/services/testing.py +0 -0
  201. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/services/text_dates.py +0 -0
  202. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/services/type_system.py +0 -0
  203. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/services/write_impact.py +0 -0
  204. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/skills/__init__.py +0 -0
  205. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/skills/installer.py +0 -0
  206. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/skills/steering.py +0 -0
  207. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/mammoth_cli/testing.py +0 -0
  208. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/activity.yaml +0 -0
  209. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/addon.yaml +0 -0
  210. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/agent.yaml +0 -0
  211. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/ai.yaml +0 -0
  212. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/annotation.yaml +0 -0
  213. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/auth.yaml +0 -0
  214. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/automation.yaml +0 -0
  215. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/batch.yaml +0 -0
  216. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/billing.yaml +0 -0
  217. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/browse.yaml +0 -0
  218. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/calc.yaml +0 -0
  219. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/capability.yaml +0 -0
  220. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/client-app.yaml +0 -0
  221. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/completion.yaml +0 -0
  222. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/config.yaml +0 -0
  223. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/connector.yaml +0 -0
  224. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/context.yaml +0 -0
  225. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/dashboard.yaml +0 -0
  226. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/data-app.yaml +0 -0
  227. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/doctor.yaml +0 -0
  228. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/external-key.yaml +0 -0
  229. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/file.yaml +0 -0
  230. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/folder.yaml +0 -0
  231. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/job.yaml +0 -0
  232. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/log.yaml +0 -0
  233. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/notification.yaml +0 -0
  234. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/parameter.yaml +0 -0
  235. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/report.yaml +0 -0
  236. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/schedule.yaml +0 -0
  237. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/schema.yaml +0 -0
  238. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/skill.yaml +0 -0
  239. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/snippet.yaml +0 -0
  240. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/support.yaml +0 -0
  241. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/template.yaml +0 -0
  242. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/trash.yaml +0 -0
  243. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/upgrade.yaml +0 -0
  244. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/user.yaml +0 -0
  245. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/version.yaml +0 -0
  246. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/view.yaml +0 -0
  247. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/webhook.yaml +0 -0
  248. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/workflow.yaml +0 -0
  249. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/commands/workspace.yaml +0 -0
  250. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/openapi-operations.yaml +0 -0
  251. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/manifests/schema-v1.json +0 -0
  252. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/spec/openapi/metadata.json +0 -0
  253. {mammoth_cli-2.2.4 → mammoth_cli-2.2.5}/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.4
3
+ Version: 2.2.5
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.5
20
+ Requires-Dist: mammoth-io<0.9,>=0.8.6
21
21
  Requires-Dist: platformdirs<5,>=4.10
22
22
  Requires-Dist: pydantic<3,>=2.12.5
23
23
  Requires-Dist: pyyaml<7,>=6
@@ -212,8 +212,7 @@ Onboard me first:
212
212
  `recommendation`, print exactly this and wait until I say done: "In the
213
213
  Mammoth web app open Workspace settings → API Tokens → Create token (no
214
214
  project, so I can create projects), copy the token (it starts with mm_ and
215
- is shown once), and note the workspace id (the number after /workspaces/
216
- in the address bar), then run in your own terminal: mammoth auth login" —
215
+ is shown once), then run in your own terminal: mammoth auth login" —
217
216
  never ask for, read, or pass the token yourself, and never run auth login.
218
217
  3. Require `mammoth doctor` to pass, then run `mammoth skill show` and
219
218
  follow the guide it prints.
@@ -184,8 +184,7 @@ Onboard me first:
184
184
  `recommendation`, print exactly this and wait until I say done: "In the
185
185
  Mammoth web app open Workspace settings → API Tokens → Create token (no
186
186
  project, so I can create projects), copy the token (it starts with mm_ and
187
- is shown once), and note the workspace id (the number after /workspaces/
188
- in the address bar), then run in your own terminal: mammoth auth login" —
187
+ is shown once), then run in your own terminal: mammoth auth login" —
189
188
  never ask for, read, or pass the token yourself, and never run auth login.
190
189
  3. Require `mammoth doctor` to pass, then run `mammoth skill show` and
191
190
  follow the guide it prints.
@@ -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.4"
9
+ __version__ = "2.2.5"
10
10
 
11
11
  # The versioned machine output envelope contract.
12
12
  SCHEMA_VERSION = 1
@@ -1,6 +1,6 @@
1
1
  # Authentication and profiles
2
2
 
3
- Required: an API token (`mm_...`) and a workspace id. Optional: a one-label
3
+ Required: an API token (`mm_...`); it names its own workspace. Optional: a one-label
4
4
  server prefix (default `app`, resolving to `https://app.mammoth.io/api/v2`).
5
5
  Login accepts nothing else. If `auth status` reports `credential: key_secret`
6
6
  (a profile saved by an older CLI), it still works, but ask the operator to run
@@ -29,8 +29,7 @@ human operator:
29
29
  1. Tell the operator where the credentials come from: in the Mammoth web app,
30
30
  **Workspace settings → API Tokens → Create token** gives a token that
31
31
  starts with `mm_`; the web app shows it only once (if it is lost, create a
32
- new one). The workspace id is the number after `/workspaces/`
33
- in the web app's address bar. Then give the exact command to run in
32
+ new one). Then give the exact command to run in
34
33
  **their own** terminal. For production it is:
35
34
 
36
35
  ```bash
@@ -40,7 +39,7 @@ human operator:
40
39
  Add `--server-prefix release` only when the task names the release
41
40
  environment, and `--profile NAME` only when the operator wants a profile
42
41
  other than `default`. The command prompts for the token with hidden
43
- input, then the workspace id, so no secret enters chat, argv, or history.
42
+ input, so no secret enters chat, argv, or history.
44
43
  Tokens are per environment and per workspace: a release token never
45
44
  authenticates on `app`.
46
45
  On macOS the Keychain may show a dialog about `mammoth-cli`; tell the
@@ -54,7 +53,7 @@ human operator:
54
53
  `auth login` yourself, with or without `--input`, unless the operator has
55
54
  explicitly given you a protected `0600` credential file path to use.
56
55
 
57
- The only supported configuration is the API token, the workspace id, and an optional one-label server prefix (default `app`). There is no base-url
56
+ The only supported configuration is the API token and an optional one-label server prefix (default `app`). There is no base-url
58
57
  override.
59
58
 
60
59
  ## Cold-start sequence
@@ -123,7 +122,7 @@ file backend as a secret store; use the OS keyring or stop and obtain a
123
122
  supported secure store. Remove any input file after the
124
123
  profile is stored.
125
124
 
126
- `creds.json` is a `0600` JSON file: `{"api_token": "mm_...", "workspace_id": 4,
125
+ `creds.json` is a `0600` JSON file: `{"api_token": "mm_...",
127
126
  "server_prefix": "app"}` (`server_prefix` optional). You can
128
127
  also pipe it with `--input - --input-format json`.
129
128
 
@@ -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 595 commands. 455 of them bind one of the 528 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, 2 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 597 commands. 455 of them bind one of the 528 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, 2 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 595; 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 597; 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
 
@@ -25,12 +25,13 @@ Load only the applicable domain file:
25
25
  - [dashboard-style](commands/dashboard-style.md) — 10 published commands
26
26
  - [dashboard](commands/dashboard.md) — 93 published commands
27
27
  - [data-app](commands/data-app.md) — 12 published commands
28
- - [dataset](commands/dataset.md) — 20 published commands
28
+ - [dataset](commands/dataset.md) — 21 published commands
29
29
  - [doctor](commands/doctor.md) — 1 published commands
30
30
  - [external-key](commands/external-key.md) — 4 published commands
31
31
  - [file](commands/file.md) — 9 published commands
32
32
  - [folder](commands/folder.md) — 10 published commands
33
33
  - [job](commands/job.md) — 4 published commands
34
+ - [link](commands/link.md) — 1 published commands
34
35
  - [log](commands/log.md) — 2 published commands
35
36
  - [notification](commands/notification.md) — 5 published commands
36
37
  - [parameter](commands/parameter.md) — 14 published commands
@@ -22,6 +22,16 @@ Result: `DatasetBrokenRowsListResult`; mutation `read`, confirmation `none`, wai
22
22
 
23
23
  Status on release: untried; no live run recorded.
24
24
 
25
+ ### `dataset.broken-rows.resolve`
26
+
27
+ Run: `mammoth dataset broken-rows resolve`. Exact input fields: `mammoth schema get dataset.broken-rows.resolve`.
28
+
29
+ Example: `mammoth dataset broken-rows resolve 123 --input '{"op": "add", "batch_id": 1, "rows": [{"sample_key": "Status"}]}'`. Illustrative only: append `--yes` after observing an owned target.
30
+
31
+ Result: `DatasetBrokenRowsResolveResult`; mutation `destructive`, confirmation `prompt_or_yes`, wait policy `not_async`.
32
+
33
+ Status on release: untried; no live run recorded.
34
+
25
35
  ### `dataset.bulk-delete`
26
36
 
27
37
  Run: `mammoth dataset bulk-delete`. Exact input fields: `mammoth schema get dataset.bulk-delete`.
@@ -0,0 +1,13 @@
1
+ # `link` 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
+ ### `link`
6
+
7
+ Run: `mammoth link`. Exact input fields: `mammoth schema get link`.
8
+
9
+ Example: `mammoth link https://app.mammoth.io/workspaces/1/projects/2/data/datasets`. Placeholders are illustrative; resolve IDs and input from observed reads.
10
+
11
+ Result: `LinkResult`; mutation `read`, confirmation `none`, wait policy `not_async`.
12
+
13
+ Status on release: untried; no live run recorded.
@@ -58,3 +58,39 @@ mammoth view list DATASET_ID --project PROJECT_ID # the new view, row_count s
58
58
  The new view is ready at once and takes transforms like any other (verified
59
59
  on release, 2026-09-24). Run `view create` only when `view list DATASET_ID`
60
60
  is empty, so that a retry does not add a second view.
61
+
62
+ ## A pasted link to a file with "Unstructured rows"
63
+
64
+ `mammoth project needs-attention --project PROJECT_ID` lists it as a
65
+ `needs_input` row with `action: "unstructured_rows"` and the `dataset_id`.
66
+ The Monitor panel lists this as **Unstructured rows** ("header and data rows
67
+ need mapping"): some lines of an uploaded file did not fit the dataset's
68
+ columns and were set aside, so the dataset waits for a person. Turn the pasted
69
+ address into ids first; it makes no request:
70
+
71
+ ```bash
72
+ mammoth link 'https://app.mammoth.io/workspaces/1/projects/2/data/folders/3?selectedResourceId=4'
73
+ ```
74
+
75
+ The folder and `selected_resource_id` in a link are resource ids, not dataset
76
+ ids: find the dataset with `mammoth dataset find NAME`. Then read the set-aside
77
+ lines and why each one does not fit (the first 100, with `row_count` the total):
78
+
79
+ ```bash
80
+ mammoth dataset broken-rows list DATASET_ID --project PROJECT_ID
81
+ ```
82
+
83
+ Then fix them, with the user's confirmation. Take a line in after correcting
84
+ it so its column count matches, or discard it (discarded lines do not come
85
+ back; say so first). `batch_id` and `line_num` come from the list:
86
+
87
+ ```bash
88
+ mammoth dataset broken-rows resolve DATASET_ID --project PROJECT_ID \
89
+ --input '{"op": "remove", "batch_id": 7, "rows": [{"line_num": 4, "line": ""}]}'
90
+ mammoth job wait JOB_ID
91
+ mammoth dataset broken-rows list DATASET_ID --project PROJECT_ID # row_count 0 = done
92
+ ```
93
+
94
+ `op: "add"` takes the corrected `line` of each row in instead. The same step is
95
+ **Review & Fix** in the app. Do not tell the user to open the Monitor item's
96
+ link.
@@ -1,8 +1,9 @@
1
1
  """Bespoke `auth` command family: login, status, logout.
2
2
 
3
- Authentication needs an API token (``mm_...``, sent as ``Authorization:
4
- Bearer``) and a workspace id, plus an optional server prefix (default
5
- ``app``). There is no environment credential path. These commands never accept a secret as an
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
6
7
  ordinary command-line value: it comes from a hidden TTY prompt or a
7
8
  permission-checked JSON/YAML login document read through ``--input``.
8
9
  """
@@ -18,18 +19,14 @@ from typing import Any, cast
18
19
  import typer
19
20
  from pydantic import ValidationError
20
21
 
21
- from mammoth_cli.context import credentials, profiles
22
+ from mammoth_cli.context import credentials, profiles, resolver
22
23
  from mammoth_cli.context.endpoint import resolve_base_url
23
- from mammoth_cli.context.resolver import (
24
- ResolvedAuth,
25
- resolve_auth,
26
- )
24
+ from mammoth_cli.context.resolver import ResolvedAuth, resolve_auth
27
25
  from mammoth_cli.contracts.auth import LoginRequest
28
26
  from mammoth_cli.errors.envelope import (
29
27
  CODE_AUTHENTICATION_FAILED,
30
28
  CODE_CONFIRMATION_DECLINED,
31
29
  CODE_CONFIRMATION_REQUIRED,
32
- CODE_INVALID_WORKSPACE_ID,
33
30
  EXIT_USAGE,
34
31
  CliError,
35
32
  )
@@ -128,7 +125,7 @@ def _validate_login_document(document: dict[str, Any]) -> LoginRequest:
128
125
  message="The login request document failed validation.",
129
126
  exit_status=EXIT_USAGE,
130
127
  hint=(
131
- 'Expected {"api_token": "mm_...", "workspace_id": N} with an optional '
128
+ 'Expected {"api_token": "mm_..."} with an optional '
132
129
  '"server_prefix". API key + secret pairs are no longer accepted; create '
133
130
  "a token in Workspace settings -> API Tokens."
134
131
  ),
@@ -217,6 +214,59 @@ def _prompt_blockers(invocation: Invocation) -> list[str]:
217
214
  return reasons
218
215
 
219
216
 
217
+ def _verify_login(invocation: Invocation, *, base_url: str, api_token: str) -> int:
218
+ """Learn the token's workspace from the server and run the connection check.
219
+
220
+ Nothing is saved here; a failure leaves existing profile state unchanged.
221
+
222
+ Returns:
223
+ The workspace id the server reports for the token.
224
+
225
+ Raises:
226
+ CliError: ``authentication_failed`` (with the endpoint and a masked
227
+ receipt of the token) when the server rejects it; any other mapped
228
+ transport error as is.
229
+ """
230
+ try:
231
+ workspace_id = resolver.resolve_token_workspace(base_url, api_token, invocation.timeout)
232
+ service = service_factory.build_service(
233
+ ResolvedAuth(
234
+ api_key=None,
235
+ api_secret=None,
236
+ workspace_id=workspace_id,
237
+ base_url=base_url,
238
+ api_token=api_token,
239
+ ),
240
+ timeout=invocation.timeout,
241
+ )
242
+ try:
243
+ service.check_connection()
244
+ finally:
245
+ service.close()
246
+ except CliError as exc:
247
+ if exc.code == CODE_AUTHENTICATION_FAILED:
248
+ # Say exactly what was tried, without the secret: the endpoint and
249
+ # a masked receipt of the token. Credentials are per environment,
250
+ # and a release token typed at a production login is the common
251
+ # cause of an otherwise opaque 401.
252
+ exc.details = {
253
+ **exc.details,
254
+ "endpoint_base_url": base_url,
255
+ # A receipt only (length and last four characters). The output
256
+ # layer redacts any key that looks like a credential, so this
257
+ # is named for what it is: a description, not the value.
258
+ "credential_receipt": {"type": "api token", "shape": _masked_receipt(api_token)},
259
+ }
260
+ exc.hint = (
261
+ f"{base_url} rejected this token. Credentials are per environment: "
262
+ "a token issued on one Mammoth server does not authenticate on "
263
+ "another. Check the token and that --server-prefix matches where "
264
+ "it was issued."
265
+ )
266
+ raise
267
+ return workspace_id
268
+
269
+
220
270
  def _run_login(
221
271
  invocation: Invocation,
222
272
  *,
@@ -234,7 +284,6 @@ def _run_login(
234
284
 
235
285
  blockers = _prompt_blockers(invocation)
236
286
 
237
- effective_workspace: int | None
238
287
  if invocation.input_file is not None:
239
288
  # The permission check is deliberately separate from parsing so a
240
289
  # secret-bearing file is rejected before any bytes are read. The
@@ -246,15 +295,12 @@ def _run_login(
246
295
  request = _validate_login_document(document)
247
296
  api_token = request.api_token.strip()
248
297
  _check_token_shape(api_token)
249
- effective_workspace = request.workspace_id
250
298
  effective_prefix = server_prefix if server_prefix is not None else request.server_prefix
251
299
  elif not blockers:
252
- # Two flows, nothing else: a terminal prompts for everything (token,
253
- # then workspace id), and non-interactive uses --input. The workspace
254
- # is asked last, after the credential.
300
+ # Two flows, nothing else: a terminal prompts for the token, and
301
+ # non-interactive uses --input.
255
302
  api_token = _prompt_secret("API token")
256
303
  _check_token_shape(api_token)
257
- effective_workspace = typer.prompt("Workspace id", type=int)
258
304
  effective_prefix = server_prefix
259
305
  else:
260
306
  raise CliError(
@@ -269,49 +315,8 @@ def _run_login(
269
315
  ),
270
316
  )
271
317
 
272
- if effective_workspace is None or effective_workspace <= 0:
273
- raise CliError(
274
- code=CODE_INVALID_WORKSPACE_ID,
275
- message="A positive --workspace id is required.",
276
- exit_status=EXIT_USAGE,
277
- )
278
318
  resolved_base_url = resolve_base_url(effective_prefix)
279
-
280
- resolved_auth = ResolvedAuth(
281
- api_key=None,
282
- api_secret=None,
283
- workspace_id=effective_workspace,
284
- base_url=resolved_base_url,
285
- api_token=api_token,
286
- )
287
- service = service_factory.build_service(resolved_auth, timeout=invocation.timeout)
288
- try:
289
- service.check_connection()
290
- except CliError as exc:
291
- if exc.code == CODE_AUTHENTICATION_FAILED:
292
- # Say exactly what was tried, without the secret: the endpoint,
293
- # the workspace, and a masked receipt of the key. Credentials are
294
- # per environment, and a release key typed at a production login
295
- # is the common cause of an otherwise opaque 401.
296
- exc.details = {
297
- **exc.details,
298
- "endpoint_base_url": resolved_base_url,
299
- "workspace_id": effective_workspace,
300
- # A receipt only (length and last four characters). The output
301
- # layer redacts any key that looks like a credential, so this
302
- # is named for what it is: a description, not the value.
303
- "credential_receipt": {"type": "api token", "shape": _masked_receipt(api_token)},
304
- }
305
- exc.hint = (
306
- f"{resolved_base_url} rejected this token for workspace "
307
- f"{effective_workspace}. Credentials are per environment and per workspace: "
308
- "a token issued on one Mammoth server or workspace does not authenticate on "
309
- "another. Check the token, the workspace id, and that --server-prefix "
310
- "matches where it was issued."
311
- )
312
- raise
313
- finally:
314
- service.close()
319
+ effective_workspace = _verify_login(invocation, base_url=resolved_base_url, api_token=api_token)
315
320
 
316
321
  profile_name = invocation.profile or profiles.DEFAULT_PROFILE_NAME
317
322
  profiles.validate_profile_name(profile_name)
@@ -366,8 +371,8 @@ def auth_login(
366
371
  """Log in and store one profile's credentials.
367
372
 
368
373
  Prompts for the API token (mm_..., from Workspace settings -> API Tokens)
369
- and the workspace id in a terminal. For non-interactive use (agents, CI), pass
370
- ``--input FILE`` with {"api_token": ..., "workspace_id": ...} instead.
374
+ in a terminal; the token names its workspace. For non-interactive use
375
+ (agents, CI), pass ``--input FILE`` with {"api_token": ...} instead.
371
376
  Performs a lightweight connection check before saving anything; a failed
372
377
  check leaves existing profile state unchanged.
373
378
  """
@@ -37,6 +37,7 @@ from mammoth_cli.services.listing import (
37
37
  fit_budget,
38
38
  name_hit,
39
39
  search_page,
40
+ source_of,
40
41
  )
41
42
 
42
43
  HandlerResult = tuple[Any, dict[str, Any]]
@@ -142,16 +143,9 @@ def _require_string_positional(invocation: Invocation, name: str) -> str:
142
143
  return str(invocation.extra_args[0])
143
144
 
144
145
 
145
- # The projects endpoint accepts at most limit=100 and exposes no offset, so a
146
- # cross-project search can see at most 100 projects; the result says when the
147
- # list was cut there.
148
- _MAX_PROJECTS_SEARCHED = 100
149
-
150
-
151
146
  def _visible_projects(service: Any) -> list[dict[str, Any]]:
152
- """The projects the credential can see (at most ``_MAX_PROJECTS_SEARCHED``)."""
153
- listing = service.list_projects(limit=_MAX_PROJECTS_SEARCHED)
154
- return list(listing.get("projects", [])) if isinstance(listing, dict) else []
147
+ """Every project the credential is a member of, across all pages."""
148
+ return list(service.list_all_projects())
155
149
 
156
150
 
157
151
  def _find_in_projects(
@@ -163,7 +157,11 @@ def _find_in_projects(
163
157
  project_id = project.get("id")
164
158
  if project_id is None:
165
159
  continue
166
- response = service.call("mammoth.api.datasets.DatasetsAPI.list_all", project_id=project_id)
160
+ response = service.call(
161
+ "mammoth.api.datasets.DatasetsAPI.list_all",
162
+ project_id=project_id,
163
+ fields=DATASET_ROW_FIELDS,
164
+ )
167
165
  datasets = response.get("datasets", []) if isinstance(response, dict) else []
168
166
  for dataset in datasets:
169
167
  name = dataset.get("name") if isinstance(dataset, dict) else None
@@ -173,6 +171,7 @@ def _find_in_projects(
173
171
  "project_id": project_id,
174
172
  "project_name": project.get("name"),
175
173
  **name_hit(dataset),
174
+ "source": source_of(dataset),
176
175
  }
177
176
  )
178
177
  return matches
@@ -231,7 +230,6 @@ def dataset_find(invocation: Invocation) -> HandlerResult:
231
230
  result: dict[str, Any] = {
232
231
  "matches": matches,
233
232
  "projects_searched": len(projects),
234
- "projects_truncated": len(projects) >= _MAX_PROJECTS_SEARCHED,
235
233
  }
236
234
  if note := ambiguity_note(len(matches), name_substring):
237
235
  result["note"] = note
@@ -454,6 +452,33 @@ def dataset_broken_rows(invocation: Invocation) -> HandlerResult:
454
452
  return _read_dataset(invocation)
455
453
 
456
454
 
455
+ def dataset_broken_rows_resolve(invocation: Invocation) -> HandlerResult:
456
+ """Add corrected set-aside lines to a dataset, or discard them. Prompt or ``--yes``.
457
+
458
+ ``--input`` carries ``op`` (``add`` or ``remove``), ``batch_id`` and ``rows``
459
+ (``{"line_num", "line"}`` each, from ``dataset broken-rows list``). Returns a
460
+ job to wait on.
461
+ """
462
+ project_id = require_project(invocation)
463
+ dataset_id = _require_int_positional(invocation, "dataset id")
464
+ document = invocation.load_input()
465
+ kwargs: dict[str, Any] = {
466
+ "dataset_id": dataset_id,
467
+ "op": _require_field(document, "op"),
468
+ "batch_id": _require_field(document, "batch_id"),
469
+ "rows": _require_field(document, "rows"),
470
+ "project_id": project_id,
471
+ }
472
+ enforce_confirmation(
473
+ invocation,
474
+ policy=POLICY_PROMPT_OR_YES,
475
+ action=f"{kwargs['op']} set-aside lines of dataset {dataset_id}",
476
+ )
477
+ with open_service(invocation) as (service, auth):
478
+ data = service.call(_symbol(invocation), **kwargs)
479
+ return data, _meta(invocation, auth.workspace_id, project_id)
480
+
481
+
457
482
  def _read_dataset(invocation: Invocation) -> HandlerResult:
458
483
  """Call this command's SDK read with the DATASET_ID positional."""
459
484
  project_id = require_project(invocation)
@@ -104,12 +104,6 @@ def _require_string_positional(invocation: Invocation, name: str) -> str:
104
104
  return str(invocation.extra_args[0])
105
105
 
106
106
 
107
- # The projects endpoint accepts at most limit=100 and exposes no offset, so a
108
- # cross-project search can see at most 100 projects; the result says when the
109
- # list was cut there.
110
- _MAX_PROJECTS_SEARCHED = 100
111
-
112
-
113
107
  def folder_find(invocation: Invocation) -> HandlerResult:
114
108
  """Search folder names for a substring across every visible project.
115
109
 
@@ -122,8 +116,7 @@ def folder_find(invocation: Invocation) -> HandlerResult:
122
116
  needle = name_substring.lower()
123
117
  matches: list[dict[str, Any]] = []
124
118
  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 []
119
+ visible = list(service.list_all_projects())
127
120
  if invocation.project is not None:
128
121
  projects: list[dict[str, Any]] = [named_project(service, invocation.project, visible)]
129
122
  else:
@@ -157,9 +150,6 @@ def folder_find(invocation: Invocation) -> HandlerResult:
157
150
  return {
158
151
  "matches": matches,
159
152
  "projects_searched": len(projects),
160
- "projects_truncated": (
161
- invocation.project is None and len(projects) >= _MAX_PROJECTS_SEARCHED
162
- ),
163
153
  }, meta
164
154
 
165
155
 
@@ -0,0 +1,89 @@
1
+ """The ``link`` command: local, read-only, turns a pasted Mammoth app URL into ids.
2
+
3
+ A user pastes a link from the web app (``.../workspaces/W/projects/P/data/folders/F
4
+ ?selectedResourceId=R``, a dataset or view editor link, a dashboard link) and asks
5
+ about the item behind it. Every id in the link is already there, so reading it
6
+ needs no server; ``link`` is the one place that knows the app's route shapes, so
7
+ an agent does not guess which number is which.
8
+
9
+ The route shapes mirror the web app's router (mm-frontend ``data-library``,
10
+ ``data-editor``, ``workflows``, ``dashboard`` and ``data-apps`` route files).
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import re
16
+ from typing import Any
17
+ from urllib.parse import parse_qs, urlparse
18
+
19
+ from mammoth_cli.errors.envelope import CODE_INVALID_ARGUMENT, EXIT_USAGE, CliError
20
+ from mammoth_cli.runtime.invocation import Invocation
21
+
22
+ HandlerResult = tuple[Any, dict[str, Any]]
23
+
24
+ #: ``(pattern, field)``: each pattern captures one id out of the URL path.
25
+ _PATH_IDS: tuple[tuple[re.Pattern[str], str], ...] = (
26
+ (re.compile(r"/workspaces/(\d+)(?:/|$)"), "workspace_id"),
27
+ (re.compile(r"/projects/(\d+)(?:/|$)"), "project_id"),
28
+ (re.compile(r"/data/folders/(\d+)(?:/|$)"), "folder_resource_id"),
29
+ (re.compile(r"/datasets/(\d+)(?:/|$)"), "dataset_id"),
30
+ (re.compile(r"/(?:views|dataviews)/(\d+)(?:/|$)"), "view_id"),
31
+ (re.compile(r"/dashboard/(\d+)(?:/|$)"), "dashboard_id"),
32
+ (re.compile(r"/data-apps/(\d+)(?:/|$)"), "data_app_id"),
33
+ (re.compile(r"/workflows/(\d+)(?:/|$)"), "workflow_id"),
34
+ )
35
+
36
+ #: Resource ids differ from dataset/view ids; said whenever the link carries one.
37
+ _RESOURCE_ID_NOTE = (
38
+ "folder_resource_id and selected_resource_id are the web app's resource ids, not "
39
+ "dataset or view ids: never pass them as DATASET_ID or VIEW_ID. Find the item "
40
+ "with 'mammoth dataset find NAME' or 'mammoth dataset list --project PROJECT_ID'."
41
+ )
42
+
43
+
44
+ def _parse_error(url: str) -> CliError:
45
+ return CliError(
46
+ code=CODE_INVALID_ARGUMENT,
47
+ message=f"{url!r} is not a Mammoth app link (no /workspaces/ID in its path).",
48
+ exit_status=EXIT_USAGE,
49
+ hint="Paste the full address from the browser, for example "
50
+ "https://app.mammoth.io/workspaces/1/projects/2/data/datasets.",
51
+ )
52
+
53
+
54
+ def parse_app_link(url: str) -> dict[str, Any]:
55
+ """Ids carried by one Mammoth app URL; absent ones are left out. Pure, no network."""
56
+ parsed = urlparse(url.strip())
57
+ path = parsed.path or ""
58
+ found: dict[str, Any] = {"url": url.strip()}
59
+ for pattern, field in _PATH_IDS:
60
+ match = pattern.search(path)
61
+ if match is not None:
62
+ found[field] = int(match.group(1))
63
+ if "workspace_id" not in found:
64
+ raise _parse_error(url)
65
+ query = parse_qs(parsed.query)
66
+ for key, field in (("selectedResourceId", "selected_resource_id"), ("openSection", "section")):
67
+ if query.get(key):
68
+ value = query[key][0]
69
+ found[field] = int(value) if value.isdigit() else value
70
+ if "folder_resource_id" in found or "selected_resource_id" in found:
71
+ found["note"] = _RESOURCE_ID_NOTE
72
+ return found
73
+
74
+
75
+ def link(invocation: Invocation) -> HandlerResult:
76
+ """Read the workspace, project, folder, dataset and view ids out of a pasted app URL.
77
+
78
+ The sole positional argument is the URL. Returns only the ids the link
79
+ carries; makes no request.
80
+ """
81
+ url = invocation.extra_args[0] if invocation.extra_args else None
82
+ if not url or not url.strip():
83
+ raise CliError(
84
+ code=CODE_INVALID_ARGUMENT,
85
+ message="link requires a Mammoth app URL argument.",
86
+ exit_status=EXIT_USAGE,
87
+ hint="Pass the pasted link in quotes: mammoth link 'https://app.mammoth.io/...'.",
88
+ )
89
+ return parse_app_link(url), {}
@@ -39,6 +39,7 @@ from mammoth_cli.commands import external_key as external_key_cmd
39
39
  from mammoth_cli.commands import file as file_cmd
40
40
  from mammoth_cli.commands import folder as folder_cmd
41
41
  from mammoth_cli.commands import job as job_cmd
42
+ from mammoth_cli.commands import link as link_cmd
42
43
  from mammoth_cli.commands import notification as notification_cmd
43
44
  from mammoth_cli.commands import parameter as parameter_cmd
44
45
  from mammoth_cli.commands import project as project_cmd
@@ -234,6 +235,7 @@ HANDLERS: dict[str, Handler] = {
234
235
  "log.tail": _log_tail,
235
236
  "doctor": doctor_cmd.doctor,
236
237
  "calc": calc_cmd.calc,
238
+ "link": link_cmd.link,
237
239
  "completion.show": completion_cmd.completion_show,
238
240
  "completion.install": completion_cmd.completion_install,
239
241
  "skill.agents-md.install": skill_cmd.skill_agents_md_install,
@@ -322,6 +324,7 @@ HANDLERS: dict[str, Handler] = {
322
324
  "dataset.file-settings.update": dataset_cmd.dataset_file_settings_update,
323
325
  "dataset.file-settings.undo": dataset_cmd.dataset_file_settings_undo,
324
326
  "dataset.broken-rows.list": dataset_cmd.dataset_broken_rows,
327
+ "dataset.broken-rows.resolve": dataset_cmd.dataset_broken_rows_resolve,
325
328
  "dataset.interpretation.preview": dataset_cmd.dataset_interpretation,
326
329
  "dataset.interpretation.confirm": dataset_cmd.dataset_interpretation,
327
330
  "dataset.create": dataset_cmd.dataset_create,
@@ -378,8 +378,24 @@ _COMMAND_DISCOVERY_PURPOSES = {
378
378
  "project.pending-changes": (
379
379
  "source changes new rows not taken in yet pending updates waiting to apply"
380
380
  ),
381
+ # "I pasted a link to a file / dataset / view -- what is wrong with it?" (zulip
382
+ # Mammoth Agents, ws 247): the agent had no way to turn the app address into
383
+ # ids, and the unstructured-rows read said "broken" where users say "unstructured".
384
+ "link": (
385
+ "link url pasted address app page open file dataset view folder project "
386
+ "workspace ids selected resource parse"
387
+ ),
388
+ "dataset.broken-rows.list": (
389
+ "unstructured skipped ragged rows lines unparsed mismatched columns monitor "
390
+ "needs review file upload bad rows"
391
+ ),
392
+ "dataset.broken-rows.resolve": (
393
+ "fix unstructured skipped ragged lines discard correct resolve mismatched "
394
+ "columns review monitor needs review upload"
395
+ ),
381
396
  "project.needs-attention": (
382
- "monitor needs attention error failing pipeline views delete datasets behind list"
397
+ "monitor needs attention error failing pipeline views delete datasets behind list "
398
+ "unstructured pending review"
383
399
  ),
384
400
  "project.resource-status": "stuck stale failing broken error status anything wrong health",
385
401
  "connector.ai.chat": (