@getmagical/cli 0.3.1 → 0.4.0

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.
package/README.md CHANGED
@@ -129,20 +129,25 @@ mgcl --branch-id <branch-id> workbench patch readiness --target-draft-automation
129
129
  Branch creation defaults to main. Use `--source-branch-id` and optionally
130
130
  `--source-version-id` to fork from another branch or an older version in that
131
131
  branch's history. Names must use lowercase letters or numbers separated by
132
- single dashes, such as `release-2`. Spaces, underscores, slashes, backslashes,
133
- punctuation, uppercase letters, leading or trailing dashes, and repeated dashes
134
- are rejected before an API request. Branch IDs, not names, identify targets.
132
+ single dashes, such as `release-2`, and must be 100 characters or fewer.
133
+ Spaces, underscores, slashes, backslashes, punctuation, uppercase letters,
134
+ leading or trailing dashes, repeated dashes, and over-length names are
135
+ rejected before an API request. Branch IDs, not names, identify targets, and
136
+ every automation or branch ID must be a UUID; malformed IDs are rejected
137
+ before an API request.
135
138
  Merge previews the same change set as the web UI. A conflict returns
136
- `status: "conflict"` and does not change main or delete the branch. A
137
- conflict-free merge returns `status: "merged"`, the saved-main result, and
138
- deletes the source branch. Rename, delete, compare, and publish are
139
- intentionally deferred.
139
+ `status: "conflict"`, does not change main or delete the branch, and exits
140
+ nonzero so scripts gating on the exit code never mistake it for an applied
141
+ merge. A conflict-free merge returns `status: "merged"`, the saved-main
142
+ result, and deletes the source branch. Rename, delete, compare, and publish
143
+ are intentionally deferred.
140
144
 
