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.
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/PKG-INFO +2 -2
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/__init__.py +1 -1
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/app.py +2 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/SKILL.md +25 -23
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/auth.md +14 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/capabilities.md +1 -1
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/command-index.md +2 -1
- mammoth_cli-2.2.40/mammoth_cli/bundled_skill/mammoth-cli/references/commands/token.md +33 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/operations.md +6 -1
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/auth.py +171 -10
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/job.py +30 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/project.py +3 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/registry.py +74 -23
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/view.py +142 -26
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/context/credentials.py +92 -7
- mammoth_cli-2.2.40/mammoth_cli/context/oauth.py +473 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/context/resolver.py +13 -2
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/errors/envelope.py +8 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/output/policy.py +1 -1
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/output/render.py +30 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/dryrun_targets.py +3 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/command_contract.py +3 -0
- mammoth_cli-2.2.40/mammoth_cli/services/job_outcome.py +124 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/listing.py +43 -13
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/mapping.py +28 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/positionals.py +36 -3
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/protocol.py +9 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/read_queries.py +32 -3
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/sdk_service.py +100 -21
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/testing.py +11 -1
- mammoth_cli-2.2.40/mammoth_cli/services/view_analysis.py +92 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/skills/steering.py +2 -1
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/pyproject.toml +2 -2
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/job.yaml +4 -1
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/project.yaml +1 -1
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/schema.yaml +1 -1
- mammoth_cli-2.2.40/spec/manifests/commands/token.yaml +128 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/view.yaml +9 -5
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/edits-target.source.yaml +1 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/sdk-methods.yaml +1 -1
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/.gitignore +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/LICENSE +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/README.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/__main__.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/about-mammoth.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/capabilities-misc.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/activity.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/addon.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/agent.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/ai.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/annotation.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/auth.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/automation.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/batch.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/billing.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/browse.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/calc.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/capability.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/client-app.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/completion.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/config.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/connector.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/context.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard-qa.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard-style.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard-template.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/data-app.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dataset.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/doctor.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/external-key.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/file.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/folder.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/job.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/link.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/log.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/notification.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/parameter.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/project.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/report.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/schedule.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/schema.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/skill.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/snippet.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/support.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/template.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/trash.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/upgrade.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/user.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/version.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/view-transform.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/view.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/webhook.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/workflow.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/workspace.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/handoff.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/input.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/jobs-drafts.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/machine-output.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/auth-scope.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/cleanup.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/dashboards.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/database-import.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/end-to-end.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/exports.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/index.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/need-action.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/resources.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/scheduling.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/transforms.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/typed-etl-discovery.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/recovery.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/report-checklist.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/retention.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/safety.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/task-start.md +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/__init__.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/activity.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/addon.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/agent.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/ai.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/annotation.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/automation.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/batch.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/billing.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/browse.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/calc.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/capability.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/client_app.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/completion.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/config.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/connector.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/context.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/dashboard.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/data_app.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/dataset.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/doctor.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/external_key.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/file.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/folder.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/link.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/notification.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/parameter.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/report.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/schedule.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/schema.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/skill.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/snippet.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/support.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/template.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/trash.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/upgrade.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/user.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/view_ops.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/view_profile.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/webhook.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/workflow.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/commands/workspace.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/context/__init__.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/context/endpoint.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/context/profiles.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/contracts/__init__.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/contracts/auth.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/embed.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/errors/__init__.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/manifest/__init__.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/manifest/loader.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/messages/__init__.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/output/__init__.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/output/envelope.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/output/normalize.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/output/progress.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/py.typed +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/__init__.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/confirm.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/dataset_health.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/dryrun.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/embedded.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/executor.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/input_loader.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/intent_only.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/invocation.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/new_data.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/options.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/parents.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/runlog.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/session.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/state.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/strict.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/updates.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/validate.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/runtime/verify.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/__init__.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/append_blank_columns.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/argspec.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/board_values.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/coerce.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/conditional_format.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/conditions.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/dashboard_filters.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/dashboard_pages.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/dashboard_review.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/data_profile.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/data_quality.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/dispatch.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/factory.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/input_fields.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/local_time.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/openapi_types.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/sql_check.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/stored_stats.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/text_dates.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/type_system.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/services/write_impact.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/skills/__init__.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/skills/installer.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/testing.py +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/activity.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/addon.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/agent.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/ai.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/annotation.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/auth.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/automation.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/batch.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/billing.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/browse.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/calc.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/capability.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/client-app.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/completion.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/config.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/connector.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/context.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/dashboard.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/data-app.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/dataset.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/doctor.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/external-key.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/file.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/folder.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/link.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/log.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/notification.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/parameter.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/report.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/schedule.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/skill.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/snippet.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/support.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/template.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/trash.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/upgrade.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/user.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/version.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/webhook.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/workflow.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/commands/workspace.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/openapi-operations.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/schema-v1.json +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/manifests/sdk-catalog.source.yaml +0 -0
- {mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/spec/openapi/metadata.json +0 -0
- {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.
|
|
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
|
+
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
|
|
@@ -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
|
|
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:
|
|
22
|
-
|
|
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' #
|
|
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
|
-
|
|
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
|
|
61
|
-
`
|
|
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;
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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`).
|
|
107
|
-
|
|
108
|
-
|
|
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 `
|
|
144
|
-
|
|
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`
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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
|
{mammoth_cli-2.2.38 → mammoth_cli-2.2.40}/mammoth_cli/bundled_skill/mammoth-cli/references/auth.md
RENAMED
|
@@ -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
|
|
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
|
|
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.
|
|
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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
|
|
374
|
-
|
|
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
|