141
145
  The global branch target is accepted by `automations update`, `automations
142
- run-draft`, `workbench diagnostics`, `workbench schema-suggestions`, and
143
- `workbench patch preview`, `readiness`, and `apply`. It is required by
144
- `automations branches get` and `merge`. Other commands reject `--branch-id`
145
- before making an API request. Branch-aware responses identify the selected
146
+ run-draft`, `automations diff-from-published`, `workbench diagnostics`,
147
+ `workbench schema-suggestions`, and `workbench patch preview`, `readiness`,
148
+ and `apply`. It is required by `automations branches get` and `merge`. Other
149
+ commands reject `--branch-id` before making an API request, and
150
+ `mgcl --help` lists the branch-aware commands. Branch-aware responses identify the selected
146
151
  target with `branchId` and `headVersionId`. Merge returns `branchId`, its exact
147
152
  preview and conflicts, plus the new main head as `applyResult.draftVersionId`
148
153
  when successful. Branch inspection excludes workspace authentication records
package/dist/index.js CHANGED
@@ -7764,6 +7764,10 @@ function safeJsonParseWithoutLogging(json) {
7764
7764
  }
7765
7765
  }
7766
7766
 
7767
+ // ../common/dist/src/constants/automation.js
7768
+ var AUTOMATION_BRANCH_NAME_MAX_LENGTH = 100;
7769
+ var AUTOMATION_BRANCH_NAME_MAX_LENGTH_MESSAGE = `Branch name must be ${AUTOMATION_BRANCH_NAME_MAX_LENGTH} characters or fewer.`;
7770
+
7767
7771
  // ../common/dist/src/constants/tool-declarations.js
7768
7772
  import { z as z15 } from "zod";
7769
7773
 
@@ -15336,6 +15340,7 @@ query DiffAgentVersion(
15336
15340
  query GetAgentRun($id: ID!) {
15337
15341
  agentRun(id: $id) {
15338
15342
  id
15343
+ agentId
15339
15344
  agentVersionId
15340
15345
  agentName
15341
15346
  status
@@ -15396,12 +15401,14 @@ query GetAutomationAgents($ids: [ID!]!) {
15396
15401
  operationName: "GetAutomationDiffFromPublished",
15397
15402
  kind: "query",
15398
15403
  inputSchema: z27.object({
15399
- automationId: z27.string().min(1)
15404
+ automationId: z27.uuid("--automation-id must be a UUID."),
15405
+ branchId: z27.uuid("--branch-id must be a UUID.").optional()
15400
15406
  }),
15401
15407
  cli: {
15408
+ branchContext: "optional",
15402
15409
  name: "get-automation-diff-from-published",
15403
15410
  path: ["automations", "diff-from-published"],
15404
- description: "Fetch draft-vs-published automation JSON Patch.",
15411
+ description: "Fetch draft-vs-published automation JSON Patch for main or one branch.",
15405
15412
  resultKey: "automationDiffFromPublished",
15406
15413
  options: [
15407
15414
  stringOption({
@@ -15413,9 +15420,10 @@ query GetAutomationAgents($ids: [ID!]!) {
15413
15420
  ]
15414
15421
  },
15415
15422
  mcp: { fileName: "automationDiffFromPublished.graphql" },
15416
- document: `# Query JSON Patch changes from published automation JSON to draft automation JSON
15417
- query GetAutomationDiffFromPublished($automationId: ID!) {
15418
- automationDiffFromPublished(automationId: $automationId) {
15423
+ document: `# Query JSON Patch changes from published automation JSON to draft automation JSON.
15424
+ # Pass branchId to diff a branch head against published instead of the main draft.
15425
+ query GetAutomationDiffFromPublished($automationId: ID!, $branchId: ID) {
15426
+ automationDiffFromPublished(automationId: $automationId, branchId: $branchId) {
15419
15427
  automationId
15420
15428
  automationName
15421
15429
  mode
@@ -15559,12 +15567,15 @@ query GetAutomationRun($id: ID!) {
15559
15567
  automationRun(id: $id) {
15560
15568
  id
15561
15569
  automationId
15570
+ automationVersionId
15562
15571
  parentAutomationRunId
15563
15572
  status
15564
15573
  statusDetail
15565
15574
  summary
15566
15575
  invocationType
15567
15576
  input
15577
+ initialStore
15578
+ currentStore
15568
15579
  additionalPrompt
15569
15580
  debugUrl
15570
15581
  createdAt
@@ -15599,6 +15610,7 @@ query GetAutomationRun($id: ID!) {
15599
15610
  query GetAutomationRunAgentRuns($automationRunId: ID!) {
15600
15611
  automationRunAgentRuns(automationRunId: $automationRunId) {
15601
15612
  id
15613
+ agentId
15602
15614
  agentVersionId
15603
15615
  agentName
15604
15616
  status
@@ -15618,6 +15630,7 @@ query GetAutomationRunAgentRuns($automationRunId: ID!) {
15618
15630
  automationRunId: z27.string().min(1),
15619
15631
  agentRunId: z27.string().min(1).optional(),
15620
15632
  limit: z27.number().int().positive().optional(),
15633
+ page: z27.number().int().nonnegative().optional(),
15621
15634
  reverse: z27.boolean().optional()
15622
15635
  }),
15623
15636
  cli: {
@@ -15642,6 +15655,11 @@ query GetAutomationRunAgentRuns($automationRunId: ID!) {
15642
15655
  flagName: "limit",
15643
15656
  description: "Maximum number of iterations to return."
15644
15657
  }),
15658
+ numberOption({
15659
+ inputKey: "page",
15660
+ flagName: "page",
15661
+ description: "Zero-based page number."
15662
+ }),
15645
15663
  booleanOption({
15646
15664
  inputKey: "reverse",
15647
15665
  flagName: "reverse",
@@ -15655,18 +15673,21 @@ query GetAutomationRunIterations(
15655
15673
  $automationRunId: ID!
15656
15674
  $agentRunId: ID
15657
15675
  $limit: Int
15676
+ $page: Int
15658
15677
  $reverse: Boolean
15659
15678
  ) {
15660
15679
  automationRunIterations(
15661
15680
  automationRunId: $automationRunId
15662
15681
  agentRunId: $agentRunId
15663
15682
  limit: $limit
15683
+ page: $page
15664
15684
  reverse: $reverse
15665
15685
  ) {
15666
15686
  id
15667
15687
  sequence
15668
15688
  agentRunId
15669
15689
  metadata
15690
+ store
15670
15691
  startedAt
15671
15692
  finishedAt
15672
15693
  totalDurationMs
@@ -15682,6 +15703,42 @@ query GetAutomationRunIterations(
15682
15703
  screenshotMimeType
15683
15704
  }
15684
15705
  }
15706
+ }`
15707
+ }),
15708
+ createOperationSpec({
15709
+ operationName: "GetIterationScreenshot",
15710
+ kind: "query",
15711
+ inputSchema: z27.object({
15712
+ iterationId: z27.string().min(1),
15713
+ hasMarks: z27.boolean().default(false)
15714
+ }),
15715
+ cli: {
15716
+ name: "get-iteration-screenshot",
15717
+ path: ["automation-runs", "iteration-screenshot"],
15718
+ description: "Fetch a fresh screenshot URL for an iteration.",
15719
+ resultKey: "iterationScreenshot",
15720
+ options: [
15721
+ stringOption({
15722
+ inputKey: "iterationId",
15723
+ flagName: "iteration-id",
15724
+ description: "Automation run iteration ID.",
15725
+ required: true
15726
+ }),
15727
+ booleanOption({
15728
+ inputKey: "hasMarks",
15729
+ flagName: "with-marks",
15730
+ description: "Fetch the marked screenshot instead of the base screenshot."
15731
+ })
15732
+ ]
15733
+ },
15734
+ mcp: { fileName: "iterationScreenshot.graphql" },
15735
+ document: `# Fetch a fresh screenshot URL for an automation run iteration
15736
+ query GetIterationScreenshot($iterationId: ID!, $hasMarks: Boolean = false) {
15737
+ iterationScreenshot(iterationId: $iterationId, hasMarks: $hasMarks) {
15738
+ status
15739
+ url
15740
+ mimeType
15741
+ }
15685
15742
  }`
15686
15743
  }),
15687
15744
  createOperationSpec({
@@ -15770,6 +15827,7 @@ query GetAutomationRuns(
15770
15827
  ) {
15771
15828
  id
15772
15829
  automationId
15830
+ automationVersionId
15773
15831
  parentAutomationRunId
15774
15832
  status
15775
15833
  statusDetail
@@ -15818,6 +15876,7 @@ query GetAutomationRunsPage(
15818
15876
  items {
15819
15877
  id
15820
15878
  automationId
15879
+ automationVersionId
15821
15880
  parentAutomationRunId
15822
15881
  status
15823
15882
  statusDetail
@@ -15975,7 +16034,7 @@ query ViewAutomationReview($automationId: ID!) {
15975
16034
  operationName: "ListAutomationBranches",
15976
16035
  kind: "query",
15977
16036
  inputSchema: z27.object({
15978
- automationId: z27.string().min(1)
16037
+ automationId: z27.uuid("--automation-id must be a UUID.")
15979
16038
  }),
15980
16039
  cli: {
15981
16040
  name: "list-automation-branches",
@@ -16010,10 +16069,13 @@ query ListAutomationBranches($automationId: ID!) {
16010
16069
  operationName: "CreateAutomationBranch",
16011
16070
  kind: "mutation",
16012
16071
  inputSchema: z27.object({
16013
- automationId: z27.string().min(1),
16014
- name: z27.string().regex(AUTOMATION_BRANCH_NAME_PATTERN, AUTOMATION_BRANCH_NAME_MESSAGE),
16015
- sourceBranchId: z27.string().min(1).optional(),
16016
- sourceVersionId: z27.string().min(1).optional()
16072
+ automationId: z27.uuid("--automation-id must be a UUID."),
16073
+ name: z27.string().regex(AUTOMATION_BRANCH_NAME_PATTERN, AUTOMATION_BRANCH_NAME_MESSAGE).max(
16074
+ AUTOMATION_BRANCH_NAME_MAX_LENGTH,
16075
+ AUTOMATION_BRANCH_NAME_MAX_LENGTH_MESSAGE
16076
+ ),
16077
+ sourceBranchId: z27.uuid("--source-branch-id must be a UUID.").optional(),
16078
+ sourceVersionId: z27.uuid("--source-version-id must be a UUID.").optional()
16017
16079
  }),
16018
16080
  cli: {
16019
16081
  name: "create-automation-branch",
@@ -16074,8 +16136,8 @@ mutation CreateAutomationBranch(
16074
16136
  operationName: "GetAutomationBranch",
16075
16137
  kind: "query",
16076
16138
  inputSchema: z27.object({
16077
- automationId: z27.string().min(1),
16078
- branchId: z27.string().min(1)
16139
+ automationId: z27.uuid("--automation-id must be a UUID."),
16140
+ branchId: z27.uuid("--branch-id must be a UUID.")
16079
16141
  }),
16080
16142
  cli: {
16081
16143
  branchContext: "required",
@@ -16106,14 +16168,14 @@ query GetAutomationBranch($automationId: ID!, $branchId: ID!) {
16106
16168
  operationName: "MergeAutomationBranch",
16107
16169
  kind: "mutation",
16108
16170
  inputSchema: z27.object({
16109
- automationId: z27.string().min(1),
16110
- branchId: z27.string().min(1)
16171
+ automationId: z27.uuid("--automation-id must be a UUID."),
16172
+ branchId: z27.uuid("--branch-id must be a UUID.")
16111
16173
  }),
16112
16174
  cli: {
16113
16175
  branchContext: "required",
16114
16176
  name: "merge-automation-branch",
16115
16177
  path: ["automations", "branches", "merge"],
16116
- description: "Preview and merge a branch into main when every change is conflict-free.",
16178
+ description: "Preview and merge a branch into main when every change is conflict-free. Exits nonzero when conflicts block the merge.",
16117
16179
  resultKey: "mergeAutomationBranch",
16118
16180
  options: [
16119
16181
  stringOption({
@@ -18586,7 +18648,7 @@ var pathwayRegressionAgentVersionRegressionRunResponseSchema = z28.object({
18586
18648
  automationVersionId: z28.string().min(1),
18587
18649
  baselineAgentVersionId: z28.string().min(1),
18588
18650
  baselineAutomationVersionId: z28.string().min(1),
18589
- baselineContractId: z28.string().min(1),
18651
+ baselineContractId: z28.string().min(1).nullable(),
18590
18652
  candidateContractId: z28.string().min(1),
18591
18653
  contractId: z28.string().min(1),
18592
18654
  paths: z28.array(pathwayRegressionAgentVersionRunPathSchema),
@@ -19464,6 +19526,32 @@ function configureCommandPresentation(command) {
19464
19526
  command.createHelp = () => new MagicalHelp();
19465
19527
  return command;
19466
19528
  }
19529
+ function formatBranchAwareCommandsHelp() {
19530
+ const branchAwareCommandLines = operationSpecs.flatMap((operationSpec) => {
19531
+ const { branchContext } = operationSpec.cli;
19532
+ if (branchContext === void 0) {
19533
+ return [];
19534
+ }
19535
+ return [
19536
+ `mgcl ${operationSpec.cli.path.join(" ")} (--branch-id ${branchContext})`
19537
+ ];
19538
+ }).toSorted();
19539
+ return formatExamples("Branch-aware commands", branchAwareCommandLines);
19540
+ }
19541
+ function formatRootAfterHelpText() {
19542
+ return `
19543
+ ${formatExamples("Quick start", [
19544
+ "mgcl auth login",
19545
+ "mgcl org list",
19546
+ "mgcl automations list --limit 10",
19547
+ "mgcl automation-runs get --id <run-id>",
19548
+ "mgcl update"
19549
+ ])}
19550
+
19551
+ ${formatBranchAwareCommandsHelp()}
19552
+
19553
+ ${formatOutputModesNote()}`;
19554
+ }
19467
19555
  function createOperationHelpExamples(operationSpec) {
19468
19556
  const commandPath = operationSpec.cli.path.join(" ");
19469
19557
  const baseCommand = operationSpec.cli.branchContext === "required" ? `mgcl --branch-id <branch-id> ${commandPath}` : `mgcl ${commandPath}`;
@@ -21903,6 +21991,7 @@ async function handleOperationCommand(dependencies, operationSpec, commandOption
21903
21991
  json: commandOptions.json,
21904
21992
  result
21905
21993
  });
21994
+ assertBranchMergeApplied(operationSpec, result);
21906
21995
  if (operationSpec.operationName === "ViewAutomationReview" && commandOptions["open"] && isRecord5(result) && typeof result["reportUrl"] === "string") {
21907
21996
  await dependencies.openExternalUrl(result["reportUrl"]).catch((error) => {
21908
21997
  dependencies.io.error(
@@ -21911,6 +22000,13 @@ async function handleOperationCommand(dependencies, operationSpec, commandOption
21911
22000
  });
21912
22001
  }
21913
22002
  }
22003
+ function assertBranchMergeApplied(operationSpec, result) {
22004
+ if (operationSpec.operationName === "MergeAutomationBranch" && (!isRecord5(result) || result["status"] !== "merged")) {
22005
+ throw new CliError(
22006
+ "Merge not applied. Review the merge output, resolve any conflicts, then merge again."
22007
+ );
22008
+ }
22009
+ }
21914
22010
  function getOperation(operationName) {
21915
22011
  const operationSpec = operationSpecs.find(
21916
22012
  (candidate) => candidate.operationName === operationName
@@ -22898,26 +22994,14 @@ function buildProgram(dependencies) {
22898
22994
  ).addOption(new Option3("--json", "Render JSON output.")).addOption(
22899
22995
  new Option3(
22900
22996
  "--branch-id <id>",
22901
- "Target a supported automation command at one branch; omit it to target main."
22997
+ 'Target a supported automation command at one branch; omit it to target main. "Branch-aware commands" below lists the commands that accept it.'
22902
22998
  )
22903
22999
  ).version(CLI_VERSION, "--version", `Display mgcl version (${CLI_VERSION}).`).addOption(
22904
23000
  new Option3(
22905
23001
  "--update",
22906
23002
  "Update mgcl to the latest published npm release."
22907
23003
  )
22908
- ).showHelpAfterError().showSuggestionAfterError().addHelpText(
22909
- "after",
22910
- `
22911
- ${formatExamples("Quick start", [
22912
- "mgcl auth login",
22913
- "mgcl org list",
22914
- "mgcl automations list --limit 10",
22915
- "mgcl automation-runs get --id <run-id>",
22916
- "mgcl update"
22917
- ])}
22918
-
22919
- ${formatOutputModesNote()}`
22920
- );
23004
+ ).showHelpAfterError().showSuggestionAfterError().addHelpText("after", formatRootAfterHelpText());
22921
23005
  program2.hook("preAction", (_thisCommand, actionCommand) => {
22922
23006
  const options = actionCommand.optsWithGlobals();
22923
23007
  const branchContext = commandBranchContexts.get(actionCommand);